int main( int argc, char* argv[] ) { CvCascadeClassifier classifier; string cascadeDirName, vecName, bgName; int numPos = 2000; int numNeg = 1000; int numStages = 20; int numThreads = getNumThreads(); int precalcValBufSize = 256, precalcIdxBufSize = 256; bool baseFormatSave = false; CvCascadeParams cascadeParams; CvCascadeBoostParams stageParams; Ptr<CvFeatureParams> featureParams[] = { makePtr<CvHaarFeatureParams>(), makePtr<CvLBPFeatureParams>(), makePtr<CvHOGFeatureParams>() }; int fc = sizeof(featureParams)/sizeof(featureParams[0]); if( argc == 1 ) { cout << "Usage: " << argv[0] << endl; cout << " -data <cascade_dir_name>" << endl; cout << " -vec <vec_file_name>" << endl; cout << " -bg <background_file_name>" << endl; cout << " [-numPos <number_of_positive_samples = " << numPos << ">]" << endl; cout << " [-numNeg <number_of_negative_samples = " << numNeg << ">]" << endl; cout << " [-numStages <number_of_stages = " << numStages << ">]" << endl; cout << " [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = " << precalcValBufSize << ">]" << endl; cout << " [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = " << precalcIdxBufSize << ">]" << endl; cout << " [-baseFormatSave]" << endl; cout << " [-numThreads <max_number_of_threads = " << numThreads << ">]" << endl; cascadeParams.printDefaults(); stageParams.printDefaults(); for( int fi = 0; fi < fc; fi++ ) featureParams[fi]->printDefaults(); return 0; } for( int i = 1; i < argc; i++ ) { bool set = false; if( !strcmp( argv[i], "-data" ) ) { cascadeDirName = argv[++i]; } else if( !strcmp( argv[i], "-vec" ) ) { vecName = argv[++i]; } else if( !strcmp( argv[i], "-bg" ) ) { bgName = argv[++i]; } else if( !strcmp( argv[i], "-numPos" ) ) { numPos = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-numNeg" ) ) { numNeg = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-numStages" ) ) { numStages = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-precalcValBufSize" ) ) { precalcValBufSize = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-precalcIdxBufSize" ) ) { precalcIdxBufSize = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-baseFormatSave" ) ) { baseFormatSave = true; } else if( !strcmp( argv[i], "-numThreads" ) ) { numThreads = atoi(argv[++i]); } else if ( cascadeParams.scanAttr( argv[i], argv[i+1] ) ) { i++; } else if ( stageParams.scanAttr( argv[i], argv[i+1] ) ) { i++; } else if ( !set ) { for( int fi = 0; fi < fc; fi++ ) { set = featureParams[fi]->scanAttr(argv[i], argv[i+1]); if ( !set ) { i++; break; } } } } setNumThreads( numThreads ); classifier.train( cascadeDirName, vecName, bgName, numPos, numNeg, precalcValBufSize, precalcIdxBufSize, numStages, cascadeParams, *featureParams[cascadeParams.featureType], stageParams, baseFormatSave ); return 0; }
int main( int argc, char* argv[] ) { // переменные и классы CvCascadeClassifier classifier; // from cascadeclassifier.h string cascadeDirName, vecName, bgName; int numPos = 2000; // Number of positive samples used in training for every classifier stage. int numNeg = 1000; // Number of negative samples used in training for every classifier stage. int numStages = 20; // Number of cascade stages to be trained. int numThreads = getNumThreads(); // Maximum number of threads to use during training. Notice that the actual number of used // threads may be lower, depending on your machine and compilation options. // Function getNumThreads() from opencv2/core.hpp int precalcValBufSize = 1024, // Size of buffer for precalculated feature values (in Mb). precalcIdxBufSize = 1024; // Size of buffer for precalculated feature indices (in Mb). The more memory you have the // faster the training process. bool baseFormatSave = false; // This argument is actual in case of Haar-like features. If it is specified, the cascade will // be saved in the old format. double acceptanceRatioBreakValue = -1.0; // This argument is used to determine how precise your model should keep learning and // when to stop. A good guideline is to train not further than 10e-5, to ensure // the model does not overtrain on your training data. By default this value is // set to -1 to disable this feature. // Cascade parameters: CvCascadeParams cascadeParams; // from cascadeclassifier.h // здесь устанавливаются стандартные параметры каскада: // // CvCascadeParams::CvCascadeParams() : stageType( defaultStageType ), // Type of stages. Only boosted classifier are supported as a stage type at the moment. // // -stageType <BOOST(default)> // featureType( defaultFeatureType ), // Type of features: HAAR - Haar-like features, // // LBP - local binary patterns. // // -featureType<{HAAR(default), LBP}> // winSize( cvSize(24, 24) ) // Size of training samples (in pixels). Must have exactly // // the same values as used during training samples creation // // (opencv_createsamples utility). // { // name = CC_CASCADE_PARAMS; // } // Boosted classifer parameters: CvCascadeBoostParams stageParams; // from cascadeclassifier.h <-- boost.h // CvCascadeBoostParams( int _boostType, // Type of boosted classifiers: // // DAB - Discrete AdaBoost, // // RAB - Real AdaBoost, // // LB - LogitBoost, // // GAB - Gentle AdaBoost. // // -bt <{DAB, RAB, LB, GAB(default)}> // float _minHitRate, // Minimal desired hit rate for each stage of the classifier. Overall hit rate may be estimated // // as (min_hit_rate\^number_of_stages). // // -minHitRate <min_hit_rate> // float _maxFalseAlarm, // Maximal desired false alarm rate for each stage of the classifier. Overall false alarm rate // // may be estimated as (max_false_alarm_rate\^number_of_stages). // // -maxFalseAlarmRate <max_false_alarm_rate> // double _weightTrimRate, // Specifies whether trimming should be used and its weight. A decent choice is 0.95. // // -weightTrimRate <weight_trim_rate> // int _maxDepth, // Maximal depth of a weak tree. A decent choice is 1, that is case of stumps. // // -maxDepth <max_depth_of_weak_tree> // int _maxWeakCount ); // Maximal count of weak trees for every cascade stage. The boosted classifier (stage) will // // have so many weak trees (<=maxWeakCount), as needed to achieve the given -maxFalseAlarmRate. // // -maxWeakCount <max_weak_tree_count> // вот здесь непонятно, массив из фичей Haar, LBP и HOG! Ptr<CvFeatureParams> featureParams[] = { makePtr<CvHaarFeatureParams>(), makePtr<CvLBPFeatureParams>(), makePtr<CvHOGFeatureParams>() }; int fc = sizeof(featureParams)/sizeof(featureParams[0]); // вычисление размера массива // здесь проиходит вывод справочной инфы, если не были переданы параметры if( argc == 1 ) { cout << "Usage: " << argv[0] << endl; cout << " -data <cascade_dir_name>" << endl; cout << " -vec <vec_file_name>" << endl; cout << " -bg <background_file_name>" << endl; cout << " [-numPos <number_of_positive_samples = " << numPos << ">]" << endl; cout << " [-numNeg <number_of_negative_samples = " << numNeg << ">]" << endl; cout << " [-numStages <number_of_stages = " << numStages << ">]" << endl; cout << " [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = " << precalcValBufSize << ">]" << endl; cout << " [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = " << precalcIdxBufSize << ">]" << endl; cout << " [-baseFormatSave]" << endl; cout << " [-numThreads <max_number_of_threads = " << numThreads << ">]" << endl; cout << " [-acceptanceRatioBreakValue <value> = " << acceptanceRatioBreakValue << ">]" << endl; cascadeParams.printDefaults(); stageParams.printDefaults(); for( int fi = 0; fi < fc; fi++ ) featureParams[fi]->printDefaults(); return 0; } // распознавание аргументов командной строки Common arguments: // -data <cascade_dir_name> // -vec <vec_file_name> // -bg <background_file_name> // -numPos <number_of_positive_samples> // -numNeg <number_of_negative_samples> // -numStages <number_of_stages> // -precalcValBufSize <precalculated_vals_buffer_size_in_Mb> // -precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb> // -baseFormatSave // -numThreads <max_number_of_threads> // -acceptanceRatioBreakValue <break_value> for( int i = 1; i < argc; i++ ) { bool set = false; if( !strcmp( argv[i], "-data" ) ) { cascadeDirName = argv[++i]; } else if( !strcmp( argv[i], "-vec" ) ) { vecName = argv[++i]; } else if( !strcmp( argv[i], "-bg" ) ) { bgName = argv[++i]; } else if( !strcmp( argv[i], "-numPos" ) ) { numPos = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-numNeg" ) ) { numNeg = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-numStages" ) ) { numStages = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-precalcValBufSize" ) ) { precalcValBufSize = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-precalcIdxBufSize" ) ) { precalcIdxBufSize = atoi( argv[++i] ); } else if( !strcmp( argv[i], "-baseFormatSave" ) ) { baseFormatSave = true; } else if( !strcmp( argv[i], "-numThreads" ) ) { numThreads = atoi(argv[++i]); } else if( !strcmp( argv[i], "-acceptanceRatioBreakValue" ) ) { acceptanceRatioBreakValue = atof(argv[++i]); } // распознавание аргументов командной строки Cascade parameters: else if ( cascadeParams.scanAttr( argv[i], argv[i+1] ) ) { i++; } // распознавание аргументов командной строки Boosted classifer parameters: else if ( stageParams.scanAttr( argv[i], argv[i+1] ) ) { i++; } // что-то происходит, если ещё какие параметры идут, возможно, Haar-like feature parameters: // -mode <BASIC (default) | CORE | ALL> // Selects the type of Haar features set used in training. BASIC use only upright features, while ALL uses // the full set of upright and 45 degree rotated feature set. See [86] for more details. else if ( !set ) { for( int fi = 0; fi < fc; fi++ ) { set = featureParams[fi]->scanAttr(argv[i], argv[i+1]); if ( !set ) { i++; break; } } } } // set max_number_of_threads // Maximum number of threads to use during training. Notice that the actual number of used // threads may be lower, depending on your machine and compilation options. setNumThreads( numThreads ); // метод train определён в cascadeclassifier.h, он тренирует классификатор и сохраняет его в xml-file // After the traincascade application has finished its work, the trained cascade will be saved // in cascade.xml file in the folder, which was passed as -data parameter. Other files in this folder // are created for the case of interrupted training, so you may delete them after completion of training. classifier.train( cascadeDirName, vecName, bgName, numPos, numNeg, precalcValBufSize, precalcIdxBufSize, numStages, cascadeParams, *featureParams[cascadeParams.featureType], stageParams, baseFormatSave, acceptanceRatioBreakValue ); return 0; }