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();
}



...

11/14/2014

cvCalcBackProjectPatch example source code


...
#include< cv.h>  
#include< highgui.h>  
  
void GetHSV (const IplImage* image, IplImage** h, IplImage** s, IplImage** v);  
  
int main()  
{  
    IplImage* src = cvLoadImage ("bluecup.jpg", 1);  
    IplImage* h_src = NULL;  
    IplImage* s_src = NULL;  
    GetHSV (src, &h_src, &s_src, NULL);  
    IplImage *images[] = {h_src,s_src};  
    CvHistogram* hist_src = NULL;  
  
    /*่ฎก็ฎ—ไบŒ็ปด็›ดๆ–นๅ›พ*/  
    int dims = 2;  
    int size[] = {30, 32};  
    float range_h[] = {0, 180};  
    float range_s[] = {0, 256};  
    float* ranges[] = {range_h, range_s};  
    hist_src = cvCreateHist (dims, size, CV_HIST_ARRAY, ranges);  
    cvCalcHist (images, hist_src);  
    cvNormalizeHist (hist_src, 1);  
  
    IplImage* dst = cvLoadImage ("adrian1.jpg", 1);  
    IplImage* h_dst = NULL;  
    IplImage* s_dst = NULL;  
    GetHSV (dst, &h_dst, &s_dst, NULL);  
    images[0] = h_dst;  
    images[1] = s_dst;  
  
    CvSize patch_size = cvSize (src->width, src->height);  
    IplImage* result = cvCreateImage (cvSize(h_dst->width - patch_size.width + 1, h_dst->height - patch_size.height + 1),  
        IPL_DEPTH_32F, 1);  
    cvCalcBackProjectPatch (images, result, patch_size, hist_src, CV_COMP_CORREL, 1);  
    cvShowImage ("result", result);  
      

    CvPoint max_location;  
    cvMinMaxLoc(result, NULL, NULL, NULL, &max_location, NULL);  
    max_location.x += cvRound (patch_size.width / 2);  
    max_location.y += cvRound (patch_size.height / 2);  
  

    CvPoint top = cvPoint(max_location.x - patch_size.width / 2,max_location.y - patch_size.height / 2);  
    CvPoint bottom = cvPoint(max_location.x + patch_size.width / 2, max_location.y + patch_size.height / 2);  
    cvRectangle (dst, top, bottom, CV_RGB(255, 0, 0), 1, 8, 0);  
    cvShowImage ("dst", dst);  
  
    cvWaitKey (0);  
  
    cvReleaseImage(&src);    
    cvReleaseImage(&dst);    
    cvReleaseImage(&h_src);    
    cvReleaseImage(&h_dst);    
    cvReleaseImage(&s_dst);    
    cvReleaseImage(&s_src);    
    cvReleaseHist(&hist_src);    
    cvReleaseImage(&result);    
    cvDestroyAllWindows();  
}  
  
void GetHSV (const IplImage* image, IplImage** h, IplImage** s, IplImage** v)  
{  
    IplImage* hsv = cvCreateImage (cvGetSize (image), 8, 3);  
    cvCvtColor (image, hsv, CV_BGR2HSV);  
      
    if ((h != NULL) && (*h == NULL))  
        *h = cvCreateImage (cvGetSize(image), 8, 1);  
    if ((s != NULL) && (*s == NULL))  
        *s = cvCreateImage (cvGetSize(image), 8, 1);  
    if ((v != NULL) && (*v == NULL))  
        *v = cvCreateImage (cvGetSize(image), 8, 1);  
  
    cvSplit (hsv, *h, (s == NULL)?NULL:*s, (v == NULL)?NULL:*v, NULL);  
    cvReleaseImage (&hsv);  
}  


---

11/05/2014

Opencv gpu MOG2_GPU example source code (background subtraction)



refer to example source code
I also have introduced other background subtraction method in here.
http://feelmare.blogspot.kr/2014/04/opencv-study-background-subtractor-mog.html

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


#ifdef _DEBUG        
#pragma comment(lib, "opencv_core249d.lib")
#pragma comment(lib, "opencv_imgproc249d.lib")   //MAT processing
#pragma comment(lib, "opencv_gpu249d.lib")
#pragma comment(lib, "opencv_highgui249d.lib")
#else
#pragma comment(lib, "opencv_core249.lib")
#pragma comment(lib, "opencv_imgproc249.lib")
#pragma comment(lib, "opencv_gpu249.lib")
#pragma comment(lib, "opencv_highgui249.lib")
#endif   


#define RWIDTH 800
#define RHEIGHT 600

using namespace std;
using namespace cv;

