11/26/2014

OpenCV SVM learning method and xml convert method to use in Hog.SetSVMDetector() function

This is example of SVM learning method.
This example is I already have explained in past time.
See the this page - >http://feelmare.blogspot.kr/search/label/SVM

But other contents is added in this example.
That is converting of trained xml file to use in Hog.MultiScaleDetection function.

Converting process is started after svm learning.
See the comment of "the second save option" in source code.

Thank you.



---
#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 

class MySvm: public CvSVM  
{  
public:  
 int get_alpha_count(){
  return this->sv_total;}

 int get_sv_dim(){
  return this->var_all;}

 int get_sv_count(){
  return this->decision_func->sv_count;}
 
 double* get_alpha(){
  return this->decision_func->alpha;}
 
 float** get_sv(){
  return this->sv;}
 
 float get_rho(){
  return this->decision_func->rho;}
};


void main()
{
 
 //Read Hog feature from XML file
 ///////////////////////////////////////////////////////////////////////////
 printf("1. Feature data xml load\n");
 //create xml to read
 FileStorage read_PositiveXml("C:\\POSCO\\Learned\\Positive1643_64_64.xml", FileStorage::READ);
 FileStorage read_NegativeXml("C:\\POSCO\\Learned\\Negative16064_64_64.xml", FileStorage::READ);
 char SVMSaveFile[100] = "C:\\POSCO\\Learned\\trainedSVM_1643_16064_64_64.xml";
 char SVM_HOGDetectorFile[100] = "C:\\POSCO\\Learned\\HogDetectorXML_1643_16064_64_64.xml";
 //Positive Mat
 Mat pMat; 
 read_PositiveXml["Descriptor_of_images"] >> pMat;
 //Read Row, Cols
 int pRow,pCol;
 pRow = pMat.rows; pCol = pMat.cols;

 //Negative Mat
 Mat nMat;
 read_NegativeXml["Descriptor_of_images"] >> nMat;
 //Read Row, Cols
 int nRow,nCol;
 nRow = nMat.rows; nCol = nMat.cols;

 //Rows, Cols printf
 printf("   pRow=%d pCol=%d, nRow=%d nCol=%d\n", pRow, pCol, nRow, nCol );
 //release
 read_PositiveXml.release();
 //release
 read_NegativeXml.release();
 /////////////////////////////////////////////////////////////////////////////////

 //Make training data for SVM
 /////////////////////////////////////////////////////////////////////////////////
 printf("2. Make training data for SVM\n");
 //descriptor data set
 Mat PN_Descriptor_mtx( pRow + nRow, pCol, CV_32FC1 ); //in here pCol and nCol is descriptor number, so two value must be same;
 memcpy(PN_Descriptor_mtx.data, pMat.data, sizeof(float) * pMat.cols * pMat.rows );
 int startP = sizeof(float) * pMat.cols * pMat.rows;
 memcpy(&(PN_Descriptor_mtx.data[ startP ]), nMat.data, sizeof(float) * nMat.cols * nMat.rows );
 //data labeling
 Mat labels( pRow + nRow, 1, CV_32FC1, Scalar(-1.0) );
    labels.rowRange( 0, pRow ) = Scalar( 1.0 );
 /////////////////////////////////////////////////////////////////////////////////

 //Set svm parameter
 /////////////////////////////////////////////////////////////////////////////////
 printf("4. SVM training\n");
 MySvm svm; //CvSVM svm;
 CvSVMParams params;
 params.svm_type = CvSVM::C_SVC;
    params.kernel_type = CvSVM::LINEAR;
    params.term_crit = cvTermCriteria( CV_TERMCRIT_ITER, 10000, 1e-6 );
 /////////////////////////////////////////////////////////////////////////////////

 //Training
 /////////////////////////////////////////////////////////////////////////////////
 svm.train(PN_Descriptor_mtx, labels, Mat(), Mat(), params);
 //Trained data save
 /////////////////////////////////////////////////////////////////////////////////
 printf("5. SVM xml save\n");
 svm.save( SVMSaveFile );
 
 //////////////////////////////////////////////////////////////////////////////////
 //Second Save option
 //This save file is for Hog.SetSVMDectector() function
 //And if we can use this function(SetSVMDectector), we can use detectMultiScale function.
 //This function is very easy to detect target, and we also can apply GPU option.

 //make firstly, inherited class to access alpha vector and value
 int svmVectorSize = svm.get_support_vector_count();
 int featureSize = pCol;
 //prepare, variables 
 
 
 Mat sv = Mat(svmVectorSize, featureSize, CV_32FC1, 0.0);
 Mat alp = Mat(1, svmVectorSize, CV_32FC1, 0.0);
 Mat re = Mat(1, featureSize, CV_32FC1, 0.0);
 Mat re2 = Mat(1, featureSize+1, CV_32FC1, 0.0);

 
 
 //set value to variables
 for(int i=0; i< svmVectorSize; ++i)
  memcpy( (sv.data + i*featureSize), svm.get_support_vector(i), featureSize*sizeof(float) ); //ok

 
 double * alphaArr = svm.get_alpha();
 int alphaCount = svm.get_alpha_count();

 for(int i=0; i< svmVectorSize; ++i)
 { 
  alp.at< float>(0, i) = (float)alphaArr[i];
  //printf("alpha[%d] = %lf \n", i, (float)alphaArr[i] );
 }
 
 //cvMatMul(alp, sv, re);
 re = alp * sv;

 for(int i=0; i< featureSize; ++i)
  re2.at< float>(0,i) =  re.at< float>(0,i) * -1;
 re2.at< float>(0,featureSize) = svm.get_rho();

 //save to 1d vector to XML format!!
 FileStorage svmSecondXML(SVM_HOGDetectorFile, FileStorage::WRITE);
 svmSecondXML << "SecondSVMd" << re2 ; 

 svmSecondXML.release();
 
 
// FileStorage hogXml("testXML.xml", FileStorage::WRITE); //FileStorage::READ
// write(hogXml, "Data", PN_Descriptor_mtx);
// write(hogXml, "Label", labels);
// hogXml.release();
}



...

10 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hello, I would like to thank you for your great tutorials, I tested the three steps of hog+svm and they are working fine for me.
    Now I want to use my own trained hog-svm for humain detection.
    To do so I guess I have to use "Hog.SetSVMDetector()" and give it my own detector as input. this input must be an std::vector but in your code I can't find the 1D vector that I should use. Can you please explain to me what are the "Mat" variables and where is the vector that I'm looking for?
    Thank you in advance.
    ๊ณ ๋ง™์Šต๋‹ˆ๋‹ค!

    ReplyDelete
  3. re2 is 1D Mat.
    Check again.
    Thank you.

    ReplyDelete
    Replies
    1. Thank you for your quick response, I already checked hog.setSVMDetector(re2); but it gave me this error:
      "error: (-215) checkDetectorSize() in function setSVMDetector" is there a problem with the re2 size? How can I fix it?

      Delete
    2. I didn't solve the problem yet, I do really need your help sir. can you please tell me what's wrong, I've been looking for the solution for days and I almost checked out every possible mistake. :(
      thank you.

      Delete
  4. Hi, I tried your code. step123 are all working. But when I tried to use setSVMdetector(), it has error "assertion failed check detectorsize....". I set the descriptor in the step the same as yours d( Size(32,16), Size(8,8), Size(4,4), Size(4,4), 9); and in the detector part, I used the same size. what is going on?

    ReplyDelete
    Replies
    1. Check image size and gray-scale image.
      Thank you

      Delete
  5. This comment has been removed by the author.

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

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete