FaceRecognizer class is now derived from Algorithm, therefore it's possible to set...
authorVadim Pisarevsky <no@email>
Mon, 21 May 2012 15:27:40 +0000 (15:27 +0000)
committerVadim Pisarevsky <no@email>
Mon, 21 May 2012 15:27:40 +0000 (15:27 +0000)
modules/contrib/include/opencv2/contrib/contrib.hpp
modules/contrib/src/facerec.cpp

index 64faf77..638eadb 100644 (file)
@@ -918,7 +918,7 @@ namespace cv
         void lda(InputArray src, InputArray labels);
     };
     
-    class CV_EXPORTS FaceRecognizer
+    class CV_EXPORTS FaceRecognizer : public Algorithm
     {
     public:
         //! virtual destructor
@@ -970,6 +970,8 @@ namespace cv
     };
     
     CV_EXPORTS void applyColorMap(InputArray src, OutputArray dst, int colormap);
+    
+    CV_EXPORTS bool initModule_contrib();
 }
 
 
index 987e021..37d6d1f 100644 (file)
@@ -90,7 +90,7 @@ class Eigenfaces : public FaceRecognizer
 private:
     int _num_components;
     vector<Mat> _projections;
-    vector<int> _labels;
+    Mat _labels;
     Mat _eigenvectors;
     Mat _eigenvalues;
     Mat _mean;
@@ -124,20 +124,10 @@ public:
 
     // See FaceRecognizer::save.
     void save(FileStorage& fs) const;
-
-    // Returns the eigenvectors of this PCA.
-    Mat eigenvectors() const { return _eigenvectors; }
-
-    // Returns the eigenvalues of this PCA.
-    Mat eigenvalues() const { return _eigenvalues; }
-
-    // Returns the sample mean of this PCA.
-    Mat mean() const { return _mean; }
-
-    // Returns the number of components used in this PCA.
-    int num_components() const { return _num_components; }
+    
+    AlgorithmInfo* info() const;
 };
-
+    
 // Belhumeur, P. N., Hespanha, J., and Kriegman, D. "Eigenfaces vs. Fisher-
 // faces: Recognition using class specific linear projection.". IEEE
 // Transactions on Pattern Analysis and Machine Intelligence 19, 7 (1997),
@@ -150,7 +140,7 @@ private:
     Mat _eigenvalues;
     Mat _mean;
     vector<Mat> _projections;
-    vector<int> _labels;
+    Mat _labels;
 
 public:
     using FaceRecognizer::save;
@@ -185,17 +175,7 @@ public:
     // See FaceRecognizer::save.
     virtual void save(FileStorage& fs) const;
 
-    // Returns the eigenvectors of this Fisherfaces model.
-    Mat eigenvectors() const { return _eigenvectors; }
-
-    // Returns the eigenvalues of this Fisherfaces model.
-    Mat eigenvalues() const { return _eigenvalues; }
-
-    // Returns the sample mean of this Fisherfaces model.
-    Mat mean() const { return _eigenvalues; }
-
-    // Returns the number of components used in this Fisherfaces model.
-    int num_components() const { return _num_components; }
+    AlgorithmInfo* info() const;
 };
 
 // Face Recognition based on Local Binary Patterns.
@@ -217,7 +197,7 @@ private:
     int _neighbors;
 
     vector<Mat> _histograms;
-    vector<int> _labels;
+    Mat _labels;
 
 public:
     using FaceRecognizer::save;
@@ -271,6 +251,7 @@ public:
     int grid_x() const { return _grid_x; }
     int grid_y() const { return _grid_y; }
 
+    AlgorithmInfo* info() const;
 };
 
 
@@ -302,7 +283,8 @@ void Eigenfaces::train(InputArray src, InputArray _lbls) {
     if(_lbls.getMat().type() != CV_32SC1)
         CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
     // get labels
-    vector<int> labels = _lbls.getMat();
+    Mat labels = _lbls.getMat();
+    CV_Assert( labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1));
     // observations in row
     Mat data = asRowMatrix(src, CV_64FC1);
     // number of samples
