bool CvCascadeClassifier::load( const string cascadeDirName ) { FileStorage fs( cascadeDirName + CC_PARAMS_FILENAME, FileStorage::READ ); if ( !fs.isOpened() ) return false; FileNode node = fs.getFirstTopLevelNode(); if ( !readParams( node ) ) return false; featureEvaluator = CvFeatureEvaluator::create(cascadeParams.featureType); featureEvaluator->init( ((CvFeatureParams*)featureParams), numPos + numNeg, cascadeParams.winSize ); fs.release(); char buf[10]; for ( int si = 0; si < numStages; si++ ) { sprintf( buf, "%s%d", "stage", si); fs.open( cascadeDirName + buf + ".xml", FileStorage::READ ); node = fs.getFirstTopLevelNode(); if ( !fs.isOpened() ) break; CvCascadeBoost *tempStage = new CvCascadeBoost; if ( !tempStage->read( node, (CvFeatureEvaluator*)featureEvaluator, *((CvCascadeBoostParams*)stageParams )) ) { delete tempStage; fs.release(); break; } stageClassifiers.push_back(tempStage); } return true; }
bool CvCascadeClassifier::readStages( const FileNode &node) { FileNode rnode = node[CC_STAGES]; if (!rnode.empty() || !rnode.isSeq()) return false; stageClassifiers.reserve(numStages); FileNodeIterator it = rnode.begin(); for( int i = 0; i < min( (int)rnode.size(), numStages ); i++, it++ ) { CvCascadeBoost* tempStage = new CvCascadeBoost; if ( !tempStage->read( *it, (CvFeatureEvaluator *)featureEvaluator, *((CvCascadeBoostParams*)stageParams) ) ) { delete tempStage; return false; } stageClassifiers.push_back(tempStage); } return true; }
bool CvCascadeClassifier::train( const string _cascadeDirName, const string _posFilename, const string _negFilename, int _numPos, int _numNeg, int _precalcValBufSize, int _precalcIdxBufSize, int _numStages, const CvCascadeParams& _cascadeParams, const CvFeatureParams& _featureParams, const CvCascadeBoostParams& _stageParams, bool baseFormatSave, double acceptanceRatioBreakValue) { // Start recording clock ticks for training time output const clock_t begin_time = clock(); if( _cascadeDirName.empty() || _posFilename.empty() || _negFilename.empty() ) CV_Error( CV_StsBadArg, "_cascadeDirName or _bgfileName or _vecFileName is NULL" ); string dirName; if (_cascadeDirName.find_last_of("/\\") == (_cascadeDirName.length() - 1) ) dirName = _cascadeDirName; else dirName = _cascadeDirName + '/'; numPos = _numPos; numNeg = _numNeg; numStages = _numStages; if ( !imgReader.create( _posFilename, _negFilename, _cascadeParams.winSize ) ) { cout << "Image reader can not be created from -vec " << _posFilename << " and -bg " << _negFilename << "." << endl; return false; } if ( !load( dirName ) ) { cascadeParams = _cascadeParams; featureParams = CvFeatureParams::create(cascadeParams.featureType); featureParams->init(_featureParams); stageParams = new CvCascadeBoostParams; *stageParams = _stageParams; featureEvaluator = CvFeatureEvaluator::create(cascadeParams.featureType); featureEvaluator->init( (CvFeatureParams*)featureParams, numPos + numNeg, cascadeParams.winSize ); stageClassifiers.reserve( numStages ); }else{ // Make sure that if model parameters are preloaded, that people are aware of this, // even when passing other parameters to the training command cout << "---------------------------------------------------------------------------------" << endl; cout << "Training parameters are pre-loaded from the parameter file in data folder!" << endl; cout << "Please empty this folder if you want to use a NEW set of training parameters." << endl; cout << "---------------------------------------------------------------------------------" << endl; } cout << "PARAMETERS:" << endl; cout << "cascadeDirName: " << _cascadeDirName << endl; cout << "vecFileName: " << _posFilename << endl; cout << "bgFileName: " << _negFilename << endl; cout << "numPos: " << _numPos << endl; cout << "numNeg: " << _numNeg << endl; cout << "numStages: " << numStages << endl; cout << "precalcValBufSize[Mb] : " << _precalcValBufSize << endl; cout << "precalcIdxBufSize[Mb] : " << _precalcIdxBufSize << endl; cout << "acceptanceRatioBreakValue : " << acceptanceRatioBreakValue << endl; cascadeParams.printAttrs(); stageParams->printAttrs(); featureParams->printAttrs(); cout << "Number of unique features given windowSize [" << _cascadeParams.winSize.width << "," << _cascadeParams.winSize.height << "] : " << featureEvaluator->getNumFeatures() << "" << endl; int startNumStages = (int)stageClassifiers.size(); if ( startNumStages > 1 ) cout << endl << "Stages 0-" << startNumStages-1 << " are loaded" << endl; else if ( startNumStages == 1) cout << endl << "Stage 0 is loaded" << endl; double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) / (double)stageParams->max_depth; double tempLeafFARate; for( int i = startNumStages; i < numStages; i++ ) { cout << endl << "===== TRAINING " << i << "-stage =====" << endl; cout << "<BEGIN" << endl; if ( !updateTrainingSet( requiredLeafFARate, tempLeafFARate ) ) { cout << "Train dataset for temp stage can not be filled. " "Branch training terminated." << endl; break; } if( tempLeafFARate <= requiredLeafFARate ) { cout << "Required leaf false alarm rate achieved. " "Branch training terminated." << endl; break; } if( (tempLeafFARate <= acceptanceRatioBreakValue) && (acceptanceRatioBreakValue >= 0) ){ cout << "The required acceptanceRatio for the model has been reached to avoid overfitting of trainingdata. " "Branch training terminated." << endl; break; } CvCascadeBoost* tempStage = new CvCascadeBoost; bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator, curNumSamples, _precalcValBufSize, _precalcIdxBufSize, *((CvCascadeBoostParams*)stageParams) ); cout << "END>" << endl; if(!isStageTrained) break; stageClassifiers.push_back( tempStage ); // save params if( i == 0) { std::string paramsFilename = dirName + CC_PARAMS_FILENAME; FileStorage fs( paramsFilename, FileStorage::WRITE); if ( !fs.isOpened() ) { cout << "Parameters can not be written, because file " << paramsFilename << " can not be opened." << endl; return false; } fs << FileStorage::getDefaultObjectName(paramsFilename) << "{"; writeParams( fs ); fs << "}"; } // save current stage char buf[10]; sprintf(buf, "%s%d", "stage", i ); string stageFilename = dirName + buf + ".xml"; FileStorage fs( stageFilename, FileStorage::WRITE ); if ( !fs.isOpened() ) { cout << "Current stage can not be written, because file " << stageFilename << " can not be opened." << endl; return false; } fs << FileStorage::getDefaultObjectName(stageFilename) << "{"; tempStage->write( fs, Mat() ); fs << "}"; // Output training time up till now float seconds = float( clock () - begin_time ) / CLOCKS_PER_SEC; int days = int(seconds) / 60 / 60 / 24; int hours = (int(seconds) / 60 / 60) % 24; int minutes = (int(seconds) / 60) % 60; int seconds_left = int(seconds) % 60; cout << "Training until now has taken " << days << " days " << hours << " hours " << minutes << " minutes " << seconds_left <<" seconds." << endl; } if(stageClassifiers.size() == 0) { cout << "Cascade classifier can't be trained. Check the used training parameters." << endl; return false; } save( dirName + CC_CASCADE_FILENAME, baseFormatSave ); return true; }
bool CvCascadeClassifier::train( const String _cascadeDirName, const String _posFilename, const String _negFilename, int _numPos, int _numNeg, int _precalcValBufSize, int _precalcIdxBufSize, int _numStages, const CvCascadeParams& _cascadeParams, const CvFeatureParams& _featureParams, const CvCascadeBoostParams& _stageParams, bool baseFormatSave ) { if( _cascadeDirName.empty() || _posFilename.empty() || _negFilename.empty() ) CV_Error( CV_StsBadArg, "_cascadeDirName or _bgfileName or _vecFileName is NULL" ); string dirName; if (_cascadeDirName.find_last_of("/\\") == (_cascadeDirName.length() - 1) ) dirName = _cascadeDirName; else dirName = _cascadeDirName + '/'; numPos = _numPos; numNeg = _numNeg; numStages = _numStages; if ( !imgReader.create( _posFilename, _negFilename, _cascadeParams.winSize ) ) { cout << "Image reader can not be created from -vec " << _posFilename << " and -bg " << _negFilename << "." << endl; return false; } if ( !load( dirName ) ) { cascadeParams = _cascadeParams; featureParams = CvFeatureParams::create(cascadeParams.featureType); featureParams->init(_featureParams); stageParams = new CvCascadeBoostParams; *stageParams = _stageParams; featureEvaluator = CvFeatureEvaluator::create(cascadeParams.featureType); featureEvaluator->init( (CvFeatureParams*)featureParams, numPos + numNeg, cascadeParams.winSize ); stageClassifiers.reserve( numStages ); } cout << "PARAMETERS:" << endl; cout << "cascadeDirName: " << _cascadeDirName << endl; cout << "vecFileName: " << _posFilename << endl; cout << "bgFileName: " << _negFilename << endl; cout << "numPos: " << _numPos << endl; cout << "numNeg: " << _numNeg << endl; cout << "numStages: " << numStages << endl; cout << "precalcValBufSize[Mb] : " << _precalcValBufSize << endl; cout << "precalcIdxBufSize[Mb] : " << _precalcIdxBufSize << endl; cascadeParams.printAttrs(); stageParams->printAttrs(); featureParams->printAttrs(); int startNumStages = (int)stageClassifiers.size(); if ( startNumStages > 1 ) cout << endl << "Stages 0-" << startNumStages-1 << " are loaded" << endl; else if ( startNumStages == 1) cout << endl << "Stage 0 is loaded" << endl; double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) / (double)stageParams->max_depth; double tempLeafFARate; for( int i = startNumStages; i < numStages; i++ ) { cout << endl << "===== TRAINING " << i << "-stage =====" << endl; cout << "<BEGIN" << endl; if ( !updateTrainingSet( tempLeafFARate ) ) { cout << "Train dataset for temp stage can not be filled. " "Branch training terminated." << endl; break; } if( tempLeafFARate <= requiredLeafFARate ) { cout << "Required leaf false alarm rate achieved. " "Branch training terminated." << endl; break; } CvCascadeBoost* tempStage = new CvCascadeBoost; bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator, curNumSamples, _precalcValBufSize, _precalcIdxBufSize, *((CvCascadeBoostParams*)stageParams) ); cout << "END>" << endl; if(!isStageTrained) break; stageClassifiers.push_back( tempStage ); // save params if( i == 0) { std::string paramsFilename = dirName + CC_PARAMS_FILENAME; FileStorage fs( paramsFilename, FileStorage::WRITE); if ( !fs.isOpened() ) { cout << "Parameters can not be written, because file " << paramsFilename << " can not be opened." << endl; return false; } fs << FileStorage::getDefaultObjectName(paramsFilename) << "{"; writeParams( fs ); fs << "}"; } // save current stage char buf[10]; sprintf(buf, "%s%d", "stage", i ); string stageFilename = dirName + buf + ".xml"; FileStorage fs( stageFilename, FileStorage::WRITE ); if ( !fs.isOpened() ) { cout << "Current stage can not be written, because file " << stageFilename << " can not be opened." << endl; return false; } fs << FileStorage::getDefaultObjectName(stageFilename) << "{"; tempStage->write( fs, Mat() ); fs << "}"; } if(stageClassifiers.size() == 0) { cout << "Cascade classifier can't be trained. Check the used training parameters." << endl; return false; } cout << "Save to " << dirName + CC_CASCADE_FILENAME <<endl; save( dirName + CC_CASCADE_FILENAME, baseFormatSave ); return true; }