2/09/2015

Extracting two hog feature and comparing by vectors of descriptor in opencv (example source code)


I am wondering that two hog features can compare or not.

There was a article about this question on this page ->
http://stackoverflow.com/questions/11626140/extracting-hog-features-using-opencv

This article introduces that to compare the descriptor values of HOG.
I don't know this comparison is surely exact or not.

I think this comparison need more experiment.




similarity test in video





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


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

#define M_PI 3.1415

using namespace std;  
using namespace cv;  


Mat get_hogdescriptor_visual_image(Mat& origImg,
                                   vector< float>& descriptorValues,
                                   Size winSize,
                                   Size cellSize,                                   
                                   int scaleFactor,
                                   double viz_factor);

int main()  
{  

 //image load
 Mat img1 = imread("./b1.jpg");
 Mat img2 = imread("./c5.jpg");

 //rgb 2 gray
 Mat img1_gray; 
 cvtColor(img1, img1_gray, CV_RGB2GRAY);

 Mat img2_gray; 
 cvtColor(img2, img2_gray, CV_RGB2GRAY);

 //resize smaller
 Mat r_img1_gray;
 resize(img1_gray, r_img1_gray, Size(64, 8));
 Mat r_img2_gray;
 resize(img2_gray, r_img2_gray, Size(64, 8));


 //extractino hog feature
 HOGDescriptor d1( Size(64,8), Size(8,8), Size(4,4), Size(4,4), 9);
 HOGDescriptor d2( Size(64,8), 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,

 //hog feature compute
 vector< float> descriptorsValues1;
 vector< Point> locations1;
 d1.compute( r_img1_gray, descriptorsValues1, Size(0,0), Size(0,0), locations1);
 vector< float> descriptorsValues2;
 vector< Point> locations2;
 d2.compute( r_img2_gray, descriptorsValues2, Size(0,0), Size(0,0), locations2);

 //hog feature size
 //cout << descriptorsValues1.size() << endl;


 ///////////////////////
 //copy vector to mat  
 //create Mat  
 Mat A(descriptorsValues1.size(),1,CV_32FC1); 
 //copy vector to mat  
 memcpy(A.data,descriptorsValues1.data(),descriptorsValues1.size()*sizeof(float));
 //create Mat  
 Mat B(descriptorsValues2.size(),1,CV_32FC1); 
 //copy vector to mat  
 memcpy(B.data,descriptorsValues2.data(),descriptorsValues2.size()*sizeof(float));


 /////////////////////////
 //sum( sqrt( (A.-B)^2 ) )
 Mat C = A-B;
 C = C.mul(C);
 cv::sqrt(C, C);
 cv::Scalar rr = cv::sum(C);
 float rrr = rr(0);
 cout << "Distance: " << rrr << endl;

 
 //hog visualization
 Mat r1 = get_hogdescriptor_visual_image(r_img1_gray, descriptorsValues1, Size(64,8), Size(4,4), 10, 3);
 Mat r2 = get_hogdescriptor_visual_image(r_img2_gray, descriptorsValues2, Size(64,8), Size(4,4), 10, 3);

 imshow("hog visualization1", r1);
 imshow("hog visualization2", r2);

 waitKey(0);

 return 0;
}






refer to this page http://feelmare.blogspot.kr/2015/02/opencv-hog-descriptor-computation-and.html about the function "get_hogdescriptor_visual_image" in example source code.


OpenCV, Mat operation example of sum(sqrt( A.-B) )

Simple Mat operation using opencv.
But it always not remember well.





vector< float> v1;
 vector< float> v2;
 for(int i=0; i<5; ++i)
 {
  v1.push_back(i*2);
  v2.push_back(i*3);
 }


 Mat AA(v1.size(),1,CV_32FC1); 
 //copy vector to mat  
 memcpy(AA.data,v1.data(),v1.size()*sizeof(float));
 //create Mat  
 Mat BB(v2.size(),1,CV_32FC1); 
 //copy vector to mat  
 memcpy(BB.data,v2.data(),v2.size()*sizeof(float));

 cout << "AA: " << AA << endl;
 cout << "BB: " << BB << endl << endl;


 Mat CC = AA-BB;
 cout << "CC = AA-BB : " << CC << endl << endl;
 CC = CC.mul(CC);
 cout << "CC.*CC or CC^2 : " << CC << endl << endl;
 cv::sqrt(CC, CC);
 cout << "sqrt(CC.) : " << CC << endl << endl;
 cv::Scalar rr = cv::sum(CC);
 float rrr = rr(0);
 cout << "sum(CC.) : " << rrr << endl << endl;


2/08/2015

OpenCV, HOG descriptor computation and visualization (HOGDescriptor function)

This article is about hog feature extraction and visualization.

Hog feature can computer easy using HOGDescriptor method in opencv.

Visualization is little bit complex. But Jürgen Brauer introduce HOG feature visualization function in his blog.
refer to this page -> http://www.juergenwiki.de/work/wiki/doku.php?id=public:hog_descriptor_computation_and_visualization
I thought he is very excellent researcher in computer vision.

So, I introduce hog feature extraction and visualization using his code.


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


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

#define M_PI 3.1415

using namespace std;  
using namespace cv;  


Mat get_hogdescriptor_visual_image(Mat& origImg,
                                   vector< float>& descriptorValues,
                                   Size winSize,
                                   Size cellSize,                                   
                                   int scaleFactor,
                                   double viz_factor);

int main()  
{  

 

 Mat img1 = imread("./1.jpg");

 Mat img1_gray; 
 cvtColor(img1, img1_gray, CV_RGB2GRAY);
 
 Mat r_img1_gray;
 resize(img1_gray, r_img1_gray, Size(32, 16));


 //extractino hog feature
 HOGDescriptor d1( Size(32,16), 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,


 //feature compare
 vector< float> descriptorsValues1;
 vector< Point> locations1;
 d1.compute( r_img1_gray, descriptorsValues1, Size(0,0), Size(0,0), locations1);


 //hog visualization
 Mat r1 = get_hogdescriptor_visual_image(r_img1_gray,
                                   descriptorsValues1,
                                   Size(32,16),
                                   Size(4,4),                                   
                                   10,
                                   5);

 imshow("hog visualization", r1);
 waitKey(0);

 return 0;
}



Mat get_hogdescriptor_visual_image(Mat& origImg,
                                   vector< float>& descriptorValues,
                                   Size winSize,
                                   Size cellSize,                                   
                                   int scaleFactor,
                                   double viz_factor)
{   
    Mat visual_image;
    resize(origImg, visual_image, Size(origImg.cols*scaleFactor, origImg.rows*scaleFactor));
 cvtColor(visual_image, visual_image, CV_GRAY2BGR);

 
    int gradientBinSize = 9;
    // dividing 180° into 9 bins, how large (in rad) is one bin?
    float radRangeForOneBin = 3.14/(float)gradientBinSize; 
 
    // prepare data structure: 9 orientation / gradient strenghts for each cell
 int cells_in_x_dir = winSize.width / cellSize.width;
    int cells_in_y_dir = winSize.height / cellSize.height;
    int totalnrofcells = cells_in_x_dir * cells_in_y_dir;
    float*** gradientStrengths = new float**[cells_in_y_dir];
    int** cellUpdateCounter   = new int*[cells_in_y_dir];
    for (int y=0; y< cells_in_y_dir; y++)
    {
        gradientStrengths[y] = new float*[cells_in_x_dir];
        cellUpdateCounter[y] = new int[cells_in_x_dir];
        for (int x=0; x< cells_in_x_dir; x++)
        {
            gradientStrengths[y][x] = new float[gradientBinSize];
            cellUpdateCounter[y][x] = 0;
 
            for (int bin=0; bin< gradientBinSize; bin++)
                gradientStrengths[y][x][bin] = 0.0;
        }
    }
 
    // nr of blocks = nr of cells - 1
    // since there is a new block on each cell (overlapping blocks!) but the last one
    int blocks_in_x_dir = cells_in_x_dir - 1;
    int blocks_in_y_dir = cells_in_y_dir - 1;
 
    // compute gradient strengths per cell
    int descriptorDataIdx = 0;
    int cellx = 0;
    int celly = 0;
 
    for (int blockx=0; blockx< blocks_in_x_dir; blockx++)
    {
        for (int blocky=0; blocky< blocks_in_y_dir; blocky++)            
        {
            // 4 cells per block ...
            for (int cellNr=0; cellNr< 4; cellNr++)
            {
                // compute corresponding cell nr
                int cellx = blockx;
                int celly = blocky;
                if (cellNr==1) celly++;
                if (cellNr==2) cellx++;
                if (cellNr==3)
                {
                    cellx++;
                    celly++;
                }
 
                for (int bin=0; bin< gradientBinSize; bin++)
                {
                    float gradientStrength = descriptorValues[ descriptorDataIdx ];
                    descriptorDataIdx++;
 
                    gradientStrengths[celly][cellx][bin] += gradientStrength;
 
                } // for (all bins)
 
 
                // note: overlapping blocks lead to multiple updates of this sum!
                // we therefore keep track how often a cell was updated,
                // to compute average gradient strengths
                cellUpdateCounter[celly][cellx]++;
 
            } // for (all cells)
 
 
        } // for (all block x pos)
    } // for (all block y pos)
 
 
    // compute average gradient strengths
    for (int celly=0; celly< cells_in_y_dir; celly++)
    {
        for (int cellx=0; cellx< cells_in_x_dir; cellx++)
        {
 
            float NrUpdatesForThisCell = (float)cellUpdateCounter[celly][cellx];
 
            // compute average gradient strenghts for each gradient bin direction
            for (int bin=0; bin< gradientBinSize; bin++)
            {
                gradientStrengths[celly][cellx][bin] /= NrUpdatesForThisCell;
            }
        }
    }
 
 
    cout << "descriptorDataIdx = " << descriptorDataIdx << endl;
 
    // draw cells
    for (int celly=0; celly< cells_in_y_dir; celly++)
    {
        for (int cellx=0; cellx< cells_in_x_dir; cellx++)
        {
            int drawX = cellx * cellSize.width;
            int drawY = celly * cellSize.height;
 
            int mx = drawX + cellSize.width/2;
            int my = drawY + cellSize.height/2;
 
            rectangle(visual_image,
                      Point(drawX*scaleFactor,drawY*scaleFactor),
                      Point((drawX+cellSize.width)*scaleFactor,
                      (drawY+cellSize.height)*scaleFactor),
                      CV_RGB(100,100,100),
                      1);
 
            // draw in each cell all 9 gradient strengths
            for (int bin=0; bin< gradientBinSize; bin++)
            {
                float currentGradStrength = gradientStrengths[celly][cellx][bin];
 
                // no line to draw?
                if (currentGradStrength==0)
                    continue;
 
                float currRad = bin * radRangeForOneBin + radRangeForOneBin/2;
 
                float dirVecX = cos( currRad );
                float dirVecY = sin( currRad );
                float maxVecLen = cellSize.width/2;
                float scale = viz_factor; // just a visual_imagealization scale,
                                          // to see the lines better
 
                // compute line coordinates
                float x1 = mx - dirVecX * currentGradStrength * maxVecLen * scale;
                float y1 = my - dirVecY * currentGradStrength * maxVecLen * scale;
                float x2 = mx + dirVecX * currentGradStrength * maxVecLen * scale;
                float y2 = my + dirVecY * currentGradStrength * maxVecLen * scale;
 
                // draw gradient visual_imagealization
                line(visual_image,
                     Point(x1*scaleFactor,y1*scaleFactor),
                     Point(x2*scaleFactor,y2*scaleFactor),
                     CV_RGB(0,0,255),
                     1);
 
            } // for (all bins)
 
        } // for (cellx)
    } // for (celly)
 
 
    // don't forget to free memory allocated by helper data structures!
    for (int y=0; y< cells_in_y_dir; y++)
    {
      for (int x=0; x< cells_in_x_dir; x++)
      {
           delete[] gradientStrengths[y][x];            
      }
      delete[] gradientStrengths[y];
      delete[] cellUpdateCounter[y];
    }
    delete[] gradientStrengths;
    delete[] cellUpdateCounter;
 
    return visual_image;
 
}