void View::trainFaceRecognition() { TrainingInfo trainingInfo = FaceRecognitionTrainingDialog::getTrainingInfo((QWidget*)this); if(trainingInfo == TrainingInfo::empty()) { _ui.tlBttn_FaceRecognition->setChecked(false); return; } showStatusMessage("Reading face recognition trainging file..."); _controller->setFaceRecognitionTrainingName(trainingInfo.name()); TrainingData trainingData; try { trainingData = readImageClassMapFile(trainingInfo.classImageMapFileName()); validateTrainingData(trainingData); showStatusMessage("Training face recognition..."); _controller->trainFaceRecognition(trainingData); trainingData.release(); saveFaceRecognitionMethodState(trainingInfo.name()); addLoadFaceRecognitionMethodStateMenuItem(trainingInfo.name()); clearStatusMessage(); } catch(framework::BaseException& e) { trainingData.release(); clearStatusMessage(); _ui.tlBttn_FaceRecognition->setChecked(false); throw e; } }
TrainingData View::readImageClassMapFile(QString const& fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) FileOperationException(QString("Can not open '%1' file").arg(fileName)).raise(); _classNumberClassNameMap.clear(); int lastImageClassNumber = -1; TrainingData trainingData; QTextStream inputTextStream(&file); while (!inputTextStream.atEnd()) { QString line = inputTextStream.readLine(); QStringList imageNameAndClass = line.split(',', QString::SkipEmptyParts); QString imageName = combinePathIfRelative(imageNameAndClass.first(), fileName); if(QFile::exists(imageName) == false) FileOperationException(QString("File '%1' is not found").arg(imageName)).raise(); QString imageClass = imageNameAndClass.last(); int imageClassNumber; if(_classNumberClassNameMap.values().contains(imageClass)) { imageClassNumber = _classNumberClassNameMap.key(imageClass); } else { imageClassNumber = ++lastImageClassNumber; _classNumberClassNameMap[imageClassNumber] = imageClass; } trainingData.add(cv::imread(imageName.toStdString(), CV_LOAD_IMAGE_GRAYSCALE), imageClassNumber); } file.close(); return trainingData; }
ErrorStruct StrongClassifier::errorForFeatures(const TrainingData &features, bool printStats) const { ErrorStruct e; for (int i=0; i<features.size(); i++) { FeatureVector feature = *(features.feature(i)); if (decide(feature)) { feature.val() == POS ? e.true_pos++ : e.false_pos++;//it is really positive } else { feature.val() == NEG ? e.true_neg++ : e.false_neg++;//it is really negative } } // if all 10 samples, 3 is misclassified, error is 3/10 e.error = (e.false_pos + e.false_neg) / ((float)features.size()); if (printStats) { std::cout << e.true_pos << " true positives" << std::endl; std::cout << e.false_pos << " false positives" << std::endl; std::cout << e.true_neg << " true negatives" << std::endl; std::cout << e.false_neg << " false negatives" << std::endl; std::cout << e.error * 100 << "% error" << std::endl; std::cout << std::endl; } return e; }
TrainingData* Parser::getAsTrainingData() { TrainingData* trData = new TrainingData(); for (int i = 0; i < this->container->size(); i++) { trData->pushVector(this->container->getVectorAt(i)); } return trData; }
AppendDatumFunctor::AppendDatumFunctor(TrainingData &trainingData_) : trainingData(trainingData_), datumIndex(trainingData_.get_num_examples()) { // nothing to do here return; }
/** * @brief Cross covariance matrix between the training and test data, Ks(X, Z) * @note It calls the protected general member function, * CovMaterniso::K(const Hyp, const MatrixConstPtr, const int) * which only depends on pair-wise absolute distances. * @param [in] logHyp The log hyperparameters * - logHyp(0) = \f$\log(l)\f$ * - logHyp(1) = \f$\log(\sigma_f)\f$ * @param [in] trainingData The training data * @param [in] testData The test data * @return An NxM matrix pointer, \f$\mathbf{K}_* = \mathbf{K}(\mathbf{X}, \mathbf{Z})\f$\n * N: The number of training data\n * M: The number of test data */ static MatrixPtr Ks(const Hyp &logHyp, const TrainingData<Scalar> &trainingData, const TestData<Scalar> &testData) { // K(r) return K(logHyp, trainingData.pAbsDistXXs(testData)); }
/** * @brief Self covariance matrix between the training data, K(X, X) or its partial derivative * @note It calls the protected general member function, * CovMaterniso::K(const Hyp, const MatrixConstPtr, const int) * which only depends on pair-wise absolute distances.\n\n * Only this function returns partial derivatives * since they are used for learning hyperparameters with training data. * @param [in] logHyp The log hyperparameters * - logHyp(0) = \f$\log(l)\f$ * - logHyp(1) = \f$\log(\sigma_f)\f$ * @param [in] trainingData The training data * @param [in] pdHypIndex (Optional) Hyperparameter index for partial derivatives * - pdHypIndex = -1: return \f$\mathbf{K}(\mathbf{X}, \mathbf{X})\f$ (default) * - pdHypIndex = 0: return \f$\frac{\partial \mathbf{K}}{\partial \log(l)}\f$ * - pdHypIndex = 1: return \f$\frac{\partial \mathbf{K}}{\partial \log(\sigma_f)}\f$ * @return An NxN matrix pointer\n * N: The number of training data */ static MatrixPtr K(const Hyp &logHyp, TrainingData<Scalar> &trainingData, const int pdHypIndex = -1) { // Assertions only in the begining of the public static member functions which can be accessed outside. // The hyparparameter index should be less than the number of hyperparameters assert(pdHypIndex < logHyp.size()); // K(r) return K(logHyp, trainingData.pAbsDistXX(), pdHypIndex); }
bool Estimator::start() { bool result = true; std::cout << "[Log] Estimation started.\n"; parser->loadFile(this->inputFileName); //To-Do // // Test Code this->input = parser->getAsInputData(); this->input->post(); TrainingData* tr = new TrainingData(); tr = parser->getAsTrainingData(); tr->post(); std::cout << tr->getFeatureVectorAt(0)->post(); std::cout << tr->getLabelVectorAt(0)->post(); // End of the block return result; }
/************************************* * Function: update_feature_weight * ------------------------------- * Given TrainingData and a WeakClassifier that has been weighted in * get_best_classifier(), we recalculate the weights of all the features * * td: training data (set of features) * wc: (weighted) weak classifier * * returns true if successful, false otherwise */ bool AdaBooster::update_feature_weight(TrainingData &td, WeakClassifier &wc){ // check that WeakClassifier has actually been weighted if (wc.weight() < 0){ printf("Error in update_feature_weight: WeakClassifier has invalid weight\n"); return false; } // traverse features in feature set and adjust their weights for (unsigned int i=0; i<num_features; i++){ FeatureVector* fv = td.feature(i); // either 1 or -1 (used in weight below) int is_correct = is_classifier_correct(wc, *fv) ? 1 : -1; // calculate and update weight // note M_E := 2.71828 float weight = pow(M_E, (double) -1 * wc.weight() * is_correct); td.setWeight(i, td.weight(i)*weight); } // calculate normalization factor float norm = 0; for (unsigned int i=0; i<num_features; i++) norm += td.weight(i); // normalize feature weights for (unsigned int i=0; i<num_features; i++) td.setWeight(i, td.weight(i)/norm); return true; // successful }
/*********************************** * Function: create_circle * ----------------------- * Creates a circular distribution (radius 1) of POS and NEG values, with * num_pos POS values inside a radius=1/2, and num_neg NEG values outside that * radius */ TrainingData create_circle(int num_pos, int num_neg){ // create TrainingData object (circle, dimension 2) TrainingData circle; // create positive distribution within radius=1/2 vector <float> coord; float radius, theta; for (int i=0; i<num_pos; i++){ // get radius and angle radius = sqrt((float)rand()/RAND_MAX)/2; theta = 2*M_PI*(float)rand()/RAND_MAX; // convert to x and y coord.push_back(radius * cos(theta)); coord.push_back(radius * sin(theta)); coord.push_back(5.0f); //coord.push_back(coord[0]*coord[0] + coord[1]*coord[1]); FeatureVector fv(coord, POS); circle.addFeature(fv); coord.clear(); } // create negative distribution for 1/2 <= radius <= 1 for (int i=num_pos; i<num_pos+num_neg; i++){ // get radius and angle radius = sqrt(3*(float)rand()/RAND_MAX+1)/2; theta = 2*M_PI*(float)rand()/RAND_MAX; // convert to x and y coord.push_back(radius * cos(theta)); coord.push_back(radius * sin(theta)); coord.push_back(1.5f); //coord.push_back(coord[0]*coord[0] + coord[1]*coord[1]); FeatureVector fv(coord, NEG); circle.addFeature(fv); coord.clear(); } return circle; }
/************************************** * Function: create_feature_views * ------------------------------ * For each dimension, we sort the feature vectors and store the result in * *sorted*. Note that *sorted* is a little complicated -- we need the sorting to * be fast so we sort feature vector pointers, and we have a vector of these * for each dimension. * * td: training data -- set of features */ void AdaBooster::create_feature_views(TrainingData &td){ sorted = new vector<FeatureVector *>[dimensions]; // add a feature pointer to sorted for each dimension in the training data for (unsigned int i=0; i<dimensions; i++){ for (unsigned int j=0; j<num_features; j++){ sorted[i].push_back(td.feature(j)); } } // sort each feature vector pointer in sorted for (unsigned int i=0; i<dimensions; i++) sort(sorted[i].begin(), sorted[i].end(), idx_cmp(i)); }
MimRec::MimRec(const TrainingData& neutral) { currentPoints = neutral.getPoints(); vAUDetectionValue.resize(actionUnits.size()); vBackPropAUDetectionValue.resize(actionUnits.size()); areaFace(); calc_distance(); neutral_area = areas; neutral_distances.swap(current_distances); }
void View::validateTrainingData(TrainingData trainingData) const { if(trainingData.empty()) ArgumentException("Training file is empty").raise(); const int width = trainingData.imageCollection()[0].cols; const int height = trainingData.imageCollection()[0].rows; for(int i = 0; i < trainingData.size(); i++) { if(trainingData.imageCollection()[i].cols != width || trainingData.imageCollection()[i].rows != height) ArgumentException("All training images should have an equal size").raise(); } }
/************************************** * Function: getStrongError * ------------------------ * calculates error rates at each "level" of the strong classifier; i.e. at * each weak classifier * * td: Training data to check strong classifier against * strong: strong classifier (i.e. ordered set of weak classifiers) * * returns: a list of the errors at each level */ vector<vector <double> > AdaBooster::getStrongError(TrainingData &td, const WeakClassifierList &strong){ unsigned int true_pos, false_pos, true_neg, false_neg; float precision, recall; vector< vector<double> > strong_err; vector<double> stats; // clear false_indices false_indices.clear(); // set dimensions and number of features dimensions = td.dimensions(); num_features = td.size(); // initialize vector of num_ftrs to zero vector<double> classify; for (unsigned int i=0; i<num_features; i++) classify.push_back(0.0); int sign; // traverse all weak classifiers for (unsigned int i=0; i<strong.size(); i++){ true_pos = false_pos = true_neg = false_neg = precision = recall = 0; // traverse all features for (unsigned int j=0; j<num_features; j++){ // check what the classifier guessed. If weak classifier decided // the feature was POS, sign = 1, otherwise sign = -1 if ( (strong[i].threshold() > td.at(j,strong[i].dimension()) && !strong[i].isFlipped()) || (strong[i].threshold() < td.at(j,strong[i].dimension()) && strong[i].isFlipped()) ) sign = 1; else sign = -1; // calculate classify so far classify[j] += strong[i].weight() * sign; // check classification against reality if (classify.at(j) >= strong_err_threshold && td.val(j) == POS) true_pos++; else if (classify.at(j) >= strong_err_threshold && td.val(j) == NEG){ false_pos++; // if we're at the last weak classifier and we still can't classify this point if (i == strong.size()-1) false_indices.push_back(j); // add index to false indices vector } else if (classify.at(j) < strong_err_threshold && td.val(j) == POS){ false_neg++; // similarly, we can't classify the point if (i == strong.size()-1) false_indices.push_back(j); } else true_neg++; } // calculate some stats and push into strong_err stats.clear(); stats.push_back((double)(false_pos + false_neg)/num_features); // flat error percentage stats.push_back((double)(true_pos)/(true_pos+false_pos)); // precision stats.push_back((double)(true_pos)/(true_pos+false_neg)); // recall stats.push_back((double)true_pos); // true positives stats.push_back((double)true_neg); // true negatives stats.push_back((double)false_pos); // false positives stats.push_back((double)false_neg); // false negatives strong_err.push_back(stats); } return strong_err; }
/********************************* * Function: getStrongClassifier * ----------------------------- * This function generates a strong classifier that can accurately distinguish * positive training examples from negative training examples * * td: set of feature vectors * num_classifiers: the number of weak classifiers we want to be in the strong * classifier (20 tends to be a good default it seems) * * returns: a strong classifier -- set of weak classifiers in optimal order */ StrongClassifier AdaBooster::getStrongClassifier(const TrainingData &trainingData, unsigned int num_classifiers){ TrainingData td = trainingData; // set dimensions and number of features dimensions = td.dimensions(); num_features = td.size(); // initialize feature weights init_feature_weight(td); // vector of weak classifiers that make up a strong classifier vector<WeakClassifier> strong_classifier; // sort circle by features -- store in *sorted* create_feature_views(td); //td.printData(); //char garbage[80]; // use this with cin.getline() below for (unsigned int i=0; i<num_classifiers; i++){ // indentify best classifier WeakClassifier *wc = get_best_classifier(); // if index invalid, then we're done constructing our strong classifier if (!wc) return StrongClassifier(strong_classifier); // otherwise, add best classifier to strong_classifier strong_classifier.push_back(*wc); //strong_classifier.back().printClassifier(); // don't need classifier anymore so delete it delete wc; // don't think this is useful anymore, but I'm scared to delete it // without more testing, so it stays for now. TODO: delete this? td.writeData(tdFile); //td.printData(); // update weights of features update_feature_weight(td, strong_classifier.back()); // print out status update printf("\rClassifiers Calculated: %d ", i+1); fflush(stdout); /* td.printData(); // prints out the set of training data cin.getline(garbage, 80); // if you want to pause printing, use this // */ } // delete sorted array delete [] sorted; // StrongClassifier error reporting /*vector< vector<double> > strong_err = getStrongError(td, strong_classifier); printStrongStats(strong_err);*/ return strong_classifier; }
/************************************** * Function: init_feature_weight * ----------------------------- * Initializes weights of features to be 1/(total num of features) * * td: training data -- set of features */ void AdaBooster::init_feature_weight(TrainingData &td){ // set all points to same weight = 1/(# of features) for (unsigned int i=0; i<num_features; i++) td.setWeight(i, 1./num_features); }
bool BowVocabulary::computeTrainingData(TrainingData& trainingDataOut, const string& vocabularyImgsList, const string& samplesImgsList, bool outputAnalyzedImages) { if (_bowImgDescriptorExtractor->getVocabulary().rows == 0) { Mat vocabulary; if (!computeVocabulary(vocabulary, vocabularyImgsList)) { return false; } } Mat trainSamples; Mat trainLabels(0, 1, CV_32SC1); if (loadTrainingSamples(trainSamples) && loadTrainingLabels(trainLabels)) { trainingDataOut.setTrainSamples(trainSamples); trainingDataOut.setTrainLabels(trainLabels); return true; } ifstream imgsList(vocabularyImgsList); if (imgsList.is_open()) { vector<string> fileNames; string filename; while (getline(imgsList, filename)) { fileNames.push_back(filename); } int numberOfFiles = fileNames.size(); int samplesWordSize = _bowImgDescriptorExtractor->getVocabulary().rows; cout << "\n -> Analysing " << numberOfFiles << " training images..." << endl; PerformanceTimer performanceTimer; performanceTimer.start(); //#pragma omp parallel for schedule(dynamic) for (int i = 0; i < numberOfFiles; ++i) { Mat imagePreprocessed; string imageFilenameShort = IMGS_DIRECTORY + fileNames[i]; string imageFilenameFull = imageFilenameShort + IMAGE_TOKEN; if (_imagePreprocessor->loadAndPreprocessImage(imageFilenameFull, imagePreprocessed, CV_LOAD_IMAGE_GRAYSCALE, false)) { vector<KeyPoint> keypoints; _featureDetector->detect(imagePreprocessed, keypoints); vector< vector <KeyPoint> > keypointsTargetClass; vector<KeyPoint> keypointsNonTargetClass; ImageUtils::splitKeyPoints(imageFilenameShort, keypoints, keypointsTargetClass, keypointsNonTargetClass); for (size_t targetClassInstancePosition = 0; targetClassInstancePosition < keypointsTargetClass.size(); ++targetClassInstancePosition) { if (keypointsTargetClass[targetClassInstancePosition].size() > 3) { Mat descriptorsTargetClass; _bowImgDescriptorExtractor->compute(imagePreprocessed, keypointsTargetClass[targetClassInstancePosition], descriptorsTargetClass); //#pragma omp critical if (descriptorsTargetClass.rows > 0 && descriptorsTargetClass.cols == samplesWordSize) { trainSamples.push_back(descriptorsTargetClass); trainLabels.push_back(1); } } } if (keypointsNonTargetClass.size() > 3) { Mat descriptorsNonTargetClass; _bowImgDescriptorExtractor->compute(imagePreprocessed, keypointsNonTargetClass, descriptorsNonTargetClass); //#pragma omp critical if (descriptorsNonTargetClass.rows > 0 && descriptorsNonTargetClass.cols == samplesWordSize) { trainSamples.push_back(descriptorsNonTargetClass); trainLabels.push_back(0); } } if (outputAnalyzedImages) { stringstream imageOutputFilename; imageOutputFilename << SAMPLES_BUILD_OUTPUT_DIRECTORY << fileNames[i] << FILENAME_SEPARATOR << _vocabularyFilename << IMAGE_OUTPUT_EXTENSION; for (size_t targetClassInstancePosition = 0; targetClassInstancePosition < keypointsTargetClass.size(); ++targetClassInstancePosition) { if (keypointsTargetClass[targetClassInstancePosition].size() > 0) { cv::drawKeypoints(imagePreprocessed, keypointsTargetClass[targetClassInstancePosition], imagePreprocessed, TARGET_KEYPOINT_COLOR); } } if (keypointsNonTargetClass.size() > 0) { cv::drawKeypoints(imagePreprocessed, keypointsNonTargetClass, imagePreprocessed, NONTARGET_KEYPOINT_COLOR); } imwrite(imageOutputFilename.str(), imagePreprocessed); } } } cout << " -> Computed " << trainSamples.rows << " training samples from " << numberOfFiles << " images in " << performanceTimer.getElapsedTimeFormated() << "\n" << endl; if (trainSamples.rows != trainLabels.rows || trainSamples.rows == 0 || trainLabels.rows == 0) { cout << "\n !> Invalid training data!\n\n\n" << endl; return false; } trainingDataOut.setTrainSamples(trainSamples); trainingDataOut.setTrainLabels(trainLabels); saveTrainingSamples(trainSamples); saveTrainingLabels(trainLabels); return true; } return false; }