4/17/2014

Example source code of extract HOG feature from images, save descriptor values to xml file, using opencv (using HOGDescriptor )

This example source code is to extract HOG feature from images.
And save descriptors to XML file.

The source code explain how to use HOGDescriptor function.



..
#include < stdio.h>
#include < opencv2\opencv.hpp>
//#include < opencv2\gpu\gpu.hpp>

using namespace cv;
using namespace std;


#ifdef _DEBUG        
#pragma comment(lib, "opencv_core247d.lib")         
#pragma comment(lib, "opencv_imgproc247d.lib")   //MAT processing        
#pragma comment(lib, "opencv_objdetect247d.lib") //HOGDescriptor
//#pragma comment(lib, "opencv_gpu247d.lib")        
//#pragma comment(lib, "opencv_features2d247d.lib")        
#pragma comment(lib, "opencv_highgui247d.lib")        
//#pragma comment(lib, "opencv_ml247d.lib")      
//#pragma comment(lib, "opencv_stitching247d.lib");      
//#pragma comment(lib, "opencv_nonfree247d.lib");      
  
#else        
#pragma comment(lib, "opencv_core247.lib")        
#pragma comment(lib, "opencv_imgproc247.lib")        
#pragma comment(lib, "opencv_objdetect247.lib")        
//#pragma comment(lib, "opencv_gpu247.lib")        
//#pragma comment(lib, "opencv_features2d247.lib")        
#pragma comment(lib, "opencv_highgui247.lib")        
//#pragma comment(lib, "opencv_ml247.lib")        
//#pragma comment(lib, "opencv_stitching247.lib");      
//#pragma comment(lib, "opencv_nonfree247.lib");      
#endif 


void main()
{
 //variables
 char FullFileName[100];
 char FirstFileName[100]="./images/upperbody";
 char SaveHogDesFileName[100] = "Positive.xml";
 int FileNum=96;

 vector< vector < float> > v_descriptorsValues;
 vector< vector < Point> > v_locations;


 for(int i=0; i< FileNum; ++i)
 {
  sprintf_s(FullFileName, "%s%d.png", FirstFileName, i+1);
  printf("%s\n", FullFileName);

  //read image file
  Mat img, img_gray;
  img = imread(FullFileName);
  
  //resizing
  resize(img, img, Size(64,48) ); //Size(64,48) ); //Size(32*2,16*2)); //Size(80,72) ); 
  //gray
  cvtColor(img, img_gray, CV_RGB2GRAY);

  //extract feature
  HOGDescriptor d( Size(32,16), Size(8,8), Size(4,4), Size(4,4), 9);
  vector< float> descriptorsValues;
  vector< Point> locations;
  d.compute( img_gray, descriptorsValues, Size(0,0), Size(0,0), locations);

  //printf("descriptor number =%d\n", descriptorsValues.size() );
  v_descriptorsValues.push_back( descriptorsValues );
  v_locations.push_back( locations );
  //show image
  imshow("origin", img);

  waitKey(5);
 }

 //refer to this address -> http://feelmare.blogspot.kr/2014/04/the-example-source-code-of-2d-vector.html
 //save to xml
 FileStorage hogXml(SaveHogDesFileName, FileStorage::WRITE); //FileStorage::READ
 //2d vector to Mat
 int row=v_descriptorsValues.size(), col=v_descriptorsValues[0].size();
 printf("col=%d, row=%d\n", row, col);
 Mat M(row,col,CV_32F);
 //save Mat to XML
 for(int i=0; i< row; ++i)  
  memcpy( &(M.data[col * i * sizeof(float) ]) ,v_descriptorsValues[i].data(),col*sizeof(float));
 //write xml
 write(hogXml, "Descriptor_of_images",  M);

 //write(hogXml, "Descriptor", v_descriptorsValues );
 //write(hogXml, "locations", v_locations );
 hogXml.release();

}



...


same with above code.
< gist code start>

< gist code end >


