I tested the program in Matlab 2012b (32bit) in Windows. It requires the fdlibmex library for face detection, which should go in the same directory as the Matlab *.m file. As written the program looks for jpg photo files in the Input subdirectory and writes the output files to the Output subdirectory.
Update (8/28/13):
Fixed several bugs and tested on a larger sample size.
- Images without faces detected are processed, the code crops the middle section of the image.
- The code now checks that cropped region won't exceed the size of the image, resulting in a cropped image that is too small. There is also an option to disable face detection altogether.
% Sorts photos by portrait/landscape then crops centered on faces % % Last modified: 08/28/13 % Aaron Potter clear all close all InDir = 'Input'; % Input subdirectory name OutDir = 'Output'; % Output subdirectory name FilePattern = fullfile(InDir, '*.jpg'); jpgFiles = dir(FilePattern); FaceCheck = '0'; % 1/0 for enable/disable face checking 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 % Determine if image file is Portrait or Landscape % % Height = InSize(1,1); % Width = InSize(1,2); InSize = size(InImage); 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 % Find Faces % % Returns a vector with the x-position, y-position, and size as a square if FaceCheck == 1 GrayImage = rgb2gray(InImage); % Converts to grayscale, required by face search function Pos = fdlibmex(GrayImage); % Performs face search NumFaces = length(Pos(:,1)); % Number of faces found else NumFaces = 0; end if NumFaces > 0 % Proceed if there faces are detected % Reject faces smaller than a limit. % 'fdlibmex' detects faces as small as 15 x 15 pixels Limit = 120; % Cut-off limit in pixels (default 120) OverLimitFaces = 0; % Index for over limit face count for i = 1:NumFaces if Pos(i,3) > Limit % Column 3 is the face sizes OverLimitFaces = OverLimitFaces + 1; end end if OverLimitFaces > 0 % Proceed if there are faces over limit BigFace = zeros(OverLimitFaces,3); % Set size of positon matrix of faces over limit n = 1; % Index for cycling through face matrix rows for i = 1:NumFaces if Pos(i,3) > 100 BigFace(n,:) = Pos(i,:); n = n + 1; end end clear n % Find center point between all the faces CenterPoint = zeros(1,2); CenterPoint(1) = round(sum(BigFace(:,1))/OverLimitFaces); % X-coordinate CenterPoint(2) = round(sum(BigFace(:,2))/OverLimitFaces); % Y-coordinate % 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 %CropImage = imcrop(OutImage,CropRect); % Testing %CropImage = OutImage; %display(File); %display(InSize(1,1)); %display(CenterPoint); %display(ScaleFactor); %display(ScaledCenter); %display(ScaledHeight); %display(Offset); %display(CropRect); %clear OutImage %clear InImage else %Scale/crop photos without over-limit faces detected if InType==1 % Portrait Edge = round(InSize(1,2)/(800*4)); OutImage = imresize(InImage, [NaN 800]); CropRect = [0 Edge 800 599]; elseif InType==2 % Landscape Edge = round(InSize(1,2)/(1920*4)); OutImage = imresize(InImage, [NaN 1920]); CropRect = [0 Edge 1920 1079]; elseif InType==3 % Square Edge = round(InSize(1,2)/(800*4)); OutImage = imresize(InImage, [800 800]); CropRect = [0 Edge 800 599]; end end else %Scale/crop photos faces detected if InType==1 % Portrait Edge = round(InSize(1,2)/(800*4)); OutImage = imresize(InImage, [NaN 800]); CropRect = [0 Edge 800 599]; elseif InType==2 % Landscape Edge = round(InSize(1,2)/(1920*4)); OutImage = imresize(InImage, [NaN 1920]); CropRect = [0 Edge 1920 1079]; elseif InType==3 % Square Edge = round(InSize(1,2)/(800*4)); OutImage = imresize(InImage, [800 800]); CropRect = [0 Edge 800 599]; end end %clear OutImage %clear InImage % 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'); % Disable for testing end
No comments:
Post a Comment