Saturday, July 28, 2012

SVM Tutorial, HOG based Face Detection using SVM-Light in Matlab



This tutorial will show you how to use SVM-Light [1] for Object detection (face, car, person or any other object recognition) in Matlab.  Particularly, it will implement a very basic Face Detector just to give you a bit of intuition about how these things work. I have uploaded the source code of this tutorial here, which is well commented and quite self explanatory. It shouldn’t be hard to understand and modify it for any other object detection. All you have to do is to follow the step in Section 2 to and make it work on your system. Section 1 is the detailed explanation of the algorithm.

Section 1
Algorithm Overview

There are two key factors involved in object detection: (1) to choose an efficient feature descriptor, (2) selection of proper classifier. I choose HOG [3] and off course SVM for this tutorial. The approach is quite straightforward; to train a support vector machine you need some positive (face) and some negative (non face) labeled examples. For each training example, extract features from each image and train a SVM to differentiate between the two classes. For detection, scan the test image in sliding window fashion. For each window extract features and run the classifier to determine whether or not there is a face at that location.

Training:

There are 322 images originally and their flipped version, so total of 644 positive (face) examples and the same way 2572 negative (non face) examples in the training dataset. To train the SVM you will need to extract feature from both positive and negative examples and label them as 1 for positive and -1 for negative examples in case of SVM-Light, and if you want binary classification then labels should be 1 and 0 respectively. Below is the example code.

if exist('model.mat','file')
    load model;
else
    [fpos, fneg] = features(pathPos, pathNeg);  % extract features
    [ model ] = trainSVM( fpos,fneg );          % train SVM
    save model model;
end

function [fpos, fneg] = features(pathPos,pathNeg)
% extract features for positive examples
imlist = dir([pathPos '*.png']);
for i = 1:length(imlist)
    im = imread([pathPos imlist(i).name]);
    fpos{i} = HOG(double(im));
end
% extract features for negative examples
imlist = dir([pathNeg '*.png']);
for i = 1:length(imlist)
    im = imread([pathNeg imlist(i).name]);
    fneg{i} = HOG(double(im));
end

end

function [ model ] = trainSVM( fpos,fneg )
SV = loadingV(fpos,fneg);   % loading and labeling each training example
fprintf('Training SVM..\n');
T = cell2mat(SV(2,:));
tP = SV(3,:)';
P = cell2mat(tP); % each row of P correspond to a training example
model = svmlearn(P, T', '-t -g 0.3 -c 0.5');
fprintf('done. \n');
end


Testing:

Here is the example code for detection.

function detect(im,model,wSize)
%{
this function will take three parameters
    1.  im      --> Test Image
    2.  model   --> trained model
    3.  wStize  --> Size of the window, i.e. [24,32]
and draw rectangle on best estimated window
%}

topLeftRow = 1;
topLeftCol = 1;
[bottomRightCol bottomRightRow d] = size(im);

fcount = 1;

% this for loop scan the entire image and extract features for each sliding window
for y = topLeftCol:bottomRightCol-wSize(2)   
    for x = topLeftRow:bottomRightRow-wSize(1)
        p1 = [x,y];
        p2 = [x+(wSize(1)-1), y+(wSize(2)-1)];
        po = [p1; p2];
        img = imcut(po,im);     
        featureVector{fcount} = HOG(double(img));
        boxPoint{fcount} = [x,y];
        fcount = fcount+1;
        x = x+1;
    end
end

lebel = ones(length(featureVector),1);
P = cell2mat(featureVector);
% each row of P' correspond to a window
[~, predictions] = svmclassify(P',lebel,model); % classifying each window

[a, indx]= max(predictions);
bBox = cell2mat(boxPoint(indx));
rectangle('Position',[bBox(1),bBox(2),24,32],'LineWidth',1, 'EdgeColor','r');
end


Section 2

To compile this library in Matlab you will need a C compiler and Mex function. So, let’s start with setting up Mex.

1.      Setting up Mex

If you have done this already, skip this part. Setting up Mex is very easy; all you have to do is to
  • Get and install a Matlab supported compiler.
  • Type mex -setup in Matlab’s command window press enter and then to locate compiler enter ‘y’, to select Compiler enter its number. Similar as in the figure below.



Note: The list of compilers shown on your system might be different from the list shown in this example. The path names to your compilers might also be different.  To read more about Mex click here and here 

2.      Download and extract the source code of this tutorial from here, set it to current working directory in matlab.
3.      Download SVM-Light from here
4.      Extract it into current working directory


5.      Add following paths to main file, demo.m in our case.

addpath './svm_mex601/matlab';
addpath './svm_mex601/bin';

6.      The library is precompiled; all binary files can be found in the ‘bin’ folder. Sometimes they work just fine but sometimes they cause problems, maybe due to compatibility and architectural issues. To compile them run compilemex()after adding the above paths.  compilemex.m  is located in the directory ‘matlab’ and resulting binary files should be stored in ‘bin’ directory. If compilemex fails then you would need to edit compilemex.m  as follows.

At line number 4 replace ‘cd bin’ to ‘cd svm_mex601/bin’ and add one more ‘cd ..’ after line 18 to point back to current working directory. As shown in the figure below



To run the compilemex insert break point after addpath lines as shown in the figure below, press F5 or click on the run button and when debugger stops at the break point run compilemex() through command window.





This might show some warning but don’t worry everything will work fine, if it is compiled successfully.

7.      Run mex HoG.cpp [2] through command window to compile the HoG.cpp file.


That’s it, everything is now ready to run this face detection code. To do so run the demo.m, this will read an image and determine whether or not there is a face in that image.


Results:











References
[3] N. Dalal, and B. Triggs. Histograms of Oriented Gradients for Human Detection. In Proc. CVPR, 2005.