Thursday, October 22, 2009

Object Detection using opencv II - Calculation of Hog Features

This is follow up post to an earlier post where I have described how an integral histogram can be obtained from an image for fast calculation of hog features. Here I am posting the code for how this integral histogram can be used to calculate the hog feature vectors for an image window. I have commented the code for easier understanding of how it works :



/* This function takes in a block as a rectangle and
calculates the hog features for the block by dividing
it into cells of size cell(the supplied parameter),
calculating the hog features for each cell using the
function calculateHOG_rect(...), concatenating the so
obtained vectors for each cell and then normalizing over
the concatenated vector to obtain the hog features for a
block */ 

void calculateHOG_block(CvRect block, CvMat* hog_block, 
IplImage** integrals,CvSize cell, int normalization) 
{
int cell_start_x, cell_start_y;
CvMat vector_cell;
int startcol = 0;
for (cell_start_y = block.y; cell_start_y <= 
block.y + block.height - cell.height; 
cell_start_y += cell.height) 
{
for (cell_start_x = block.x; cell_start_x <= 
block.x + block.width - cell.width; 
cell_start_x += cell.width) 
{
cvGetCols(hog_block, &vector_cell, startcol, 
startcol + 9);

calculateHOG_rect(cvRect(cell_start_x,
cell_start_y, cell.width, cell.height), 
&vector_cell, integrals, -1);

startcol += 9;
}
}
if (normalization != -1)
cvNormalize(hog_block, hog_block, 1, 0, 
normalization);
}

/* This function takes in a window(64x128 pixels,
but can be easily modified for other window sizes)
and calculates the hog features for the window. It
can be used to calculate the feature vector for a 
64x128 pixel image as well. This window/image is the
training/detection window which is used for training
or on which the final detection is done. The hog
features are computed by dividing the window into
overlapping blocks, calculating the hog vectors for
each block using calculateHOG_block(...) and
concatenating the so obtained vectors to obtain the
hog feature vector for the window*/

CvMat* calculateHOG_window(IplImage** integrals,
CvRect window, int normalization) 
{

/*A cell size of 8x8 pixels is considered and each
block is divided into 2x2 such cells (i.e. the block
is 16x16 pixels). So a 64x128 pixels window would be
divided into 7x15 overlapping blocks*/ 

int block_start_x, block_start_y, cell_width = 8;
int cell_height = 8;
int block_width = 2, block_height = 2;

/* The length of the feature vector for a cell is
9(since no. of bins is 9), for block it would  be
9*(no. of cells in the block) = 9*4 = 36. And the
length of the feature vector for a window would be
36*(no. of blocks in the window */

CvMat* window_feature_vector = cvCreateMat(1,
((((window.width - cell_width * block_width)
/ cell_width) + 1) * (((window.height -
cell_height * block_height) / cell_height)
+ 1)) * 36, CV_32FC1);

CvMat vector_block;
int startcol = 0;
for (block_start_y = window.y; block_start_y
<= window.y + window.height - cell_height
* block_height; block_start_y += cell_height)
{
for (block_start_x = window.x; block_start_x
<= window.x + window.width - cell_width
* block_width; block_start_x += cell_width)
{
cvGetCols(window_feature_vector, &vector_block,
startcol, startcol + 36);

calculateHOG_block(cvRect(block_start_x,
block_start_y, cell_width * block_width, cell_height
* block_height), &vector_block, integrals, cvSize(
cell_width, cell_height), normalization);

startcol += 36;
}
}
return (window_feature_vector);
}




I will very soon post how a support vector machine (svm) can trained using the above functions for an object using a dataset and how the learned model can be used to detect the corresponding object in an image.

