matlabimage-processingcomputer-visionface-detectioncascade-classifier

How to straighten a tilted face after cropping?


I'm doing a project on facial feature extraction. I have written MATLAB code for histogram equalization, face detection and face cropping. Now I want to straighten the face if it is tilted. Can you help me with the MATLAB code? Here is the code I have written so far.

clear all
clc

I=imread('100_3082.jpg');
figure(1)
imshow(I);
J=rgb2gray(I);
figure(2)
imshow(J);                                                             
P = histeq(J);
figure(3)
imshow(P);

FDetect = vision.CascadeObjectDetector;

BB = step(FDetect,P);
hold on
for i = 1:size(BB,1)
rectangle('Position',BB(i,:),'LineWidth',5,'LineStyle','-','EdgeColor','r');

end
for i = 1:size(BB,1)
Q= imcrop(P,BB(i,:));
figure(4)
imshow(Q);
end
title('Face Detection');   

hold off;

This is the image ('100_3082.jpg') I'm working on:-

100_3082.jpg


Solution

  • Algorithm:-
    My solution implements your task using the following algorithm:

    1. Finding the position of both eyes.
    2. Finding the angle between them.
    3. Rotating the image based on that angle.

    Input Image:-
    Input image of this code is the one you're getting at the end of your code i.e. Q.

    input

    Code:-

    % Dividing the image in two halves for better detection
    % To see why , see this: https://www.mathworks.com/matlabcentral/answers/155126-how-does-the-vision-cascadeobjectdetector-detect-left-and-right-eyes-separately-it-is-constantly-de
    n = fix(size(Q,2)/2);
    lefthalf = Q(:,1:n,:);
    righthalf = Q(:,n+1:end,:);
    
    RightEyeDetect = vision.CascadeObjectDetector('RightEyeCART');
    LeftEyeDetect = vision.CascadeObjectDetector('LeftEyeCART');
    % vision.CascadeObjectDetector(EyePairBig) is not much efficient in this case
    % because the image is tilted. So, detecting both eyes separately.
    
    %Bounding Boxes
    BBREye= step(RightEyeDetect,lefthalf); %Right eye is on our left
    BBLEye= step(LeftEyeDetect,righthalf); %Left eye is on our right
    BBLEye(1)=BBLEye(1)+n; %correcting the x position of left eye (caused due to dividing the image in two halves)
    
    figure
    imshow(imrotate(Q,(180/pi)*atan((BBREye(2)-BBLEye(2))/(BBREye(1)-BBLEye(1)))));
    

    Output:-

    Output


    P.S:
    1. This may not be a perfect solution.
    2. It is assumed that there is only one tilted face to be corrected.
    3. The accuracy of this solution is dependent on the accuracy of detection of eyes for which the built-in MATLAB functions, which are based on Viola-Jones Algorithm, are used.
    4. In case if this code fails, you can check whether the eyes were correctly detected or not by adding these lines:

    BBEyes= [BBLEye ; BBREye];
    figure,
    imshow(Q); 
    for i = 1:size(BBEyes,1)
     rectangle('Position',BBEyes(i,:),'LineWidth',4,'LineStyle','-','EdgeColor','r');
    end
    

    For your image, since this worked, you can still check whether the eyes were correctly detected or not. The result is the following which is correct:-

    eyes detection