int main(int argc, char** argv) { if (argc != 3) { help(); return 0; } // ------------ TRAINING PHASE { // ----- LOAD IMAGES FROM PATH QString path(argv[1]); QStringList filesToOpen = fetchFiles(path); if (filesToOpen.empty()) { help(); return 1; } // Create feature detector and descriptor extractor: cv::Ptr<cv::ORB> detector = cv::ORB::create(150); cv::Mat trainingDescriptors(0, detector->descriptorSize(), detector->descriptorType()); std::cout << "Training descriptor size & type : " << detector->descriptorSize() << ", " << detector->descriptorType() << std::endl; std::vector<cv::KeyPoint> keypoints; // Loop on files : std::cout << "Extract features from training images" << std::endl; foreach (QString file, filesToOpen) { SD_TRACE1("Open file '%1'", file); QString f = path + "/" + file; cv::Mat inImage = cv::imread(f.toStdString(), cv::IMREAD_GRAYSCALE); cv::Mat descriptors; detector->detectAndCompute(inImage, cv::Mat(), keypoints, descriptors); trainingDescriptors.push_back(descriptors); cv::Mat imageWithKeyPoints; cv::drawKeypoints(inImage, keypoints, imageWithKeyPoints); // ImageCommon::displayMat(imageWithKeyPoints, true, "Input image with keypoints"); keypoints.clear(); } std::cout << "Total number of descriptors : " << trainingDescriptors.rows << std::endl; trainingDescriptors.convertTo(trainingDescriptors, CV_32F); ImageCommon::printMat(trainingDescriptors, "trainingDescriptors"); cv::BOWKMeansTrainer bowTrainer(15); bowTrainer.add(trainingDescriptors); cv::Mat vocabulary = bowTrainer.cluster(); //ImageCommon::displayMat(vocabulary, true, "Vocabulary"); // Train }
inline void BoW::create_vocabulary(int N_cent, const string path_run_folders) { cout << "Calculating Vocabulary " << endl; cout << "# clusters: " << N_cent << endl; mat uni_features; for (uword pe=0; pe<peo_train.n_rows; ++pe) { mat mat_features_tmp; mat mat_features; for (uword act = 0 ; act < actions.n_rows; ++act) { for (uword sc = 1 ; sc <= 4; ++sc) { mat mat_features_video_i; std::stringstream ssName_feat_video; //ssName_feat_video << "./run"<< run <<"/features/train/feat_vec" << peo_train(pe) << "_" << actions(act) << "_d" << sc; ssName_feat_video << path_run_folders <<"/features_all_nor/feat_vec_" << peo_train(pe) << "_" << actions(act) << "_d" << sc; mat_features_video_i.load( ssName_feat_video.str() ); if ( mat_features_video_i.n_cols>0 ) { mat_features_tmp = join_rows( mat_features_tmp, mat_features_video_i ); } else { cout << "# vectors = 0 in " << ssName_feat_video.str() << endl; } } } cout << "mat_features_tmp.n_cols "<< mat_features_tmp.n_cols << endl; const uword N_max = 100000; // maximum number of vectors per action to create universal GMM //const uword N_max = 100000; //??? if (mat_features_tmp.n_cols > N_max) { ivec tmp1 = randi( N_max, distr_param(0,mat_features_tmp.n_cols-1) ); ivec tmp2 = unique(tmp1); uvec my_indices = conv_to<uvec>::from(tmp2); mat_features = mat_features_tmp.cols(my_indices); // extract a subset of the columns } else { mat_features = mat_features_tmp; } cout << "mat_features.n_cols "<< mat_features.n_cols << endl; if ( mat_features.n_cols>0 ) { uni_features = join_rows( uni_features, mat_features ); } else { cout << "# vectors = 0 in uni_features" << endl; } //uni_features = join_rows( uni_features, mat_features ); mat_features_tmp.reset(); mat_features.reset(); } cout << "r&c "<< uni_features.n_rows << " & " << uni_features.n_cols << endl; bool is_finite = uni_features.is_finite(); if (!is_finite ) { cout << "is_finite?? " << is_finite << endl; cout << uni_features.n_rows << " " << uni_features.n_cols << endl; getchar(); } fmat f_uni_features = conv_to< fmat >::from(uni_features); //uni_features.reset(); cv::Mat featuresUnclustered(f_uni_features.n_cols, dim, CV_32FC1, f_uni_features.memptr() ); //cv::Mat featuresUnclustered( featuresUnclusteredTMP.t() ); int rows = featuresUnclustered.rows; int cols = featuresUnclustered.cols; cout << "OpenCV rows & cols " << rows << " & " << cols << endl; //cout << "Press a Key" << endl; //getchar(); //cout << f_uni_features.col(1000) << endl; //cout << uni_features.col(1000) << endl; //cout << featuresUnclustered.row(1000) << endl; //cout << "Press a Key" << endl; //getchar(); //Construct BOWKMeansTrainer //the number of bags int dictionarySize = N_cent; //define Term Criteria cv::TermCriteria tc(CV_TERMCRIT_ITER,100,0.001); //retries number int retries=1; //necessary flags int flags=cv::KMEANS_PP_CENTERS; //Create the BoW (or BoF) trainer cv::BOWKMeansTrainer bowTrainer(dictionarySize,tc,retries,flags); //cluster the feature vectors cv::Mat dictionary = bowTrainer.cluster(featuresUnclustered); //Displaying # of Rows&Cols int rows_dic = dictionary.rows; int cols_dic = dictionary.cols; cout << "OpenCV Dict rows & cols " << rows_dic << " & " << cols_dic << endl; //store the vocabulary std::stringstream name_vocabulary; name_vocabulary << "./run"<< run <<"/visual_vocabulary/means_Ng" << N_cent << "_dim" <<dim << "_all_sc" << ".yml"; cv::FileStorage fs(name_vocabulary.str(), cv::FileStorage::WRITE); fs << "vocabulary" << dictionary; fs.release(); cout << "DONE"<< endl; }
bool bowCV::train_run(const string& _filepathForSavingResult,const string& _filenameForSavingResult, cvac::ServiceManager *sman) { if(!flagName) { cout << "Need to initialize detector, extractor, matcher, and so on with the function train_initialize()." << endl; fflush(stdout); return false; } if(vFilenameTrain.size() < 1) { cout << "There is no training images." << endl; fflush(stdout); return false; } else { cout<< "Training is started. " << endl; fflush(stdout); } ////////////////////////////////////////////////////////////////////////// // START - Clustering (Most time-consuming step) ////////////////////////////////////////////////////////////////////////// Mat _descriptorRepository; Rect _rect; for(unsigned int k=0;k<vFilenameTrain.size();k++) { _fullFilePathImg = vFilenameTrain[k]; _img = imread(_fullFilePathImg); if(_img.empty()) { cout<<"Error - no file: " << _fullFilePathImg << endl; fflush(stdout); return false; } if (sman->stopRequested()) { sman->stopCompleted(); return false; } _rect = Rect(vBoundX[k],vBoundY[k],vBoundWidth[k],vBoundHeight[k]); if((_rect.width != 0) && (_rect.height != 0)) _img = _img(_rect); // imshow("Crop",_img); // waitKey(); fDetector->detect(_img, _keypoints); dExtractor->compute(_img, _keypoints, _descriptors); _descriptorRepository.push_back(_descriptors); cout<< "Progress of Feature Extraction: " << k+1 << "/" << vFilenameTrain.size() << '\xd'; fflush(stdout); } cout << endl; fflush(stdout); cout << "Total number of descriptors: " << _descriptorRepository.rows << endl; fflush(stdout); cout << "Clustering ... It will take a time.." << std::endl; fflush(stdout); BOWKMeansTrainer bowTrainer(cntCluster); bowTrainer.add(_descriptorRepository); mVocabulary = bowTrainer.cluster(); if(!train_writeVocabulary(_filepathForSavingResult + "/" + filenameVocabulary,mVocabulary)) return false; ////////////////////////////////////////////////////////////////////////// // END - Clustering (Most time-consuming step) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // START - Setup Vocabulary ////////////////////////////////////////////////////////////////////////// cout << "Setting Vocabulary ... " << endl; fflush(stdout); bowExtractor->setVocabulary(mVocabulary); ////////////////////////////////////////////////////////////////////////// // START - End Vocabulary ////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // START - Train Classifier (SVM) ////////////////////////////////////////////////////////////////////////// cout << "Training Classifier ... " << endl; fflush(stdout); Mat trainDescriptors; trainDescriptors.create(0,bowExtractor->descriptorSize(),bowExtractor->descriptorType()); Mat trainClass; trainClass.create(0,1,CV_32FC1); int _classID; for(unsigned int k=0;k<vFilenameTrain.size();k++) { _fullFilePathImg = vFilenameTrain[k]; _classID = vClassIDTrain[k]; if(_classID==-1) continue; if (sman->stopRequested()) { sman->stopCompleted(); return false; } _img = imread(_fullFilePathImg); _rect = Rect(vBoundX[k],vBoundY[k],vBoundWidth[k],vBoundHeight[k]); if((_rect.width != 0) && (_rect.height != 0)) _img = _img(_rect); fDetector->detect(_img, _keypoints); bowExtractor->compute(_img, _keypoints, _descriptors); trainDescriptors.push_back(_descriptors); trainClass.push_back(_classID); } //SVMTrainParamsExt svmParamsExt; //CvSVMParams svmParams; //CvMat class_wts_cv; //setSVMParams( svmParams, class_wts_cv, labels, true ); //CvParamGrid c_grid, gamma_grid, p_grid, nu_grid, coef_grid, degree_grid; //setSVMTrainAutoParams( c_grid, gamma_grid, p_grid, nu_grid, coef_grid, degree_grid ); //classifierSVM[class_].train_auto( samples_32f, labels, Mat(), Mat(), svmParams, 10, c_grid, gamma_grid, p_grid, nu_grid, coef_grid, degree_grid ); classifierSVM.train(trainDescriptors,trainClass); _fullFilePathList = _filepathForSavingResult + "/" + _filenameForSavingResult; ofstream ofile(_fullFilePathList.c_str()); ofile << "# This file should includes the followings:" << std::endl; ofile << "# The name of Detector" << std::endl; ofile << "# The name of Extractor" << std::endl; ofile << "# The name of Matcher" << std::endl; ofile << "# The filename of vocabulary" << std::endl; ofile << "# Filenames of svm results" << std::endl; ofile << nameDetector << std::endl; ofile << nameExtractor << std::endl; ofile << nameMatcher << std::endl; ofile << filenameVocabulary << std::endl; string _svmName = "logTrain_svm.xml.gz"; ofile << _svmName << endl; _fullFilePathList = _filepathForSavingResult + "/" + _svmName; classifierSVM.save(_fullFilePathList.c_str()); ofile.close(); flagTrain = true; return true; }
//Main function int main ( int argc, char *argv[] ) { //--- VARIABLES ---// //saving database descriptors cv::Mat training_descriptors; //for measuring processing time clock_t t; // --- ---// std::cout << std::endl; std::cout << "+++ BOW FOR DATA SET +++" << std::endl; std::cout << TRAIN_PATH << std::endl; //--- DESCRIPTORS EXTRACTION ---// std::string train_path = TRAIN_PATH; //read descriptors from file std::cout << "*** TRAIN DESCRIPTORS INFO ***" << std::endl; cv::FileStorage fstore_descrip(DESCRIP_MAT_NAME, cv::FileStorage::READ); std::cout << "No Documents: " << (int)fstore_descrip["noDocuments"] << std::endl; std::cout << "No Classes: " << (int)fstore_descrip["noClasses"] << std::endl; std::cout << "No total descriptors: " << (int)fstore_descrip["totalDescriptors"] << std::endl; std::cout << "No max desrcriptors in an image: " << (int)fstore_descrip["maxDescriptors"] << std::endl; std::cout << "Descriptors processing time: " << (float)fstore_descrip["procTime"] << std::endl; std::cout << std::endl; fstore_descrip["matDescriptors"] >> training_descriptors; fstore_descrip.release(); //--- BUILD A DICTIONARY ---// cv::TermCriteria tc(CV_TERMCRIT_ITER,100,0.001); int cluster_attempts = 1; int dictionary_size = atoi(argv[1]); std::cout << "*** BOW DICTIONARY INFO ***" << std::endl; std::cout << "Dictionary size: " << dictionary_size << std::endl; cv::BOWKMeansTrainer bowTrainer(dictionary_size,tc,cluster_attempts, cv::KMEANS_PP_CENTERS); bowTrainer.add(training_descriptors); t = clock(); cv::Mat my_dictionary = bowTrainer.cluster(); t = clock()-t; std::cout << "Dictionary processing time:" << std::endl; std::cout << t << " clicks " << ((float)t)/CLOCKS_PER_SEC << " seconds" << std::endl; std::cout << std::endl; //--- ---// //--- NAIVE BAYES FOR CLASSIFICATION ---// cv::NormalBayesClassifier nb_classifier; cv::Mat training_data(0,dictionary_size,CV_32FC1); cv::Mat labels(0,1,CV_32FC1); //set the dictionary to bow descriptor extractor bowDE.setVocabulary(my_dictionary); std::cout << "*** CLASSIFIER TRAINING ***" << std::endl; bow_encode(fs::path(train_path),training_data,labels); // +++ for debugging - can be commented +++// std::cout << training_data.size() << " * " << labels.size() << std::endl; if(training_data.type() == CV_32FC1) {std::cout << "training data matrix accepted" << std::endl;} if(labels.type() == CV_32FC1) {std::cout << "labels matrix accepted" << std::endl;} // +++ +++ // t = clock(); nb_classifier.train(training_data,labels,cv::Mat(),cv::Mat(),false); t = clock() - t; nb_classifier.save("nbModel_flavia_leaves_a.yml","nbModel_flavia_leaves_a"); std::cout << " Training processing time:" << std::endl; std::cout << t << " clicks " << ((float)t)/CLOCKS_PER_SEC << " seconds" << std::endl; std::cout << std::endl; //if you already have a classifier uncomment the next line and comment the all the //Classifier Training section //nb_classifier.load("nbModel_flavia_leaves_b.yml","nbModel_flavia_leaves_b"); //std::cout << "Classfier model loaded"<< std::endl; //--- ---// //--- BOW ENCODING OF TEST SET AND EVALUATION ---// cv::Mat ground_truth(0,1,CV_32FC1); cv::Mat eval_data(0,dictionary_size,CV_32FC1); cv::Mat results; std::string test_path = TEST_PATH; double accuRate = 0.; std::cout << "*** CLASSIFIER EVALUATION ***" << std::endl; bow_encode(fs::path(test_path),eval_data,ground_truth); t = clock(); nb_classifier.predict(eval_data,&results); t = clock()-t; std::cout << " Classifier evaluation time:" << std::endl; std::cout << t << " clicks " << ((float)t)/CLOCKS_PER_SEC << " seconds" << std::endl; accuRate = 1. -( (double) cv::countNonZero(ground_truth - results) / eval_data.rows); std::cout << "Accuracy rate: " << accuRate << std::endl; std::cout << "Classifier Results" << std::endl; std::cout << results << std::endl << std::endl; return 0; } /* ---------- end of function main ---------- */