int main()
{
 /////////////////////////////////////////////////////////////////////////
 gpu::MOG2_GPU pMOG2_g(30);
 pMOG2_g.history = 3000; //300;
 pMOG2_g.varThreshold =64; //128; //64; //32;//; 
 pMOG2_g.bShadowDetection = true;
 Mat Mog_Mask;
 gpu::GpuMat Mog_Mask_g;
 /////////////////////////////////////////////////////////////////////////


 VideoCapture cap("C:\\videoSample\\tracking\\sample.avi");//0);
 /////////////////////////////////////////////////////////////////////////
 Mat o_frame;
 gpu::GpuMat o_frame_gpu;
 gpu::GpuMat r_frame_gpu;
 gpu::GpuMat rg_frame_gpu;
 gpu::GpuMat r_frame_blur_gpu;
 /////////////////////////////////////////////////////////////////////////

 cap >> o_frame;
 if( o_frame.empty() )
   return 0; 
 vector< gpu::GpuMat> gpurgb(3);
 vector< gpu::GpuMat> gpurgb2(3);
 /////////////////////////////////////////////////////////////////////////


 unsigned long AAtime=0, BBtime=0;

 //Mat rFrame;
 Mat showMat_r_blur;
 Mat showMat_r;

 while(1)
 {
  /////////////////////////////////////////////////////////////////////////
  cap >> o_frame;
  if( o_frame.empty() )
   return 0;

  
  o_frame_gpu.upload(o_frame);
  gpu::resize(o_frame_gpu, r_frame_gpu, Size(RWIDTH, RHEIGHT) );
  AAtime = getTickCount();
  

  gpu::split(r_frame_gpu, gpurgb);
  gpu::blur(gpurgb[0], gpurgb2[0], Size(3,3) );
  gpu::blur(gpurgb[1], gpurgb2[1], Size(3,3) );
  gpu::blur(gpurgb[2], gpurgb2[2], Size(3,3) );
  gpu::merge(gpurgb2, r_frame_blur_gpu);
  //
  pMOG2_g.operator()(r_frame_blur_gpu, Mog_Mask_g,-1);
  //
  Mog_Mask_g.download(Mog_Mask);

  BBtime = getTickCount(); 
  float pt = (BBtime - AAtime)/getTickFrequency(); 
  float fpt = 1/pt;
  printf("gpu %.4lf / %.4lf \n",  pt, fpt );

  
  r_frame_gpu.download(showMat_r);
  //rg_frame_gpu.download(showMat_rg);
  r_frame_blur_gpu.download(showMat_r_blur);
  imshow("origin", showMat_r);
  //imshow("gray", showMat_rg);
  imshow("blur", showMat_r_blur);
  imshow("mog_mask", Mog_Mask);
  
  
  /////////////////////////////////////////////////////////////////////////

  if( waitKey(10) > 0)
   break;
 }

 return 0;
}
..

Opencv gpu 3 channel blur example

There is no 3 channel blur in gpu function.

gpu::blur is support CV_8UC1 and CV_8UC4  channel only.
gpu::gaussianblur is also not suitable often.

So one of idea is split channel.
split 3 channel and perform blur function for each channel.
and then merge to a blur 3channel image.

this is faster than cpu code(lager image will be faster).

In my case, the process takes cpu :0.0126sec gpu:0.0035sec in 800x600 image.

refer to example source code.


...
//gpu case
gpu::resize(o_frame_gpu, r_frame_gpu, Size(RWIDTH, RHEIGHT) );
vector< gpu::GpuMat> gpurgb(3);
vector< gpu::GpuMat> gpurgb2(3);
gpu::split(r_frame_gpu, gpurgb);
gpu::blur(gpurgb[0], gpurgb2[0], Size(3,3) );
gpu::blur(gpurgb[1], gpurgb2[1], Size(3,3) );
gpu::blur(gpurgb[2], gpurgb2[2], Size(3,3) );
gpu::merge(gpurgb2, r_frame_blur_gpu);

//cpu case
resize(o_frame, rFrame, Size(RWIDTH, RHEIGHT) );
blur(rFrame, blurFrame, Size(3,3));



...


11/03/2014

opencv randn(...) example

opencv randn is like in matlab.

The randn function make values of normal distribution random

in matlab
randn is usage like this..

randn()
>> 0.4663

randn(10,1)'
>>   -0.1465    1.0143    0.4669    1.5750   -1.1900    0.2689   -0.2967   -0.4877    0.5671    0.5632

to use mean 5, variance 3
5+3*rand(10,1)
>> 6.2932   12.5907    6.6214    1.6941    4.8522    3.1484    6.1745    4.5230    5.2183    5.6888


OK, now consider case of OpenCV
We will make mean 10 and variance 2 normal distribution random values and fill in 2x10 matrix.

