Tuesday, September 24, 2013

Math, for fun!

My recent attempts at programming have inspired me to try to get better at it. This is by no means new, but I've been working at solving the problems in Project Euler. It's a collection of math problems which you typically have to write some sort of program to solve. After you complete a problem you get access to a forum where people are discussing the problem. In the ones I've seen so far, there's a bunch of people discussing various ways to code the problem and some math genius who solved it just with math theorems. I'm up to problem 5.

Thursday, September 19, 2013

Revisiting Photo Prep for Digital Frames

Previously, I made a Matlab script that  automatically detected the faces in a photo then cropped and resized the photo centered around the faces. Portrait photos were formatted for an 800x600 frame and landscape photos were formatted for a 1920x1080 frame. The script also had the option to disable face detection and use the center of the uncropped image as the center of the center point. I had about 700 photos I wanted to process so I ran the script both with and without face detection enabled. About 70% of the images looked ok with the face detected results, 15% with the image centered results, and 15% with neither.

All in all, however, manually picking out the images from the face-detected and image-centered sets was more work than I wanted to do. There's probably a better process I could come up with, maybe a script that shows both images and lets you pick one, but I don't think I'll ever process that many images in a single time again. The question is what do I do about the 100 or so photos that I have to crop and resize by hand. My solution is the following Matlab script. It borrows heavily from the face-detection version but instead of running the face-detection scheme the user selects a point manually. It took about a minute to process approximately 100 images. I suspect I will just use this version in the future.

% Manually selects central point to crop images for frames
%
% Last modified: 09/10/13
% Aaron Potter

clear all
close all

% set input and output subdirectories
InDir = 'Input';                             % Input subdirectory name
OutDir = 'Output';                           % Output subdirectory name
FilePattern = fullfile(InDir, '*.jpg');
jpgFiles = dir(FilePattern);

% load an example image (single file mode
%File = uigetfile('*.jpg');              % Returns file name as a string 
%InImage = imread(File);                % Reads image file into variable
%img = rgb2gray(InImage);               % Converts to grayscale

for k=1:length(jpgFiles)

% Read in image file
%
% file = 'test.jpg'                     % test file (skips file selection)
% InImage = imread(file);               % Reads test image file into variable

    BaseFileName = jpgFiles(k).name;
    File = fullfile(InDir,BaseFileName);
    InImage = imread(File);                 % Reads image file into variable
    img = rgb2gray(InImage);               % Converts to grayscale

% Determine if image file is Portrait or Landscape
%
% Height = InSize(1,1);
% Width = InSize(1,2);

    InSize = size(img);
    if InSize(1,1) > InSize(1,2)
        InType = 1;                         % Portrait
    elseif InSize(1,1) < InSize(1,2)
        InType = 2;                         % Landscape
    else
        InType = 3;                         % Square
    end

% display the image
imagesc(img)
colormap gray
axis image
axis off

% select point in image
CenterPoint = ginput(1);
close

% testing
%
% display(CenterPoint);
 
% Scale photos depending on type
%
% Portrait photos to 800 width
% Landscape photos to 1920 width
% square photos to 800 width
% crop rectangle defined as [xmin ymin width height]
            if InType==1                                        % Portrait
                OutImage = imresize(InImage, [NaN 800]);
                ScaleFactor = InSize(1,2)/800;
                ScaledHeight = InSize(1,1)/ScaleFactor;
                ScaledCenter = round(CenterPoint/ScaleFactor);
                % shift crop region if cropped region using faces center 
                % would extend past the edge of the image (i.e. images
                % would be too small
                Offset = ScaledHeight-(ScaledCenter(1,2)+300);
                 if ScaledCenter(1,2)+300 > ScaledHeight
                     CropRect = [0 ScaledCenter(1,2)-300+Offset 800 599];
                     %display('option1');
                 elseif ScaledCenter(1,2)-300 < 0
                     CropRect = [0 ScaledCenter(1,2)-300+Offset 800 599];
                     %display('option2');
                 else
                     CropRect = [0 ScaledCenter(1,2)-300 800 599];
                     %display('option3');
                end                
            elseif InType==2                                     % Landscape
                OutImage = imresize(InImage, [NaN 1920]);
                ScaleFactor = InSize(1,2)/1920;
                ScaledHeight = InSize(1,1)/ScaleFactor;
                ScaledCenter = round(CenterPoint/ScaleFactor);
                % shift crop region if cropped region using faces center 
                % would extend past the edge of the image (i.e. images
                % would be too small
                Offset = ScaledHeight-(ScaledCenter(1,2)+540);         
                 if ScaledCenter(1,2)+540 > ScaledHeight
                     CropRect = [0 ScaledCenter(1,2)-540+Offset 1920 1079];
                     %display('option1');
                 elseif ScaledCenter(1,2)-540 < 0
                     CropRect = [0 ScaledCenter(1,2)-540+Offset 1920 1079];
                     %display('option2');
                 else
                     CropRect = [0 ScaledCenter(1,2)-540 1920 1079];
                     %display('option3');
                end
            elseif InType==3                                     % Square
                OutImage = imresize(InImage, [800 800]);
                ScaleFactor = InSize(1,2)/800;
                ScaledHeight = InSize(1,1)/ScaleFactor;
                ScaledCenter = round(CenterPoint/ScaleFactor);
                CropRect = [0 ScaledCenter(1,2)-300 800 600];
                % shift crop region if cropped region using faces center 
                % would extend past the edge of the image (i.e. images
                % would be too small
                Offset = ScaledHeight-(ScaledCenter(1,2)+300);
                  if ScaledCenter(1,2)+300 > ScaledHeight
                     CropRect = [0 ScaledCenter(1,2)-300+Offset 800 599];
                     %display('option1');
                 elseif ScaledCenter(1,2)-300 < 0
                     CropRect = [0 ScaledCenter(1,2)-300+Offset 800 599];
                     %display('option2');
                 else
                     CropRect = [0 ScaledCenter(1,2)-300 800 599];
                     %display('option3');
                end 
            end

% Write resized image to file in output subdirectory
    CropImage = imcrop(OutImage,CropRect);
    InFilename = strtok(File,'.');
    OutFilename = strcat(InFilename,'_f.jpg');
    FullOutFilename = strrep(OutFilename, InDir, OutDir);
    imwrite(CropImage,FullOutFilename,'jpg');           
               
end

Wednesday, September 11, 2013

Audiophile Raspberry Pi

Lifehacker has a post on a audiophile Raspberry Pi distribution. I'm hardly an audiophile but this might be a good way to add audio nodes, possibly of better quality to my Airplay based whole house audio system. The key would be to integrate RAOP, which is reverse engineered Airplay. The same Lifehacker author has an earlier post on using Raspberry pi as an Airplay receiver, but it looks like it's based around XBMC. As is, I'm not sure how well it will work headless.

Another option might be a TP-LINK TL-WR703N Router based solution. It looks like it is possible to add the OpenWRT based firmware with Airplay implemented either yourself, for as a commenter mentioned, an already built system is available for sale for about half the price of a new Airport Express.

Update (9/11/13): A commenter on the Lifehacker post says the RaspyFi distro supports Airplay out of the box. I didn't see any documentation that supports this, but the RaspyFi forum seems to suggest this is true.