@@ -310,7 +292,7 @@ void Eigenfaces::train(InputArray src, InputArray _lbls) {
     // dimensionality of data
     //int d = data.cols;
     // assert there are as much samples as labels
-    if((size_t)n != labels.size())
+    if((size_t)n != labels.total())
         CV_Error(CV_StsBadArg, "The number of samples must equal the number of labels!");
     // clip number of components to be valid
     if((_num_components <= 0) || (_num_components > n))
@@ -321,7 +303,7 @@ void Eigenfaces::train(InputArray src, InputArray _lbls) {
     _mean = pca.mean.reshape(1,1); // store the mean vector
     _eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row
     transpose(pca.eigenvectors, _eigenvectors); // eigenvectors by column
-    _labels = labels; // store labels for prediction
+    labels.copyTo(_labels); // store labels for prediction
     // save projections
     for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
         Mat p = subspaceProject(_eigenvectors, _mean, data.row(sampleIdx));
@@ -340,7 +322,7 @@ int Eigenfaces::predict(InputArray _src) const {
         double dist = norm(_projections[sampleIdx], q, NORM_L2);
         if(dist < minDist) {
             minDist = dist;
-            minClass = _labels[sampleIdx];
+            minClass = _labels.at<int>(sampleIdx);
         }
     }
     return minClass;
@@ -354,7 +336,7 @@ void Eigenfaces::load(const FileStorage& fs) {
     fs["eigenvectors"] >> _eigenvectors;
     // read sequences
     readFileNodeList(fs["projections"], _projections);
-    readFileNodeList(fs["labels"], _labels);
+    fs["labels"] >> _labels;
 }
 
 void Eigenfaces::save(FileStorage& fs) const {
@@ -365,7 +347,7 @@ void Eigenfaces::save(FileStorage& fs) const {
     fs << "eigenvectors" << _eigenvectors;
     // write sequences
     writeFileNodeList(fs, "projections", _projections);
-    writeFileNodeList(fs, "labels", _labels);
+    fs << "labels" << _labels;
 }
 
 //------------------------------------------------------------------------------
@@ -375,16 +357,22 @@ void Fisherfaces::train(InputArray src, InputArray _lbls) {
     if(_lbls.getMat().type() != CV_32SC1)
             CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
     // get data
-    vector<int> labels = _lbls.getMat();
+    Mat labels = _lbls.getMat();
     Mat data = asRowMatrix(src, CV_64FC1);
+    
+    CV_Assert( labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1));
+    
     // dimensionality
     int N = data.rows; // number of samples
     //int D = data.cols; // dimension of samples
     // assert correct data alignment
-    if(labels.size() != (size_t)N)
+    if(labels.total() != (size_t)N)
         CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
     // compute the Fisherfaces
-    int C = (int)remove_dups(labels).size(); // number of unique classes
+    
+    vector<int> ll;
+    labels.copyTo(ll);
+    int C = (int)remove_dups(ll).size(); // number of unique classes
     // clip number of components to be a valid number
     if((_num_components <= 0) || (_num_components > (C-1)))
         _num_components = (C-1);
@@ -395,7 +383,7 @@ void Fisherfaces::train(InputArray src, InputArray _lbls) {
     // store the total mean vector
     _mean = pca.mean.reshape(1,1);
     // store labels
-    _labels = labels;
+    labels.copyTo(_labels);
     // store the eigenvalues of the discriminants
     lda.eigenvalues().convertTo(_eigenvalues, CV_64FC1);
     // Now calculate the projection matrix as pca.eigenvectors * lda.eigenvectors.
@@ -419,7 +407,7 @@ int Fisherfaces::predict(InputArray _src) const {
         double dist = norm(_projections[sampleIdx], q, NORM_L2);
         if(dist < minDist) {
             minDist = dist;
-            minClass = _labels[sampleIdx];
+            minClass = _labels.at<int>(sampleIdx);
         }
     }
     return minClass;
@@ -435,7 +423,7 @@ void Fisherfaces::load(const FileStorage& fs) {
     fs["eigenvectors"] >> _eigenvectors;
     // read sequences
     readFileNodeList(fs["projections"], _projections);
-    readFileNodeList(fs["labels"], _labels);
+    fs["labels"] >> _labels;
 }
 
 // See FaceRecognizer::save.
@@ -447,7 +435,7 @@ void Fisherfaces::save(FileStorage& fs) const {
     fs << "eigenvectors" << _eigenvectors;
     // write sequences
     writeFileNodeList(fs, "projections", _projections);
-    writeFileNodeList(fs, "labels", _labels);
+    fs << "labels" << _labels;
 }
 //------------------------------------------------------------------------------
 // LBPH
@@ -630,7 +618,7 @@ void LBPH::load(const FileStorage& fs) {
     fs["grid_y"] >> _grid_y;
     //read matrices
     readFileNodeList(fs["histograms"], _histograms);
-    readFileNodeList(fs["labels"], _labels);
+    fs["labels"] >> _labels;
 }
 
 // See FaceRecognizer::save.
@@ -641,7 +629,7 @@ void LBPH::save(FileStorage& fs) const {
     fs << "grid_y" << _grid_y;
     // write matrices
     writeFileNodeList(fs, "histograms", _histograms);
-    writeFileNodeList(fs, "labels", _labels);
+    fs << "labels" << _labels;
 }
 
 void LBPH::train(InputArray _src, InputArray _lbls) {
@@ -651,11 +639,12 @@ void LBPH::train(InputArray _src, InputArray _lbls) {
     vector<Mat> src;
     _src.getMatVector(src);
     // turn the label matrix into a vector
-    vector<int> labels = _lbls.getMat();
-    if(labels.size() != src.size())
+    Mat labels = _lbls.getMat();
+    CV_Assert( labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1));
+    if(labels.total() != src.size())
         CV_Error(CV_StsUnsupportedFormat, "The number of labels must equal the number of samples.");
     // store given labels
-    _labels = labels;
+    labels.copyTo(_labels);
     // store the spatial histograms of the original data
     for(size_t sampleIdx = 0; sampleIdx < src.size(); sampleIdx++) {
         // calculate lbp image
@@ -690,7 +679,7 @@ int LBPH::predict(InputArray _src) const {
         double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
         if(dist < minDist) {
             minDist = dist;
-            minClass = _labels[sampleIdx];
+            minClass = _labels.at<int>(sampleIdx);
         }
     }
     return minClass;
@@ -712,5 +701,35 @@ Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius, int neighbors,
 {
     return new LBPH(radius, neighbors, grid_x, grid_y);
 }
+    
+CV_INIT_ALGORITHM(Eigenfaces, "FaceRecognizer.Eigenfaces",
+                  obj.info()->addParam(obj, "ncomponents", obj._num_components);
+                  obj.info()->addParam(obj, "projections", obj._projections, true);
+                  obj.info()->addParam(obj, "labels", obj._labels, true);
+                  obj.info()->addParam(obj, "eigenvectors", obj._eigenvectors, true);
+                  obj.info()->addParam(obj, "eigenvalues", obj._eigenvalues, true);
+                  obj.info()->addParam(obj, "mean", obj._mean, true));
+
+CV_INIT_ALGORITHM(Fisherfaces, "FaceRecognizer.Fisherfaces",
+                  obj.info()->addParam(obj, "ncomponents", obj._num_components);
+                  obj.info()->addParam(obj, "projections", obj._projections, true);
+                  obj.info()->addParam(obj, "labels", obj._labels, true);
+                  obj.info()->addParam(obj, "eigenvectors", obj._eigenvectors, true);
+                  obj.info()->addParam(obj, "eigenvalues", obj._eigenvalues, true);
+                  obj.info()->addParam(obj, "mean", obj._mean, true));    
+    
+CV_INIT_ALGORITHM(LBPH, "FaceRecognizer.LBPH",
+                  obj.info()->addParam(obj, "radius", obj._radius);
+                  obj.info()->addParam(obj, "neighbors", obj._neighbors);
+                  obj.info()->addParam(obj, "grid_x", obj._grid_x);
+                  obj.info()->addParam(obj, "grid_y", obj._grid_y);
+                  obj.info()->addParam(obj, "histograms", obj._histograms, true);
+                  obj.info()->addParam(obj, "labels", obj._labels, true));
+    
+bool initModule_contrib()
+{
+    Ptr<Algorithm> efaces = createEigenfaces(), ffaces = createFisherfaces(), lbph = createLBPH();
+    return efaces->info() != 0 && ffaces->info() != 0 && lbph->info() != 0;
+}
 
 }