example 1)
randn
..
cv::Mat matrix2xN(2, 10, CV_32FC1);
randn(matrix2xN, 10, 2);
for (int i = 0; i &lt; 10; ++i)
{
  cout << matrix2xN.at<float>(0, i) << " ";
  cout << matrix2xN.at<float>(1, i) << endl;
}
..

example 2)
randn and randu
..
cv::Mat matrix2xN(2, 10, CV_32FC1);
randn(matrix2xN, 10, 2);
for (int i = 0; i < 10; ++i)
{
    cout << matrix2xN.at< float>(0, i) << " ";
    cout << matrix2xN.at< float>(1, i) << endl;
}

//gaussian generation example
Mat Gnoise = Mat(5, 5, CV_8SC1);
randn(Gnoise, 5, 10); //mean, variance
cout << Gnoise << endl;
//
Mat Unoise = Mat(5, 5, CV_8SC1);
randu(Unoise, 5, 10); //low, high
cout << Unoise << endl;


//noise adapt
Mat Gaussian_noise = Mat(img.size(), img.type());
double mean = 0;
double std = 10;
randn(Gaussian_noise, mean, std); //mean, std
Mat colorNoise = img + Gaussian_noise;
..

OpenCV EMD(earth mover distance) example source code

EMD(earth mover distance) method is very good method to compare image similarity.
But processing time is slow.
For using the EMD compare, we should make signature value.
The EMD method compares two signatures value.

Firstly, we prepare histograms of 2 images.
And convert values of histrogram to signature.

A configuration of signature values is very simple.

bins value, x index, y index.
bins value, x index, y index.
bins value, x index, y index.
bins value, x index, y index.
bins value, x index, y index.
....

Of course this type is in case of 2d histogram.
More detail, see the source code.

In here I cannot explain earth mover distance algorithm.
please refer to internet information.

thank you.


origin images
 
result


...
#include < iostream>
#include < vector>

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


#ifdef _DEBUG           
#pragma comment(lib, "opencv_core249d.lib")   
#pragma comment(lib, "opencv_imgproc249d.lib")   //MAT processing   
#pragma comment(lib, "opencv_highgui249d.lib")   
#else   
#pragma comment(lib, "opencv_core249.lib")   
#pragma comment(lib, "opencv_imgproc249.lib")      
#pragma comment(lib, "opencv_highgui249.lib")   
#endif   


using namespace cv;   
using namespace std;   
  
  
  
int main()   
{   

 //read 2 images for histogram comparing   
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
 Mat imgA, imgB;   
 imgA = imread(".\\image1.jpg");   
 imgB = imread(".\\image2.jpg");   


 imshow("img1", imgA);
 imshow("img2", imgB);


 //variables preparing   
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
 int hbins = 30, sbins = 32;    
 int channels[] = {0,  1};   
 int histSize[] = {hbins, sbins};   
 float hranges[] = { 0, 180 };   
 float sranges[] = { 0, 255 };   
 const float* ranges[] = { hranges, sranges};    

 Mat patch_HSV;   
 MatND HistA, HistB;   

 //cal histogram & normalization   
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
 cvtColor(imgA, patch_HSV, CV_BGR2HSV);   
 calcHist( &patch_HSV, 1, channels,  Mat(), // do not use mask   
  HistA, 2, histSize, ranges,   
  true, // the histogram is uniform   
  false );   
 normalize(HistA, HistA,  0, 1, CV_MINMAX);   


 cvtColor(imgB, patch_HSV, CV_BGR2HSV);   
 calcHist( &patch_HSV, 1, channels,  Mat(),// do not use mask   
  HistB, 2, histSize, ranges,   
  true, // the histogram is uniform   
  false );   
 normalize(HistB, HistB, 0, 1, CV_MINMAX);   

 //compare histogram   
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
 int numrows = hbins * sbins;

 //make signature
 Mat sig1(numrows, 3, CV_32FC1);
 Mat sig2(numrows, 3, CV_32FC1);

 //fill value into signature
 for(int h=0; h< hbins; h++)
 {
  for(int s=0; s< sbins; ++s)
  {
   float binval = HistA.at< float>(h,s);
   sig1.at< float>( h*sbins + s, 0) = binval;
   sig1.at< float>( h*sbins + s, 1) = h;
   sig1.at< float>( h*sbins + s, 2) = s;

   binval = HistB.at< float>(h,s);
   sig2.at< float>( h*sbins + s, 0) = binval;
   sig2.at< float>( h*sbins + s, 1) = h;
   sig2.at< float>( h*sbins + s, 2) = s;
  }
 }

 //compare similarity of 2images using emd.
 float emd = cv::EMD(sig1, sig2, CV_DIST_L2); //emd 0 is best matching. 
 printf("similarity %5.5f %%\n", (1-emd)*100 );
 
 waitKey(0);   

 return 0;   
}  

...