26 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. 안녕하세요"" 블로그를 참조해서 Positive, Negative data를 만들고 SVM tratining을 해보려고 하고있습니다.
    제공해주신 코드로 Positive.xml은 생성해보았는데, Negative.xml도 마찬가지로 하면 되는건지 궁금해서 질문드립니다. 아니면 Negative.xml은 이미지의 이름만 적어주면 되는건가요??
    그리고, 사람을 검출하고자 한다면 Positive.xml 생성시에 사용되는 이미지는 이미지에서 사람만 잘라서 사용해야 하는건가요?
    Negative 이미지는 사람이 없는 이미지를 그대로 사용해야하구요?

    두서없이 질문드려 죄송합니다;;

    ReplyDelete
  3. You also should make negative.xml file.
    The negative image should not contain positive image ex) face, human body...

    positive.xml have to make similar images.
    refer to this weg page" http://feelmare.blogspot.kr/search/label/Data"

    negative.xml was made by natural images not include positive images.
    and that is good way using background image of actual testing. then you can avoid false positive detection of you predicted.
    ->실제 적용할 곳의 배경 이미지를 사용하는 것이 좋습니다. 그러면 오검출 예상 부분을 없앨 수 있겠죠..

    thank you.

    ReplyDelete
  4. 안녕하세요.
    궁금한점이 생겨 이렇게 질문 드립니다.
    위에 보면 ="./images/upperbody"; 부분이 데이터셋위치 정보같은데
    폴더인가요???
    코딩시 계속 처리되지 않은 오류가 발생한다고하네요
    답답한마음에 여쭤봅니다

    ReplyDelete
    Replies
    1. 다수의 이미지가 있는 폴더여야하는지.. .xml형식의 자료여야하는지..
      또한 이미지 사이즈도 상관있는건지... 궁금합니다.
      초보가 이러한 질문해서 죄송합니다.

      Delete
    2. 지금 소스는 다수의 이미지를 for로 루프돌면서 hough 특징을 추출하고 있고요
      영상 사이즈를 같게 하기 위해서 루프안에서 resize를 해주고 있습니다.
      hough 특징은 똑같은 사이즈로 뽑고 그것을 학습할때 사용합니다.
      감사합니다.

      Delete
    3. "./images/upperbody"; 는 폴더가 맞고요
      sprintf_s(FullFileName, "%s%d.png", FirstFileName, i+1);

      이 문장에 의해서 파일명이 만들어 집니다.
      다수의 파일이 순서되로 정리 되어 있습니다.

      Delete
  5. See detail in for loop.
    How to use FirstFileName char(line 47)
    And Why code use resize function(line 55)
    Increase your code reading skill.
    Cheer up!

    ReplyDelete
  6. Anonymous6/5/16 10:54

    thx for this example

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

    ReplyDelete
  8. Hi, I wonder if there is a version of this code that can be implemented in Android studio?

    ReplyDelete
    Replies
    1. Em.. actually I don't know android environment.
      but even though android, that can load xml file, may be.
      so first make xml file on pc, and after load xml on android.
      Thank you.

      Delete
  9. Library Link Error!! Do You Kindly Share Complete Package Of Source Code

    ReplyDelete
    Replies
    1. sorry, do you meet opencv library link error?
      Do you use 2.xx version like me?
      Thank you.

      Delete
  10. 안녕하세요.
    궁금한점이 있어서 질문드립니다.
    마지막에 hogXml.release();를 for문 안에 넣으면 저장할 공간이 없다는 error 메세지가 뜨는데
    for문 밖으로 꺼내서 write를 다 끝낸 후에 release를 하면 안되는건지 궁금합니다.
    그리고 해본 결과 시간이 오래 걸리던데 오래 걸리는게 맞는건지...궁금합니다.
    아직 배우고 있는 단계여서 죄송합니다.

    ReplyDelete
    Replies
    1. 말씀하신 방법이 맞는 것 같습니다.
      코드 라인이 보기 힘들어서 gist로 다시 올렸습니다.
      감사합니다.

      Delete
  11. 안녕하세요. 궁금한점이 있어 질문드립니다.
    hog.compute 함수를 써서 제가 원하는 객체의 hog 특징을 뽑고 학습하는데 잘 이용하고 있었는데, 문제가 생겼습니다.
    좀더 자세한 feature 를 뽑고 싶어서 크게 뽑고 싶어서 다음과 같이 코드를 짯는데요. 저의 이론상으로는 확실한데 뭐가 문제인지 모르겠네요. compute 함수가 window 사이즈의 limitation 을 걸어논건지.. 아니면 제가 정말 잘못 이해하고 있는건지 모르겠어서 Mare님의 도움을 얻을수 없을까 싶어 이렇게 질문을 드립니다.

    resize(mat_input, mat_input, Size(160,100));
    cvtColor(mat_input, mat_gray, CV_RGB2GRAY);
    이미지 사이즈는 위와 160,100 으로 설정하였습니다.
    //extract feature
    HOGDescriptor hogDescriptor(Size(160, 100), Size(40, 40), Size(20, 20), Size(20, 20), 9);
    vector< float> vf_DescriptorsValues;
    vector< Point> v_LocationPoint ;

    cv::Size winStride(0, 0);
    cv::Size winPadding(0, 0);
    hogDescriptor.compute(mat_gray, vf_DescriptorsValues, winStride, winPadding, v_LocationPoint);

    제가 생각하기로는 다음과 같이 설정을 했을 경우, 1008 feature dimension이 나올것이라 예상하는데,
    128,80 까지의 윈도우 까지는 허용을 하였으나, 그 이상으로는 계산이 되질 않습니다.

    제가 설정한 코드의 문제가 있는것인가요? 확인 부탁드립니다ㅠㅠ

    문제가 있는것이면, 저는 320,200정도의 이미지에서 hog feature를 뽑고 싶은데, 혹시 큰크기의 영상에서 뽑는 방법을 알고 계신지 여쭤봐도 될까요?

    ReplyDelete
    Replies
    1. 네 감사합니다. hog 특징 생성할때, 파라미터가 좀 잘 못 된것 같은데요.. 좀더 자세히 알아보려면 저도 시간이 필요하겠네요.. 저도 hog 안한지 오래되어서 기억이 가물가물하거든요.. ^^
      지금 업무도 많고 해서.. 제가 빨리 답변 못드리는 점 죄송합니다.

      Delete
  12. how can i train my HOG descriptor to detect partial parts of the human body

    ReplyDelete
  13. your meaning is, you want to create your own hog feature right?
    and training by svm.
    if that case, this post will help

    http://study.marearts.com/2016/01/svm-hog-learning-and-detection-methods.html

    Thanks for your interesting.

    ReplyDelete
  14. Hy Mister, I'm new in HOG Feature, I want to ask, when i used hog.compute in a loop like u do, it always crash and throwing an exception, it said "Invalid_parameter:
    _SCL_SECURE_INVALID_ARGUMENT_NO_ASSERT;"
    it only compute 1 image then always crashing in the next image and throw that exception (it can't looping). Please help me solve my problem here. Thanks

    ReplyDelete
    Replies
    1. Hi, The first loop succeeded, but does it fail from the second?
      Does the image size change?
      Thank you.

      Delete
  15. Thank you for your reply, I'm really sorry I can't reply faster, there are no change of the images except before calculating HOG, like u did above. This is my code, can you check it where I did wrong, Thank you for your response.

    int main(int argc, const char* argv[])
    {
    string folder = "D:\\Project\\TA\\Data_Trainer\\Clip_Images\\Positif Training1\\pisang\\"; // folder input
    string suffix = ".png";
    int counter = 0;
    Mat img, img_gray;
    Mat img1, img2;

    for (int i = 0; i < 10; i++) {
    stringstream ss;
    cout << "check point 0 " << endl;
    ss << setw(4) << setfill('0') << counter; // 0000, 0001, 0002, etc...
    //ss << counter; // 0000, 0001, 0002, etc...
    string number = ss.str();

    string name = folder + number + suffix;
    img = imread(name);
    if (img.empty()) cout << "No image Loaded" << endl;
    else cout << "image " << counter << " Loaded Successfully" << endl;
    cout << name << endl;

    //Parameter
    setWidth = 32, setHeight = 32;

    //resizing
    resize(img, img, Size(setWidth, setHeight)); //Size(64,48) ); //Size(32*2,16*2)); //Size(80,72) );

    //GrayScaling
    cvtColor(img, img_gray, CV_RGB2GRAY); //gray

    //extract feature
    HOGDescriptor hog(Size(setWidth, setHeight), Size(8, 8), Size(4, 4), Size(4, 4), 9);
    // Size(32,16), //winSize
    // Size(8,8), //blocksize
    // Size(4,4), //blockStride,
    // Size(4,4), //cellSize,
    // 9, //nbins,
    vector< float> descriptorsValues;
    vector< Point> locations;

    hog.compute(img_gray, descriptorsValues, Size(0, 0), Size(0, 0), locations);
    // img, descriptor, winStride, Padding, Location

    if (descriptorsValues.empty()) cout << "descriptorValues empty" << endl;
    if (locations.empty()) cout << "location empty" << endl;

    v_descriptorsValues.push_back(descriptorsValues);
    v_locations.push_back(locations);

    printf("row =%d ", v_descriptorsValues.size());
    printf(" ,col =%d\n", v_descriptorsValues[0].size());

    //show image
    //imshow("origin", img);
    waitKey(3);

    cout << "loop: " << counter << endl;
    counter++;
    //img.release();
    //img_gray.release();
    cout << "check point 1" << endl;
    descriptorsValues.clear();
    locations.clear();

    }

    ReplyDelete
  16. Hopefully anyone can help me about this, I really need your help :)

    ReplyDelete