Update train_HOG.cpp
authorSuleyman TURKMEN <sturkmen@hotmail.com>
Sat, 18 Nov 2017 22:41:24 +0000 (01:41 +0300)
committerSuleyman TURKMEN <sturkmen@hotmail.com>
Sun, 3 Dec 2017 20:47:54 +0000 (23:47 +0300)
samples/cpp/train_HOG.cpp

index 4d1dcf8..1ffac4c 100644 (file)
@@ -10,14 +10,14 @@ using namespace cv;
 using namespace cv::ml;
 using namespace std;
 
-void get_svm_detector( const Ptr< SVM > & svm, vector< float > & hog_detector );
+vector< float > get_svm_detector( const Ptr< SVM >& svm );
 void convert_to_ml( const std::vector< Mat > & train_samples, Mat& trainData );
 void load_images( const String & dirname, vector< Mat > & img_lst, bool showImages );
 void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, const Size & size );
-void computeHOGs( const Size wsize, const vector< Mat > & img_lst, vector< Mat > & gradient_lst );
-int test_trained_detector( String obj_det_filename, String test_dir, String videofilename );
+void computeHOGs( const Size wsize, const vector< Mat > & img_lst, vector< Mat > & gradient_lst, bool use_flip );
+void test_trained_detector( String obj_det_filename, String test_dir, String videofilename );
 
