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

No comments:

Post a Comment