Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
eigen_faces.cpp
00001 /* 00002 * Copyright (c) 2011,2012. Philipp Wagner <bytefish[at]gmx[dot]de>. 00003 * Released to public domain under terms of the BSD Simplified license. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the organization nor the names of its contributors 00013 * may be used to endorse or promote products derived from this software 00014 * without specific prior written permission. 00015 * 00016 * See <http://www.opensource.org/licenses/bsd-license> 00017 */ 00018 #include "precomp.hpp" 00019 #include "face_basic.hpp" 00020 #include <set> 00021 #include <limits> 00022 #include <iostream> 00023 00024 namespace cv 00025 { 00026 namespace face 00027 { 00028 00029 // Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of 00030 // Cognitive Neuroscience 3 (1991), 71–86. 00031 class Eigenfaces : public BasicFaceRecognizerImpl 00032 { 00033 00034 public: 00035 // Initializes an empty Eigenfaces model. 00036 Eigenfaces(int num_components = 0, double threshold = DBL_MAX) 00037 : BasicFaceRecognizerImpl(num_components, threshold) 00038 {} 00039 00040 // Computes an Eigenfaces model with images in src and corresponding labels 00041 // in labels. 00042 void train(InputArrayOfArrays src, InputArray labels); 00043 00044 // Send all predict results to caller side for custom result handling 00045 void predict(InputArray src, Ptr<PredictCollector> collector) const; 00046 }; 00047 00048 //------------------------------------------------------------------------------ 00049 // Eigenfaces 00050 //------------------------------------------------------------------------------ 00051 void Eigenfaces::train(InputArrayOfArrays _src, InputArray _local_labels) { 00052 if(_src.total() == 0) { 00053 String error_message = format("Empty training data was given. You'll need more than one sample to learn a model."); 00054 CV_Error(Error::StsBadArg, error_message); 00055 } else if(_local_labels.getMat().type() != CV_32SC1) { 00056 String error_message = format("Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _local_labels.type()); 00057 CV_Error(Error::StsBadArg, error_message); 00058 } 00059 // make sure data has correct size 00060 if(_src.total() > 1) { 00061 for(int i = 1; i < static_cast<int>(_src.total()); i++) { 00062 if(_src.getMat(i-1).total() != _src.getMat(i).total()) { 00063 String error_message = format("In the Eigenfaces method all input samples (training images) must be of equal size! Expected %d pixels, but was %d pixels.", _src.getMat(i-1).total(), _src.getMat(i).total()); 00064 CV_Error(Error::StsUnsupportedFormat, error_message); 00065 } 00066 } 00067 } 00068 // get labels 00069 Mat labels = _local_labels.getMat(); 00070 // observations in row 00071 Mat data = asRowMatrix(_src, CV_64FC1); 00072 00073 // number of samples 00074 int n = data.rows; 00075 // assert there are as much samples as labels 00076 if(static_cast<int>(labels.total()) != n) { 00077 String error_message = format("The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", n, labels.total()); 00078 CV_Error(Error::StsBadArg, error_message); 00079 } 00080 // clear existing model data 00081 _labels.release(); 00082 _projections.clear(); 00083 // clip number of components to be valid 00084 if((_num_components <= 0) || (_num_components > n)) 00085 _num_components = n; 00086 00087 // perform the PCA 00088 PCA pca(data, Mat(), PCA::DATA_AS_ROW, _num_components); 00089 // copy the PCA results 00090 _mean = pca.mean.reshape(1,1); // store the mean vector 00091 _eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row 00092 transpose(pca.eigenvectors, _eigenvectors); // eigenvectors by column 00093 // store labels for prediction 00094 _labels = labels.clone(); 00095 // save projections 00096 for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) { 00097 Mat p = LDA::subspaceProject(_eigenvectors, _mean, data.row(sampleIdx)); 00098 _projections.push_back(p); 00099 } 00100 } 00101 00102 void Eigenfaces::predict(InputArray _src, Ptr<PredictCollector> collector) const { 00103 // get data 00104 Mat src = _src.getMat(); 00105 // make sure the user is passing correct data 00106 if(_projections.empty()) { 00107 // throw error if no data (or simply return -1?) 00108 String error_message = "This Eigenfaces model is not computed yet. Did you call Eigenfaces::train?"; 00109 CV_Error(Error::StsError, error_message); 00110 } else if(_eigenvectors.rows != static_cast<int>(src.total())) { 00111 // check data alignment just for clearer exception messages 00112 String error_message = format("Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total()); 00113 CV_Error(Error::StsBadArg, error_message); 00114 } 00115 // project into PCA subspace 00116 Mat q = LDA::subspaceProject(_eigenvectors, _mean, src.reshape(1, 1)); 00117 collector->init(_projections.size()); 00118 for (size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) { 00119 double dist = norm(_projections[sampleIdx], q, NORM_L2); 00120 int label = _labels.at<int>((int)sampleIdx); 00121 if (!collector->collect(label, dist))return; 00122 } 00123 } 00124 00125 Ptr<BasicFaceRecognizer> createEigenFaceRecognizer (int num_components, double threshold) 00126 { 00127 return makePtr<Eigenfaces>(num_components, threshold); 00128 } 00129 00130 } 00131 } 00132
Generated on Tue Jul 12 2022 14:46:34 by