-void get_svm_detector( const Ptr< SVM >& svm, vector< float > & hog_detector )
+vector< float > get_svm_detector( const Ptr< SVM >& svm )
 {
     // get the support vectors
     Mat sv = svm->getSupportVectors();
@@ -30,11 +30,11 @@ void get_svm_detector( const Ptr< SVM >& svm, vector< float > & hog_detector )
     CV_Assert( (alpha.type() == CV_64F && alpha.at<double>(0) == 1.) ||
                (alpha.type() == CV_32F && alpha.at<float>(0) == 1.f) );
     CV_Assert( sv.type() == CV_32F );
-    hog_detector.clear();
 
-    hog_detector.resize(sv.cols + 1);
+    vector< float > hog_detector( sv.cols + 1 );
     memcpy( &hog_detector[0], sv.ptr(), sv.cols*sizeof( hog_detector[0] ) );
     hog_detector[sv.cols] = (float)-rho;
+    return hog_detector;
 }
 
 /*
@@ -101,35 +101,44 @@ void sample_neg( const vector< Mat > & full_neg_lst, vector< Mat > & neg_lst, co
     srand( (unsigned int)time( NULL ) );
 
     for ( size_t i = 0; i < full_neg_lst.size(); i++ )
-    {
-        box.x = rand() % ( full_neg_lst[i].cols - size_x );
-        box.y = rand() % ( full_neg_lst[i].rows - size_y );
-        Mat roi = full_neg_lst[i]( box );
-        neg_lst.push_back( roi.clone() );
-    }
+        if ( full_neg_lst[i].cols >= box.width && full_neg_lst[i].rows >= box.height )
+        {
+            box.x = rand() % ( full_neg_lst[i].cols - size_x );
+            box.y = rand() % ( full_neg_lst[i].rows - size_y );
+            Mat roi = full_neg_lst[i]( box );
+            neg_lst.push_back( roi.clone() );
+        }
 }
 
-void computeHOGs( const Size wsize, const vector< Mat > & img_lst, vector< Mat > & gradient_lst )
+void computeHOGs( const Size wsize, const vector< Mat > & img_lst, vector< Mat > & gradient_lst, bool use_flip )
 {
     HOGDescriptor hog;
     hog.winSize = wsize;
-
-    Rect r = Rect( 0, 0, wsize.width, wsize.height );
-    r.x += ( img_lst[0].cols - r.width ) / 2;
-    r.y += ( img_lst[0].rows - r.height ) / 2;
-
     Mat gray;
     vector< float > descriptors;
 
-    for( size_t i=0 ; i< img_lst.size(); i++ )
+    for( size_t i = 0 ; i < img_lst.size(); i++ )
     {
-        cvtColor( img_lst[i](r), gray, COLOR_BGR2GRAY );
-        hog.compute( gray, descriptors, Size( 8, 8 ), Size( 0, 0 ) );
-        gradient_lst.push_back( Mat( descriptors ).clone() );
+        if ( img_lst[i].cols >= wsize.width && img_lst[i].rows >= wsize.height )
+        {
+            Rect r = Rect(( img_lst[i].cols - wsize.width ) / 2,
+                          ( img_lst[i].rows - wsize.height ) / 2,
+                          wsize.width,
+                          wsize.height);
+            cvtColor( img_lst[i](r), gray, COLOR_BGR2GRAY );
+            hog.compute( gray, descriptors, Size( 8, 8 ), Size( 0, 0 ) );
+            gradient_lst.push_back( Mat( descriptors ).clone() );
+            if ( use_flip )
+            {
+                flip( gray, gray, 1 );
+                hog.compute( gray, descriptors, Size( 8, 8 ), Size( 0, 0 ) );
+                gradient_lst.push_back( Mat( descriptors ).clone() );
+            }
+        }
     }
 }
 
-int test_trained_detector( String obj_det_filename, String test_dir, String videofilename )
+void test_trained_detector( String obj_det_filename, String test_dir, String videofilename )
 {
     cout << "Testing trained detector..." << endl;
     HOGDescriptor hog;
@@ -143,7 +152,10 @@ int test_trained_detector( String obj_det_filename, String test_dir, String vide
 
     if ( videofilename != "" )
     {
-        cap.open( videofilename );
+        if ( videofilename.size() == 1 && isdigit( videofilename[0] ) )
+            cap.open( videofilename[0] - '0' );
+        else
+            cap.open( videofilename );
     }
 
     obj_det_filename = "testing " + obj_det_filename;
@@ -165,7 +177,7 @@ int test_trained_detector( String obj_det_filename, String test_dir, String vide
 
         if ( img.empty() )
         {
-            return 0;
+            return;
         }
 
         vector< Rect > detections;
@@ -180,12 +192,11 @@ int test_trained_detector( String obj_det_filename, String test_dir, String vide
 
         imshow( obj_det_filename, img );
 
-        if( 27 == waitKey( delay ) )
+        if( waitKey( delay ) == 27 )
         {
-            return 0;
+            return;
         }
     }
-    return 0;
 }
 
 int main( int argc, char** argv )
@@ -199,6 +210,7 @@ int main( int argc, char** argv )
         "{tv    |     | test video file name}"
         "{dw    |     | width of the detector}"
         "{dh    |     | height of the detector}"
+        "{f     |false| indicates if the program will generate and use mirrored samples or not}"
         "{d     |false| train twice}"
         "{t     |false| test a trained detector}"
         "{v     |false| visualize training steps}"
@@ -223,6 +235,7 @@ int main( int argc, char** argv )
     bool test_detector = parser.get< bool >( "t" );
     bool train_twice = parser.get< bool >( "d" );
     bool visualization = parser.get< bool >( "v" );
+    bool flip_samples = parser.get< bool >( "f" );
 
     if ( test_detector )
     {
@@ -234,8 +247,8 @@ int main( int argc, char** argv )
     {
         parser.printMessage();
         cout << "Wrong number of parameters.\n\n"
-             << "Example command line:\n" << argv[0] << " -pd=/INRIAPerson/96X160H96/Train/pos -nd=/INRIAPerson/neg -td=/INRIAPerson/Test/pos -fn=HOGpedestrian96x160.yml -d\n"
-             << "\nExample command line for testing trained detector:\n" << argv[0] << " -t -dw=96 -dh=160 -fn=HOGpedestrian96x160.yml -td=/INRIAPerson/Test/pos";
+             << "Example command line:\n" << argv[0] << " -dw=64 -dh=128 -pd=/INRIAPerson/96X160H96/Train/pos -nd=/INRIAPerson/neg -td=/INRIAPerson/Test/pos -fn=HOGpedestrian64x128.xml -d\n"
+             << "\nExample command line for testing trained detector:\n" << argv[0] << " -t -fn=HOGpedestrian64x128.xml -td=/INRIAPerson/Test/pos";
         exit( 1 );
     }
 
@@ -256,40 +269,40 @@ int main( int argc, char** argv )
 
     Size pos_image_size = pos_lst[0].size();
 
-    for ( size_t i = 0; i < pos_lst.size(); ++i )
-    {
-        if( pos_lst[i].size() != pos_image_size )
-        {
-            cout << "All positive images should be same size!" << endl;
-            exit( 1 );
-        }
-    }
-
-    pos_image_size = pos_image_size / 8 * 8;
-
     if ( detector_width && detector_height )
     {
         pos_image_size = Size( detector_width, detector_height );
     }
-
-    labels.assign( pos_lst.size(), +1 );
-    const unsigned int old = (unsigned int)labels.size();
+    else
+    {
+        for ( size_t i = 0; i < pos_lst.size(); ++i )
+        {
+            if( pos_lst[i].size() != pos_image_size )
+            {
+                cout << "All positive images should be same size!" << endl;
+                exit( 1 );
+            }
+        }
+        pos_image_size = pos_image_size / 8 * 8;
+    }
 
     clog << "Negative images are being loaded...";
     load_images( neg_dir, full_neg_lst, false );
     sample_neg( full_neg_lst, neg_lst, pos_image_size );
     clog << "...[done]" << endl;
 
-    labels.insert( labels.end(), neg_lst.size(), -1 );
-    CV_Assert( old < labels.size() );
-
     clog << "Histogram of Gradients are being calculated for positive images...";
-    computeHOGs( pos_image_size, pos_lst, gradient_lst );
-    clog << "...[done]" << endl;
+    computeHOGs( pos_image_size, pos_lst, gradient_lst, flip_samples );
+    size_t positive_count = gradient_lst.size();
+    labels.assign( positive_count, +1 );
+    clog << "...[done] ( positive count : " << positive_count << " )" << endl;
 
     clog << "Histogram of Gradients are being calculated for negative images...";
-    computeHOGs( pos_image_size, neg_lst, gradient_lst );
-    clog << "...[done]" << endl;
+    computeHOGs( pos_image_size, neg_lst, gradient_lst, flip_samples );
+    size_t negative_count = gradient_lst.size() - positive_count;
+    labels.insert( labels.end(), negative_count, -1 );
+    CV_Assert( positive_count < labels.size() );
+    clog << "...[done] ( negative count : " << negative_count << " )" << endl;
 
     Mat train_data;
     convert_to_ml( gradient_lst, train_data );
@@ -306,7 +319,7 @@ int main( int argc, char** argv )
     svm->setP( 0.1 ); // for EPSILON_SVR, epsilon in loss function?
     svm->setC( 0.01 ); // From paper, soft classifier
     svm->setType( SVM::EPS_SVR ); // C_SVC; // EPSILON_SVR; // may be also NU_SVR; // do regression task
-    svm->train( train_data, ROW_SAMPLE, Mat( labels ) );
+    svm->train( train_data, ROW_SAMPLE, labels );
     clog << "...[done]" << endl;
 
     if ( train_twice )
@@ -316,22 +329,25 @@ int main( int argc, char** argv )
         my_hog.winSize = pos_image_size;
 
         // Set the trained svm to my_hog
-        vector< float > hog_detector;
-        get_svm_detector( svm, hog_detector );
-        my_hog.setSVMDetector( hog_detector );
+        my_hog.setSVMDetector( get_svm_detector( svm ) );
 
         vector< Rect > detections;
         vector< double > foundWeights;
 
         for ( size_t i = 0; i < full_neg_lst.size(); i++ )
         {
-            my_hog.detectMultiScale( full_neg_lst[i], detections, foundWeights );
+            if ( full_neg_lst[i].cols >= pos_image_size.width && full_neg_lst[i].rows >= pos_image_size.height )
+                my_hog.detectMultiScale( full_neg_lst[i], detections, foundWeights );
+            else
+                detections.clear();
+
             for ( size_t j = 0; j < detections.size(); j++ )
             {
                 Mat detection = full_neg_lst[i]( detections[j] ).clone();
                 resize( detection, detection, pos_image_size );
                 neg_lst.push_back( detection );
             }
+
             if ( visualization )
             {
                 for ( size_t j = 0; j < detections.size(); j++ )
@@ -344,30 +360,30 @@ int main( int argc, char** argv )
         }
         clog << "...[done]" << endl;
 
-        labels.clear();
-        labels.assign( pos_lst.size(), +1 );
-        labels.insert( labels.end(), neg_lst.size(), -1);
-
         gradient_lst.clear();
         clog << "Histogram of Gradients are being calculated for positive images...";
-        computeHOGs( pos_image_size, pos_lst, gradient_lst );
-        clog << "...[done]" << endl;
+        computeHOGs( pos_image_size, pos_lst, gradient_lst, flip_samples );
+        positive_count = gradient_lst.size();
+        clog << "...[done] ( positive count : " << positive_count << " )" << endl;
 
         clog << "Histogram of Gradients are being calculated for negative images...";
-        computeHOGs( pos_image_size, neg_lst, gradient_lst );
-        clog << "...[done]" << endl;
+        computeHOGs( pos_image_size, neg_lst, gradient_lst, flip_samples );
+        negative_count = gradient_lst.size() - positive_count;
+        clog << "...[done] ( negative count : " << negative_count << " )" << endl;
+
+        labels.clear();
+        labels.assign(positive_count, +1);
+        labels.insert(labels.end(), negative_count, -1);
 
         clog << "Training SVM again...";
         convert_to_ml( gradient_lst, train_data );
-        svm->train( train_data, ROW_SAMPLE, Mat( labels ) );
+        svm->train( train_data, ROW_SAMPLE, labels );
         clog << "...[done]" << endl;
     }
 
-    vector< float > hog_detector;
-    get_svm_detector( svm, hog_detector );
     HOGDescriptor hog;
     hog.winSize = pos_image_size;
-    hog.setSVMDetector( hog_detector );
+    hog.setSVMDetector( get_svm_detector( svm ) );
     hog.save( obj_det_filename );
 
     test_trained_detector( obj_det_filename, test_dir, videofilename );