diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index dfa605dbb0..09b5abdd76 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -518,8 +518,7 @@ public: virtual CvSVMParams get_params() const { return params; }; CV_WRAP virtual void clear(); - // return a single vector for HOG detector. - virtual void get_svm_detector( std::vector< float > & detector ) const; + virtual const CvSVMDecisionFunc* get_decision_function() const { return decision_func; } static CvParamGrid get_default_grid( int param_id ); diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index f7cf28d5a5..ca538ad5cc 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1245,38 +1245,6 @@ const float* CvSVM::get_support_vector(int i) const return sv && (unsigned)i < (unsigned)sv_total ? sv[i] : 0; } -void CvSVM::get_svm_detector( std::vector< float > & detector ) const -{ - CV_Assert( var_all > 0 && - sv_total > 0 && - sv != 0 && - decision_func != 0 && - decision_func->alpha != 0 && - decision_func->sv_count == sv_total ); - float svi = 0.f; - - detector.clear(); //clear stuff in vector. - detector.reserve( var_all + 1 ); //reserve place for memory efficiency. - - /** - * detector^i = \sum_j support_vector_j^i * \alpha_j - * detector^dim = -\rho - */ - for( int i = 0 ; i < var_all ; ++i ) - { - svi = 0.f; - for( int j = 0 ; j < sv_total ; ++j ) - { - if( decision_func->sv_index != NULL ) // sometime the sv_index isn't store on YML/XML. - svi += (float)( sv[decision_func->sv_index[j]][i] * decision_func->alpha[ j ] ); - else - svi += (float)( sv[j][i] * decision_func->alpha[ j ] ); - } - detector.push_back( svi ); - } - detector.push_back( (float)-decision_func->rho ); -} - bool CvSVM::set_params( const CvSVMParams& _params ) { bool ok = false; diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index eeaafa831b..ae2d1963bf 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -11,22 +11,64 @@ using namespace cv; using namespace std; +void get_svm_detector(const SVM& svm, vector< float > & hog_detector ) +{ + // get the number of variables + const int var_all = svm.get_var_count(); + // get the number of support vectors + const int sv_total = svm.get_support_vector_count(); + // get the decision function + const CvSVMDecisionFunc* decision_func = svm.get_decision_function(); + // get the support vectors + const float** sv = &(svm.get_support_vector(0)); + + CV_Assert( var_all > 0 && + sv_total > 0 && + decision_func != 0 && + decision_func->alpha != 0 && + decision_func->sv_count == sv_total ); + + float svi = 0.f; + + hog_detector.clear(); //clear stuff in vector. + hog_detector.reserve( var_all + 1 ); //reserve place for memory efficiency. + + /** + * hog_detector^i = \sum_j support_vector_j^i * \alpha_j + * hog_detector^dim = -\rho + */ + for( int i = 0 ; i < var_all ; ++i ) + { + svi = 0.f; + for( int j = 0 ; j < sv_total ; ++j ) + { + if( decision_func->sv_index != NULL ) // sometime the sv_index isn't store on YML/XML. + svi += (float)( sv[decision_func->sv_index[j]][i] * decision_func->alpha[ j ] ); + else + svi += (float)( sv[j][i] * decision_func->alpha[ j ] ); + } + hog_detector.push_back( svi ); + } + hog_detector.push_back( (float)-decision_func->rho ); +} + + /* - * Convert training/testing set to be used by OpenCV Machine Learning algorithms. - * TrainData is a matrix of size (#samples x max(#cols,#rows) per samples), in 32FC1. - * Transposition of samples are made if needed. - */ +* Convert training/testing set to be used by OpenCV Machine Learning algorithms. +* TrainData is a matrix of size (#samples x max(#cols,#rows) per samples), in 32FC1. +* Transposition of samples are made if needed. +*/ void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainData ) { - //--Convert data + //--Convert data const int rows = (int)train_samples.size(); const int cols = (int)std::max( train_samples[0].cols, train_samples[0].rows ); cv::Mat tmp(1, cols, CV_32FC1); //< used for transposition if needed - trainData = cv::Mat(rows, cols, CV_32FC1 ); - auto& itr = train_samples.begin(); - auto& end = train_samples.end(); - for( int i = 0 ; itr != end ; ++itr, ++i ) - { + trainData = cv::Mat(rows, cols, CV_32FC1 ); + auto& itr = train_samples.begin(); + auto& end = train_samples.end(); + for( int i = 0 ; itr != end ; ++itr, ++i ) + { CV_Assert( itr->cols == 1 || itr->rows == 1 ); if( itr->cols == 1 ) @@ -38,7 +80,7 @@ void convert_to_ml(const std::vector< cv::Mat > & train_samples, cv::Mat& trainD { itr->copyTo( trainData.row( i ) ); } - } + } } void load_images( const string & prefix, const string & filename, vector< Mat > & img_lst ) @@ -52,7 +94,7 @@ void load_images( const string & prefix, const string & filename, vector< Mat > cerr << "Unable to open the list of images from " << filename << " filename." << endl; exit( -1 ); } - + while( 1 ) { getline( file, line ); @@ -102,12 +144,12 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, float zoomFac = 3; Mat visu; resize(color_origImg, visu, Size(color_origImg.cols*zoomFac, color_origImg.rows*zoomFac)); - + int blockSize = 16; int cellSize = 8; int gradientBinSize = 9; float radRangeForOneBin = CV_PI/(float)gradientBinSize; // dividing 180° into 9 bins, how large (in rad) is one bin? - + // prepare data structure: 9 orientation / gradient strenghts for each cell int cells_in_x_dir = DIMX / cellSize; int cells_in_y_dir = DIMY / cellSize; @@ -122,22 +164,22 @@ Mat get_hogdescriptor_visu(Mat& color_origImg, vector& descriptorValues, { gradientStrengths[y][x] = new float[gradientBinSize]; cellUpdateCounter[y][x] = 0; - + for (int bin=0; bin& descriptorValues, cellx++; celly++; } - + for (int bin=0; bin& descriptorValues, } } } - + // draw cells for (int celly=0; celly& descriptorValues, { int drawX = cellx * cellSize; int drawY = celly * cellSize; - + int mx = drawX + cellSize/2; int my = drawY + cellSize/2; - + rectangle(visu, Point(drawX*zoomFac,drawY*zoomFac), Point((drawX+cellSize)*zoomFac,(drawY+cellSize)*zoomFac), CV_RGB(100,100,100), 1); - + // draw in each cell all 9 gradient strengths for (int bin=0; bin & img_lst, vector< Mat > & gradient_lst, const Size & size ) @@ -322,7 +364,7 @@ void test_it( const Size & size ) Scalar reference( 0, 255, 0 ); Scalar trained( 0, 0, 255 ); Mat img, draw; - SVM svm; + MySVM svm; HOGDescriptor hog; HOGDescriptor my_hog; my_hog.winSize = size; @@ -333,7 +375,7 @@ void test_it( const Size & size ) svm.load( "my_people_detector.yml" ); // Set the trained svm to my_hog vector< float > hog_detector; - svm.get_svm_detector( hog_detector ); + get_svm_detector( svm, hog_detector ); my_hog.setSVMDetector( hog_detector ); // Set the people detector. hog.setSVMDetector( hog.getDefaultPeopleDetector() ); @@ -344,7 +386,7 @@ void test_it( const Size & size ) cerr << "Unable to open the device 0" << endl; exit( -1 ); } - + while( true ) { video >> img; @@ -352,7 +394,7 @@ void test_it( const Size & size ) break; draw = img.clone(); - + locations.clear(); hog.detectMultiScale( img, locations ); draw_locations( draw, locations, reference ); @@ -373,8 +415,8 @@ int main( int argc, char** argv ) if( argc != 4 ) { cout << "Wrong number of parameters." << endl - << "Usage: " << argv[0] << " pos_dir pos.lst neg_dir neg.lst" << endl - << "example: " << argv[0] << " /INRIA_dataset/ Train/pos.lst /INRIA_dataset/ Train/neg.lst" << endl; + << "Usage: " << argv[0] << " pos_dir pos.lst neg_dir neg.lst" << endl + << "example: " << argv[0] << " /INRIA_dataset/ Train/pos.lst /INRIA_dataset/ Train/neg.lst" << endl; exit( -1 ); } vector< Mat > pos_lst;