21 comments:

  1. The first part in this series can be viewed here

    ReplyDelete
  2. Thank you so much !!!

    ReplyDelete
  3. The follow up to this post can be viewed here

    ReplyDelete
  4. Great great great job. It helps me a lot. thx.^_^

    ReplyDelete
  5. When the program calls the "calculateWeightedHOG_block_integral" function in the last part, are you meaning the "calculateHOG_Block" function?

    ReplyDelete
  6. Yes, it calls calculateHOG_Block. Thank you very much for pointing out the mistake. I'll correct it

    ReplyDelete
  7. Hi, I like to detect human body in video surveillance, So is it possible to use haar-like feature for background subtracted object, that means after background subtraction we get human in white pixels. So is it possible to detect that object?

    ReplyDelete
  8. Hi,

    Thank you for sharing your code. I just finished a HoG implementation and then found your code, so I could have saved me some work :).
    Just one comment, and one question:
    The comment: weighting each block with a Gaussian window (like in SIFT) could improve results.
    The question: I implemented HoG this way:
    - Determine histogram bins for each pixel (like you)
    - Now I divide the whole image into cells. For each cell I calculate the histogram and normalize it and store it in a new "image" ImgB
    - Then I continue very much like you, so I basically run a window over the the complete image; the window is seperated in overlapping blocks which are based on the already normalized histograms in ImgB.

    I think this would be a speed improvement for you, or do I get something wrong?
    Greeting,
    Harald

    ReplyDelete
  9. can your code detect a ball?????

    ReplyDelete
  10. Hi, thanks so much for the great code example. I was able to successfully get the integrals back from IplImage** integralsReturned = calculateIntegralHOG(img); as a variable called (obviously) integralsReturned. If I am following correctly, the next step would be to call calculateHOG_window. The issue I am having is with the cvRect param in this function. It seems it would be a section of the image, but it is only a cvRect, so that won't work. I'm definitely missing something that should be obvious, but I am totally stuck and any help would be very appreciate. -Scott

    ReplyDelete
  11. I use the source to detect people based on omega-shaped. I use svm to train for the dataset include negative and positive dataset. After that, I input the feature vector for a 64x128 detection window in the positive dataset. Then I use svm to predict and the output is 2. can you tell me what's wrong here?

    ReplyDelete
  12. Hi...

    Thank you for sharing the code.
    I have a doubt regarding this part.

    /* The length of the feature vector for a cell is
    9(since no. of bins is 9), for block it would be
    9*(no. of cells in the block) = 9*4 = 36. And the
    length of the feature vector for a window would be
    36*(no. of blocks in the window */

    CvMat* window_feature_vector = cvCreateMat(1,
    ((((window.width - cell_width * block_width)
    / cell_width) + 1) * (((window.height -
    cell_height * block_height) / cell_height)
    + 1)) * 36, CV_32FC1);

    (((window.width - cell_width * block_width)
    / cell_width) + 1) ==> won't this return number of cells? if yes then in that case it should be multiplied by 9 and not 36 ...

    ReplyDelete
  13. Hi,
    I have a query regarding window sizes.
    The current code assumes window size of 64x128 pixels, a cell size of 8x8 and a block size of 2x2. Please correct my understanding below:
    As long as the cell size and block size are fixed, the calculation
    "CvMat* window_feature_vector = cvCreateMat(1,
    ((((window.width - cell_width * block_width)
    / cell_width) + 1) * (((window.height -
    cell_height * block_height) / cell_height)
    + 1)) * 36, CV_32FC1);
    "
    holds true for any window size. Please correct my understanding.
    Help would be appreciated.

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete
  15. Awesome tutorial !!!
    Exactly what i need.

    ReplyDelete
  16. Thanks for sharing this here keep up the good work ...........

    Khurram Shahzad
    Laptop Parts Online

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. Why the speed is even slower than the OpenCV version?
    It should be faster than OpenCV, right?

    ReplyDelete
  19. you work was very helpful or me

    ReplyDelete
  20. Yοur style is very unique сompared to other folks I've read stuff from. Thanks for posting when you have the opportunity, Guess I will just book mark this web site.

    My web page - cialis365.com

    ReplyDelete
  21. Could you pl explain how to detect the crawling position of a human using HOG .Is it possible to train such a position using HOG and detect the crawling position.

    ReplyDelete