From 36afd4ef55fd291d0948da41324d124aa2d3eb4a Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Tue, 6 May 2014 16:30:03 +0400 Subject: [PATCH 1/7] added additionalInfo in faceRecognition --- .../include/opencv2/contrib/contrib.hpp | 8 + modules/contrib/src/facerec.cpp | 186 +++++++++++++++++- samples/cpp/facerec_demo.cpp | 16 +- 3 files changed, 204 insertions(+), 6 deletions(-) diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index 7d881c359..18c6eeb4b 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -948,6 +948,14 @@ namespace cv // Deserializes this object from a given cv::FileStorage. virtual void load(const FileStorage& fs) = 0; + // Sets additions information as pairs label - info. + virtual void setLabelsInfo(const std::map& additionalInfo) = 0; + + // Gets string information by label + virtual string getLabelInfo(const int label) = 0; + + // Gets labels by string + virtual vector getLabelsByString(const string str) = 0; }; CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index a3d695ad1..20bd41107 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -18,6 +18,43 @@ #include "precomp.hpp" #include +struct LabelInfo +{ + LabelInfo():label(-1), value("") {} + LabelInfo(int _label, std::string _value): label(_label), value(_value) {} + std::string value; + int label; + void write(cv::FileStorage& fs) const + { + fs << "{" << "label" << label << "value" << value << "}"; + } + void read(const cv::FileNode& node) + { + label = (int)node["label"]; + value = (std::string)node["value"]; + } + friend std::ostream& operator<<(std::ostream& out, const LabelInfo& info); +}; + +static void write(cv::FileStorage& fs, const std::string&, const LabelInfo& x) +{ + x.write(fs); +} + +static void read(const cv::FileNode& node, LabelInfo& x, const LabelInfo& default_value = LabelInfo()) +{ + if(node.empty()) + x = default_value; + else + x.read(node); +} + +std::ostream& operator<<(std::ostream& out, const LabelInfo& info) +{ + out << "{ label = " << info.label << ", " << "value = " << info.value << "}"; + return out; +} + namespace cv { @@ -98,7 +135,6 @@ inline vector<_Tp> remove_dups(const vector<_Tp>& src) { return elems; } - // Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of // Cognitive Neuroscience 3 (1991), 71–86. class Eigenfaces : public FaceRecognizer @@ -111,6 +147,7 @@ private: Mat _eigenvectors; Mat _eigenvalues; Mat _mean; + std::map _labelsInfo; public: using FaceRecognizer::save; @@ -147,6 +184,15 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; + // Sets additions information as pairs label - info. + void setLabelsInfo(const std::map& labelsInfo); + + // Gets additional information by label + string getLabelInfo(const int label); + + // Gets labels by string + std::vector getLabelsByString(const string str); + AlgorithmInfo* info() const; }; @@ -164,6 +210,7 @@ private: Mat _mean; vector _projections; Mat _labels; + std::map _labelsInfo; public: using FaceRecognizer::save; @@ -202,6 +249,15 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; + // Sets additions information as pairs label - info. + void setLabelsInfo(const std::map& labelsInfo); + + // Gets additional information by label + string getLabelInfo(const int label); + + // Gets labels by string + std::vector getLabelsByString(const string str); + AlgorithmInfo* info() const; }; @@ -222,6 +278,7 @@ private: vector _histograms; Mat _labels; + std::map _labelsInfo; // Computes a LBPH model with images in src and // corresponding labels in labels, possibly preserving @@ -287,6 +344,15 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; + // Sets additions information as pairs label - info. + void setLabelsInfo(const std::map& labelsInfo); + + // Gets additional information by label + string getLabelInfo(const int label); + + // Gets labels by string + std::vector getLabelsByString(const string str); + // Getter functions. int neighbors() const { return _neighbors; } int radius() const { return _radius; } @@ -423,6 +489,17 @@ void Eigenfaces::load(const FileStorage& fs) { // read sequences readFileNodeList(fs["projections"], _projections); fs["labels"] >> _labels; + const FileNode& fn = fs["info"]; + if (fn.type() == FileNode::SEQ) + { + _labelsInfo.clear(); + for (FileNodeIterator it = fn.begin(); it != fn.end();) + { + LabelInfo item; + it >> item; + _labelsInfo.insert(std::make_pair(item.label, item.value)); + } + } } void Eigenfaces::save(FileStorage& fs) const { @@ -434,6 +511,34 @@ void Eigenfaces::save(FileStorage& fs) const { // write sequences writeFileNodeList(fs, "projections", _projections); fs << "labels" << _labels; + fs << "info" << "["; + for (std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + fs << LabelInfo(it->first, it->second); + fs << "]"; +} + +void Eigenfaces::setLabelsInfo(const std::map& labelsInfo) +{ + _labelsInfo = labelsInfo; +} + +string Eigenfaces::getLabelInfo(const int label) +{ + if(_labelsInfo.count(label) > 0) + return _labelsInfo[label]; + return ""; +} + +vector Eigenfaces::getLabelsByString(const string str) +{ + vector labels; + for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + { + size_t found = (it->second).find(str); + if(found != string::npos) + labels.push_back(it->first); + } + return labels; } //------------------------------------------------------------------------------ @@ -544,6 +649,17 @@ void Fisherfaces::load(const FileStorage& fs) { // read sequences readFileNodeList(fs["projections"], _projections); fs["labels"] >> _labels; + const FileNode& fn = fs["info"]; + if (fn.type() == FileNode::SEQ) + { + _labelsInfo.clear(); + for (FileNodeIterator it = fn.begin(); it != fn.end();) + { + LabelInfo item; + it >> item; + _labelsInfo.insert(std::make_pair(item.label, item.value)); + } + } } // See FaceRecognizer::save. @@ -556,6 +672,34 @@ void Fisherfaces::save(FileStorage& fs) const { // write sequences writeFileNodeList(fs, "projections", _projections); fs << "labels" << _labels; + fs << "info" << "["; + for (std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + fs << LabelInfo(it->first, it->second); + fs << "]"; +} + +void Fisherfaces::setLabelsInfo(const std::map& labelsInfo) +{ + _labelsInfo = labelsInfo; +} + +string Fisherfaces::getLabelInfo(const int label) +{ + if(_labelsInfo.count(label) > 0) + return _labelsInfo[label]; + return ""; +} + +vector Fisherfaces::getLabelsByString(const string str) +{ + vector labels; + for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + { + size_t found = (it->second).find(str); + if(found != string::npos) + labels.push_back(it->first); + } + return labels; } //------------------------------------------------------------------------------ @@ -743,6 +887,17 @@ void LBPH::load(const FileStorage& fs) { //read matrices readFileNodeList(fs["histograms"], _histograms); fs["labels"] >> _labels; + const FileNode& fn = fs["info"]; + if (fn.type() == FileNode::SEQ) + { + _labelsInfo.clear(); + for (FileNodeIterator it = fn.begin(); it != fn.end();) + { + LabelInfo item; + it >> item; + _labelsInfo.insert(std::make_pair(item.label, item.value)); + } + } } // See FaceRecognizer::save. @@ -754,6 +909,34 @@ void LBPH::save(FileStorage& fs) const { // write matrices writeFileNodeList(fs, "histograms", _histograms); fs << "labels" << _labels; + fs << "info" << "["; + for (std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + fs << LabelInfo(it->first, it->second); + fs << "]"; +} + +void LBPH::setLabelsInfo(const std::map& labelsInfo) +{ + _labelsInfo = labelsInfo; +} + +string LBPH::getLabelInfo(const int label) +{ + if(_labelsInfo.count(label) > 0) + return _labelsInfo[label]; + return ""; +} + +vector LBPH::getLabelsByString(const string str) +{ + vector labels; + for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + { + size_t found = (it->second).find(str); + if(found != string::npos) + labels.push_back(it->first); + } + return labels; } void LBPH::train(InputArrayOfArrays _in_src, InputArray _in_labels) { @@ -849,7 +1032,6 @@ int LBPH::predict(InputArray _src) const { return label; } - Ptr createEigenFaceRecognizer(int num_components, double threshold) { return new Eigenfaces(num_components, threshold); diff --git a/samples/cpp/facerec_demo.cpp b/samples/cpp/facerec_demo.cpp index 6402082e8..dfc15aa81 100644 --- a/samples/cpp/facerec_demo.cpp +++ b/samples/cpp/facerec_demo.cpp @@ -39,20 +39,23 @@ static Mat toGrayscale(InputArray _src) { return dst; } -static void read_csv(const string& filename, vector& images, vector& labels, char separator = ';') { +static void read_csv(const string& filename, vector& images, vector& labels, std::map& labelsInfo, char separator = ';') { std::ifstream file(filename.c_str(), ifstream::in); if (!file) { string error_message = "No valid input file was given, please check the given filename."; CV_Error(CV_StsBadArg, error_message); } - string line, path, classlabel; + string line, path, classlabel, info; while (getline(file, line)) { stringstream liness(line); getline(liness, path, separator); - getline(liness, classlabel); + getline(liness, classlabel, separator); + getline(liness, info, separator); if(!path.empty() && !classlabel.empty()) { images.push_back(imread(path, 0)); labels.push_back(atoi(classlabel.c_str())); + if(!info.empty()) + labelsInfo.insert(std::make_pair(labels.back(), info)); } } } @@ -69,15 +72,17 @@ int main(int argc, const char *argv[]) { // These vectors hold the images and corresponding labels. vector images; vector labels; + std::map labelsInfo; // Read in the data. This can fail if no valid // input filename is given. try { - read_csv(fn_csv, images, labels); + read_csv(fn_csv, images, labels, labelsInfo); } catch (cv::Exception& e) { cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl; // nothing more we can do exit(1); } + // Quit if there are not enough images for this demo. if(images.size() <= 1) { string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!"; @@ -111,6 +116,7 @@ int main(int argc, const char *argv[]) { // cv::createEigenFaceRecognizer(10, 123.0); // Ptr model = createEigenFaceRecognizer(); + model->setLabelsInfo(labelsInfo); model->train(images, labels); // The following line predicts the label of a given // test image: @@ -124,6 +130,8 @@ int main(int argc, const char *argv[]) { // string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel); cout << result_message << endl; + if( (predictedLabel == testLabel) && (model->getLabelInfo(predictedLabel) != "") ) + cout << format("%d-th label's info: %s", predictedLabel, model->getLabelInfo(predictedLabel).c_str()) << endl; // Sometimes you'll need to get/set internal model data, // which isn't exposed by the public cv::FaceRecognizer. // Since each cv::FaceRecognizer is derived from a From aa76ef9a98d64e45f441eb914541f78d66912b9f Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Wed, 7 May 2014 17:19:22 +0400 Subject: [PATCH 2/7] fixes --- .../include/opencv2/contrib/contrib.hpp | 4 +- modules/contrib/src/facerec.cpp | 46 +++++++++---------- samples/cpp/facerec_demo.cpp | 2 +- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index 18c6eeb4b..b3b4f330d 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -952,10 +952,10 @@ namespace cv virtual void setLabelsInfo(const std::map& additionalInfo) = 0; // Gets string information by label - virtual string getLabelInfo(const int label) = 0; + virtual string getLabelInfo(int label) const = 0; // Gets labels by string - virtual vector getLabelsByString(const string str) = 0; + virtual vector getLabelsByString(const string& str) = 0; }; CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index 20bd41107..9c310e031 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -21,9 +21,9 @@ struct LabelInfo { LabelInfo():label(-1), value("") {} - LabelInfo(int _label, std::string _value): label(_label), value(_value) {} - std::string value; + LabelInfo(int _label, const std::string &_value): label(_label), value(_value) {} int label; + std::string value; void write(cv::FileStorage& fs) const { fs << "{" << "label" << label << "value" << value << "}"; @@ -33,7 +33,11 @@ struct LabelInfo label = (int)node["label"]; value = (std::string)node["value"]; } - friend std::ostream& operator<<(std::ostream& out, const LabelInfo& info); + std::ostream& operator<<(std::ostream& out) + { + out << "{ label = " << label << ", " << "value = " << value << "}"; + return out; + } }; static void write(cv::FileStorage& fs, const std::string&, const LabelInfo& x) @@ -49,12 +53,6 @@ static void read(const cv::FileNode& node, LabelInfo& x, const LabelInfo& defaul x.read(node); } -std::ostream& operator<<(std::ostream& out, const LabelInfo& info) -{ - out << "{ label = " << info.label << ", " << "value = " << info.value << "}"; - return out; -} - namespace cv { @@ -188,10 +186,10 @@ public: void setLabelsInfo(const std::map& labelsInfo); // Gets additional information by label - string getLabelInfo(const int label); + string getLabelInfo(int label) const; // Gets labels by string - std::vector getLabelsByString(const string str); + std::vector getLabelsByString(const string& str); AlgorithmInfo* info() const; }; @@ -253,10 +251,10 @@ public: void setLabelsInfo(const std::map& labelsInfo); // Gets additional information by label - string getLabelInfo(const int label); + string getLabelInfo(int label) const; // Gets labels by string - std::vector getLabelsByString(const string str); + std::vector getLabelsByString(const string& str); AlgorithmInfo* info() const; }; @@ -348,10 +346,10 @@ public: void setLabelsInfo(const std::map& labelsInfo); // Gets additional information by label - string getLabelInfo(const int label); + string getLabelInfo(int label) const; // Gets labels by string - std::vector getLabelsByString(const string str); + std::vector getLabelsByString(const string& str); // Getter functions. int neighbors() const { return _neighbors; } @@ -522,14 +520,14 @@ void Eigenfaces::setLabelsInfo(const std::map& labelsInfo) _labelsInfo = labelsInfo; } -string Eigenfaces::getLabelInfo(const int label) +string Eigenfaces::getLabelInfo(int label) const { if(_labelsInfo.count(label) > 0) - return _labelsInfo[label]; + return _labelsInfo.at(label); return ""; } -vector Eigenfaces::getLabelsByString(const string str) +vector Eigenfaces::getLabelsByString(const string& str) { vector labels; for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) @@ -683,14 +681,14 @@ void Fisherfaces::setLabelsInfo(const std::map& labelsInfo) _labelsInfo = labelsInfo; } -string Fisherfaces::getLabelInfo(const int label) +string Fisherfaces::getLabelInfo(int label) const { if(_labelsInfo.count(label) > 0) - return _labelsInfo[label]; + return _labelsInfo.at(label); return ""; } -vector Fisherfaces::getLabelsByString(const string str) +vector Fisherfaces::getLabelsByString(const string& str) { vector labels; for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) @@ -920,14 +918,14 @@ void LBPH::setLabelsInfo(const std::map& labelsInfo) _labelsInfo = labelsInfo; } -string LBPH::getLabelInfo(const int label) +string LBPH::getLabelInfo(int label) const { if(_labelsInfo.count(label) > 0) - return _labelsInfo[label]; + return _labelsInfo.at(label); return ""; } -vector LBPH::getLabelsByString(const string str) +vector LBPH::getLabelsByString(const string& str) { vector labels; for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) diff --git a/samples/cpp/facerec_demo.cpp b/samples/cpp/facerec_demo.cpp index dfc15aa81..ef480c6df 100644 --- a/samples/cpp/facerec_demo.cpp +++ b/samples/cpp/facerec_demo.cpp @@ -130,7 +130,7 @@ int main(int argc, const char *argv[]) { // string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel); cout << result_message << endl; - if( (predictedLabel == testLabel) && (model->getLabelInfo(predictedLabel) != "") ) + if( (predictedLabel == testLabel) && !model->getLabelInfo(predictedLabel).empty() ) cout << format("%d-th label's info: %s", predictedLabel, model->getLabelInfo(predictedLabel).c_str()) << endl; // Sometimes you'll need to get/set internal model data, // which isn't exposed by the public cv::FaceRecognizer. From d67c9aabff3d16e6e7b1c966b5983ad513dcb5e7 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Thu, 8 May 2014 16:43:03 +0400 Subject: [PATCH 3/7] docs --- modules/contrib/doc/facerec/facerec_api.rst | 38 ++++++++++++++++++ .../include/opencv2/contrib/contrib.hpp | 4 +- modules/contrib/src/facerec.cpp | 39 +++++++++---------- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/modules/contrib/doc/facerec/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index 2aa3dcfa0..8de4359c5 100644 --- a/modules/contrib/doc/facerec/facerec_api.rst +++ b/modules/contrib/doc/facerec/facerec_api.rst @@ -46,6 +46,15 @@ a unified access to all face recongition algorithms in OpenCV. :: // Deserializes this object from a given cv::FileStorage. virtual void load(const FileStorage& fs) = 0; + + // Sets additional information as pairs label - info. + virtual void setLabelsInfo(const std::map& labelsInfo) = 0; + + // Gets string information by label + virtual string getLabelInfo(int label) const = 0; + + // Gets labels by string + virtual vector getLabelsByString(const string& str) = 0; }; @@ -70,6 +79,8 @@ Moreover every :ocv:class:`FaceRecognizer` supports the: * **Loading/Saving** the model state from/to a given XML or YAML. +* **Setting/Getting labels info**, that is storaged as a string. + .. note:: When using the FaceRecognizer interface in combination with Python, please stick to Python 2. Some underlying scripts like create_csv will not work in other versions, like Python 3. Setting the Thresholds @@ -293,6 +304,30 @@ to enable loading the model state. ``FaceRecognizer::load(FileStorage& fs)`` in turn gets called by ``FaceRecognizer::load(const string& filename)``, to ease saving a model. +FaceRecognizer::setLabelsInfo +----------------------------- + +Sets string information about labels into the model. +.. ocv:function:: void FaceRecognizer::setLabelsInfo(const std::map& labelsInfo) = 0 + +Information about the label loads as a pair label-its info. + +FaceRecognizer::getLabelInfo +---------------------------- + +Gets string information by label. +.. ocv:function:: string FaceRecognizer::getLabelInfo(int label) const = 0 + +If there is no such label in the model or there is no information about the label it will return an empty string. + +FaceRecognizer::getLabelsByString +--------------------------------- +Gets vector of labels by string. + +.. ocv:function:: vector FaceRecognizer::getLabelsByString(const string& str) = 0 + +If the string contained in a string information for a label, this label will be pushed into the vector. + createEigenFaceRecognizer ------------------------- @@ -319,6 +354,7 @@ Model internal data: * ``mean`` The sample mean calculated from the training data. * ``projections`` The projections of the training data. * ``labels`` The threshold applied in the prediction. If the distance to the nearest neighbor is larger than the threshold, this method returns -1. +* ``labelsInfo`` The string information about the labels. createFisherFaceRecognizer -------------------------- @@ -346,6 +382,7 @@ Model internal data: * ``mean`` The sample mean calculated from the training data. * ``projections`` The projections of the training data. * ``labels`` The labels corresponding to the projections. +* ``labelsInfo`` The string information about the labels. createLBPHFaceRecognizer @@ -375,3 +412,4 @@ Model internal data: * ``threshold`` see :ocv:func:`createLBPHFaceRecognizer`. * ``histograms`` Local Binary Patterns Histograms calculated from the given training data (empty if none was given). * ``labels`` Labels corresponding to the calculated Local Binary Patterns Histograms. +* ``labelsInfo`` The string information about the labels. diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index b3b4f330d..e6e11d816 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -948,8 +948,8 @@ namespace cv // Deserializes this object from a given cv::FileStorage. virtual void load(const FileStorage& fs) = 0; - // Sets additions information as pairs label - info. - virtual void setLabelsInfo(const std::map& additionalInfo) = 0; + // Sets additional information as pairs label - info. + virtual void setLabelsInfo(const std::map& labelsInfo) = 0; // Gets string information by label virtual string getLabelInfo(int label) const = 0; diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index 9c310e031..ef32b5273 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -182,10 +182,10 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; - // Sets additions information as pairs label - info. + // Sets additional information as pairs label - info. void setLabelsInfo(const std::map& labelsInfo); - // Gets additional information by label + // Gets string information by label string getLabelInfo(int label) const; // Gets labels by string @@ -247,10 +247,10 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; - // Sets additions information as pairs label - info. + // Sets additional information as pairs label - info. void setLabelsInfo(const std::map& labelsInfo); - // Gets additional information by label + // Gets string information by label string getLabelInfo(int label) const; // Gets labels by string @@ -342,10 +342,10 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; - // Sets additions information as pairs label - info. + // Sets additional information as pairs label - info. void setLabelsInfo(const std::map& labelsInfo); - // Gets additional information by label + // Gets string information by label string getLabelInfo(int label) const; // Gets labels by string @@ -487,7 +487,7 @@ void Eigenfaces::load(const FileStorage& fs) { // read sequences readFileNodeList(fs["projections"], _projections); fs["labels"] >> _labels; - const FileNode& fn = fs["info"]; + const FileNode& fn = fs["labelsInfo"]; if (fn.type() == FileNode::SEQ) { _labelsInfo.clear(); @@ -509,7 +509,7 @@ void Eigenfaces::save(FileStorage& fs) const { // write sequences writeFileNodeList(fs, "projections", _projections); fs << "labels" << _labels; - fs << "info" << "["; + fs << "labelsInfo" << "["; for (std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) fs << LabelInfo(it->first, it->second); fs << "]"; @@ -522,9 +522,8 @@ void Eigenfaces::setLabelsInfo(const std::map& labelsInfo) string Eigenfaces::getLabelInfo(int label) const { - if(_labelsInfo.count(label) > 0) - return _labelsInfo.at(label); - return ""; + std::map::const_iterator iter(_labelsInfo.find(label)); + return iter != _labelsInfo.end() ? iter->second : ""; } vector Eigenfaces::getLabelsByString(const string& str) @@ -647,7 +646,7 @@ void Fisherfaces::load(const FileStorage& fs) { // read sequences readFileNodeList(fs["projections"], _projections); fs["labels"] >> _labels; - const FileNode& fn = fs["info"]; + const FileNode& fn = fs["labelsInfo"]; if (fn.type() == FileNode::SEQ) { _labelsInfo.clear(); @@ -670,7 +669,7 @@ void Fisherfaces::save(FileStorage& fs) const { // write sequences writeFileNodeList(fs, "projections", _projections); fs << "labels" << _labels; - fs << "info" << "["; + fs << "labelsInfo" << "["; for (std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) fs << LabelInfo(it->first, it->second); fs << "]"; @@ -683,9 +682,8 @@ void Fisherfaces::setLabelsInfo(const std::map& labelsInfo) string Fisherfaces::getLabelInfo(int label) const { - if(_labelsInfo.count(label) > 0) - return _labelsInfo.at(label); - return ""; + std::map::const_iterator iter(_labelsInfo.find(label)); + return iter != _labelsInfo.end() ? iter->second : ""; } vector Fisherfaces::getLabelsByString(const string& str) @@ -885,7 +883,7 @@ void LBPH::load(const FileStorage& fs) { //read matrices readFileNodeList(fs["histograms"], _histograms); fs["labels"] >> _labels; - const FileNode& fn = fs["info"]; + const FileNode& fn = fs["labelsInfo"]; if (fn.type() == FileNode::SEQ) { _labelsInfo.clear(); @@ -907,7 +905,7 @@ void LBPH::save(FileStorage& fs) const { // write matrices writeFileNodeList(fs, "histograms", _histograms); fs << "labels" << _labels; - fs << "info" << "["; + fs << "labelsInfo" << "["; for (std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) fs << LabelInfo(it->first, it->second); fs << "]"; @@ -920,9 +918,8 @@ void LBPH::setLabelsInfo(const std::map& labelsInfo) string LBPH::getLabelInfo(int label) const { - if(_labelsInfo.count(label) > 0) - return _labelsInfo.at(label); - return ""; + std::map::const_iterator iter(_labelsInfo.find(label)); + return iter != _labelsInfo.end() ? iter->second : ""; } vector LBPH::getLabelsByString(const string& str) From a46f119fdf1f0dc05608e2e6d8a120325650c13c Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Mon, 19 May 2014 09:54:15 +0400 Subject: [PATCH 4/7] docs fixes --- modules/contrib/doc/facerec/facerec_api.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/contrib/doc/facerec/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index 8de4359c5..4c91bb7cb 100644 --- a/modules/contrib/doc/facerec/facerec_api.rst +++ b/modules/contrib/doc/facerec/facerec_api.rst @@ -310,7 +310,7 @@ FaceRecognizer::setLabelsInfo Sets string information about labels into the model. .. ocv:function:: void FaceRecognizer::setLabelsInfo(const std::map& labelsInfo) = 0 -Information about the label loads as a pair label-its info. +Information about the label loads as a pair "label id - string info". FaceRecognizer::getLabelInfo ---------------------------- @@ -318,7 +318,7 @@ FaceRecognizer::getLabelInfo Gets string information by label. .. ocv:function:: string FaceRecognizer::getLabelInfo(int label) const = 0 -If there is no such label in the model or there is no information about the label it will return an empty string. +If an unknown label id is provided or there is no label information assosiated with the specified label id the method returns an empty string. FaceRecognizer::getLabelsByString --------------------------------- @@ -326,7 +326,7 @@ Gets vector of labels by string. .. ocv:function:: vector FaceRecognizer::getLabelsByString(const string& str) = 0 -If the string contained in a string information for a label, this label will be pushed into the vector. +The function searches for the labels containing the specified substring in the associated string info. createEigenFaceRecognizer ------------------------- From 8d4a76925c47703ebc13d593787dacc4b69568cc Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Tue, 20 May 2014 18:03:20 +0400 Subject: [PATCH 5/7] fixed binary compatibility --- modules/contrib/doc/facerec/facerec_api.rst | 15 +- .../include/opencv2/contrib/contrib.hpp | 6 +- modules/contrib/src/facerec.cpp | 169 +++++++----------- samples/cpp/facerec_demo.cpp | 1 + 4 files changed, 76 insertions(+), 115 deletions(-) diff --git a/modules/contrib/doc/facerec/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index 4c91bb7cb..edb6edb1d 100644 --- a/modules/contrib/doc/facerec/facerec_api.rst +++ b/modules/contrib/doc/facerec/facerec_api.rst @@ -48,13 +48,13 @@ a unified access to all face recongition algorithms in OpenCV. :: virtual void load(const FileStorage& fs) = 0; // Sets additional information as pairs label - info. - virtual void setLabelsInfo(const std::map& labelsInfo) = 0; + void setLabelsInfo(const std::map& labelsInfo); // Gets string information by label - virtual string getLabelInfo(int label) const = 0; + string getLabelInfo(const int &label); // Gets labels by string - virtual vector getLabelsByString(const string& str) = 0; + vector getLabelsByString(const string& str); }; @@ -308,7 +308,7 @@ FaceRecognizer::setLabelsInfo ----------------------------- Sets string information about labels into the model. -.. ocv:function:: void FaceRecognizer::setLabelsInfo(const std::map& labelsInfo) = 0 +.. ocv:function:: void FaceRecognizer::setLabelsInfo(const std::map& labelsInfo) Information about the label loads as a pair "label id - string info". @@ -316,7 +316,7 @@ FaceRecognizer::getLabelInfo ---------------------------- Gets string information by label. -.. ocv:function:: string FaceRecognizer::getLabelInfo(int label) const = 0 +.. ocv:function:: string FaceRecognizer::getLabelInfo(const int &label) If an unknown label id is provided or there is no label information assosiated with the specified label id the method returns an empty string. @@ -324,7 +324,7 @@ FaceRecognizer::getLabelsByString --------------------------------- Gets vector of labels by string. -.. ocv:function:: vector FaceRecognizer::getLabelsByString(const string& str) = 0 +.. ocv:function:: vector FaceRecognizer::getLabelsByString(const string& str) The function searches for the labels containing the specified substring in the associated string info. @@ -354,7 +354,6 @@ Model internal data: * ``mean`` The sample mean calculated from the training data. * ``projections`` The projections of the training data. * ``labels`` The threshold applied in the prediction. If the distance to the nearest neighbor is larger than the threshold, this method returns -1. -* ``labelsInfo`` The string information about the labels. createFisherFaceRecognizer -------------------------- @@ -382,7 +381,6 @@ Model internal data: * ``mean`` The sample mean calculated from the training data. * ``projections`` The projections of the training data. * ``labels`` The labels corresponding to the projections. -* ``labelsInfo`` The string information about the labels. createLBPHFaceRecognizer @@ -412,4 +410,3 @@ Model internal data: * ``threshold`` see :ocv:func:`createLBPHFaceRecognizer`. * ``histograms`` Local Binary Patterns Histograms calculated from the given training data (empty if none was given). * ``labels`` Labels corresponding to the calculated Local Binary Patterns Histograms. -* ``labelsInfo`` The string information about the labels. diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index e6e11d816..5684ee242 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -949,13 +949,13 @@ namespace cv virtual void load(const FileStorage& fs) = 0; // Sets additional information as pairs label - info. - virtual void setLabelsInfo(const std::map& labelsInfo) = 0; + void setLabelsInfo(const std::map& labelsInfo); // Gets string information by label - virtual string getLabelInfo(int label) const = 0; + string getLabelInfo(const int &label); // Gets labels by string - virtual vector getLabelsByString(const string& str) = 0; + vector getLabelsByString(const string& str); }; CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index ef32b5273..170f63668 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -133,9 +133,51 @@ inline vector<_Tp> remove_dups(const vector<_Tp>& src) { return elems; } +// This class was introduced to avoid an addition of new virtual functions in FaceRecognizer class. +// It is safe for a binary compatibility. +class FaceRecognizerBase : public FaceRecognizer +{ +protected: + // Stored pairs "label id - string info" + std::map _labelsInfo; + +public: + // Sets additional information as pairs label - info. + virtual void setLabelsInfo(const std::map& labelsInfo); + + // Gets string information by label + virtual string getLabelInfo(int label) const; + + // Gets labels by string + virtual vector getLabelsByString(const string& str); +}; + +void FaceRecognizerBase::setLabelsInfo(const std::map& labelsInfo) +{ + _labelsInfo = labelsInfo; +} + +string FaceRecognizerBase::getLabelInfo(int label) const +{ + std::map::const_iterator iter(_labelsInfo.find(label)); + return iter != _labelsInfo.end() ? iter->second : ""; +} + +vector FaceRecognizerBase::getLabelsByString(const string& str) +{ + vector labels; + for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + { + size_t found = (it->second).find(str); + if(found != string::npos) + labels.push_back(it->first); + } + return labels; +} + // Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of // Cognitive Neuroscience 3 (1991), 71–86. -class Eigenfaces : public FaceRecognizer +class Eigenfaces : public FaceRecognizerBase { private: int _num_components; @@ -145,7 +187,6 @@ private: Mat _eigenvectors; Mat _eigenvalues; Mat _mean; - std::map _labelsInfo; public: using FaceRecognizer::save; @@ -182,15 +223,6 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; - // Sets additional information as pairs label - info. - void setLabelsInfo(const std::map& labelsInfo); - - // Gets string information by label - string getLabelInfo(int label) const; - - // Gets labels by string - std::vector getLabelsByString(const string& str); - AlgorithmInfo* info() const; }; @@ -198,7 +230,7 @@ public: // faces: Recognition using class specific linear projection.". IEEE // Transactions on Pattern Analysis and Machine Intelligence 19, 7 (1997), // 711–720. -class Fisherfaces: public FaceRecognizer +class Fisherfaces: public FaceRecognizerBase { private: int _num_components; @@ -208,7 +240,6 @@ private: Mat _mean; vector _projections; Mat _labels; - std::map _labelsInfo; public: using FaceRecognizer::save; @@ -247,15 +278,6 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; - // Sets additional information as pairs label - info. - void setLabelsInfo(const std::map& labelsInfo); - - // Gets string information by label - string getLabelInfo(int label) const; - - // Gets labels by string - std::vector getLabelsByString(const string& str); - AlgorithmInfo* info() const; }; @@ -265,7 +287,7 @@ public: // patterns: Application to face recognition." IEEE Transactions on Pattern // Analysis and Machine Intelligence, 28(12):2037-2041. // -class LBPH : public FaceRecognizer +class LBPH : public FaceRecognizerBase { private: int _grid_x; @@ -276,14 +298,12 @@ private: vector _histograms; Mat _labels; - std::map _labelsInfo; // Computes a LBPH model with images in src and // corresponding labels in labels, possibly preserving // old model data. void train(InputArrayOfArrays src, InputArray labels, bool preserveData); - public: using FaceRecognizer::save; using FaceRecognizer::load; @@ -342,15 +362,6 @@ public: // See FaceRecognizer::save. void save(FileStorage& fs) const; - // Sets additional information as pairs label - info. - void setLabelsInfo(const std::map& labelsInfo); - - // Gets string information by label - string getLabelInfo(int label) const; - - // Gets labels by string - std::vector getLabelsByString(const string& str); - // Getter functions. int neighbors() const { return _neighbors; } int radius() const { return _radius; } @@ -391,6 +402,27 @@ void FaceRecognizer::load(const string& filename) { fs.release(); } +void FaceRecognizer::setLabelsInfo(const std::map& labelsInfo) +{ + FaceRecognizerBase* base = dynamic_cast(this); + CV_Assert(base != 0); + base->setLabelsInfo(labelsInfo); +} + +string FaceRecognizer::getLabelInfo(const int &label) +{ + FaceRecognizerBase* base = dynamic_cast(this); + CV_Assert(base != 0); + return base->getLabelInfo(label); +} + +vector FaceRecognizer::getLabelsByString(const string& str) +{ + FaceRecognizerBase* base = dynamic_cast(this); + CV_Assert(base != 0); + return base->getLabelsByString(str); +} + //------------------------------------------------------------------------------ // Eigenfaces //------------------------------------------------------------------------------ @@ -515,29 +547,6 @@ void Eigenfaces::save(FileStorage& fs) const { fs << "]"; } -void Eigenfaces::setLabelsInfo(const std::map& labelsInfo) -{ - _labelsInfo = labelsInfo; -} - -string Eigenfaces::getLabelInfo(int label) const -{ - std::map::const_iterator iter(_labelsInfo.find(label)); - return iter != _labelsInfo.end() ? iter->second : ""; -} - -vector Eigenfaces::getLabelsByString(const string& str) -{ - vector labels; - for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) - { - size_t found = (it->second).find(str); - if(found != string::npos) - labels.push_back(it->first); - } - return labels; -} - //------------------------------------------------------------------------------ // Fisherfaces //------------------------------------------------------------------------------ @@ -675,29 +684,6 @@ void Fisherfaces::save(FileStorage& fs) const { fs << "]"; } -void Fisherfaces::setLabelsInfo(const std::map& labelsInfo) -{ - _labelsInfo = labelsInfo; -} - -string Fisherfaces::getLabelInfo(int label) const -{ - std::map::const_iterator iter(_labelsInfo.find(label)); - return iter != _labelsInfo.end() ? iter->second : ""; -} - -vector Fisherfaces::getLabelsByString(const string& str) -{ - vector labels; - for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) - { - size_t found = (it->second).find(str); - if(found != string::npos) - labels.push_back(it->first); - } - return labels; -} - //------------------------------------------------------------------------------ // LBPH //------------------------------------------------------------------------------ @@ -911,29 +897,6 @@ void LBPH::save(FileStorage& fs) const { fs << "]"; } -void LBPH::setLabelsInfo(const std::map& labelsInfo) -{ - _labelsInfo = labelsInfo; -} - -string LBPH::getLabelInfo(int label) const -{ - std::map::const_iterator iter(_labelsInfo.find(label)); - return iter != _labelsInfo.end() ? iter->second : ""; -} - -vector LBPH::getLabelsByString(const string& str) -{ - vector labels; - for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) - { - size_t found = (it->second).find(str); - if(found != string::npos) - labels.push_back(it->first); - } - return labels; -} - void LBPH::train(InputArrayOfArrays _in_src, InputArray _in_labels) { this->train(_in_src, _in_labels, false); } diff --git a/samples/cpp/facerec_demo.cpp b/samples/cpp/facerec_demo.cpp index ef480c6df..b92308e89 100644 --- a/samples/cpp/facerec_demo.cpp +++ b/samples/cpp/facerec_demo.cpp @@ -118,6 +118,7 @@ int main(int argc, const char *argv[]) { Ptr model = createEigenFaceRecognizer(); model->setLabelsInfo(labelsInfo); model->train(images, labels); + // The following line predicts the label of a given // test image: int predictedLabel = model->predict(testSample); From 59c8edfd987a93f77cf862f14ab25b2d384132d7 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Wed, 28 May 2014 15:28:54 +0400 Subject: [PATCH 6/7] facerec2 --- modules/contrib/doc/facerec/facerec_api.rst | 2 +- .../include/opencv2/contrib/contrib.hpp | 20 ++++++++++ modules/contrib/src/facerec.cpp | 37 +++++-------------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/modules/contrib/doc/facerec/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index edb6edb1d..3da37bdd1 100644 --- a/modules/contrib/doc/facerec/facerec_api.rst +++ b/modules/contrib/doc/facerec/facerec_api.rst @@ -79,7 +79,7 @@ Moreover every :ocv:class:`FaceRecognizer` supports the: * **Loading/Saving** the model state from/to a given XML or YAML. -* **Setting/Getting labels info**, that is storaged as a string. +* **Setting/Getting labels info**, that is storaged as a string. String labels info is useful for keeping names of the recognized people. .. note:: When using the FaceRecognizer interface in combination with Python, please stick to Python 2. Some underlying scripts like create_csv will not work in other versions, like Python 3. diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index 5684ee242..f74d9ca49 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -958,6 +958,26 @@ namespace cv vector getLabelsByString(const string& str); }; + // The FaceRecognizerBase class is introduced to keep the FaceRecognizer binary backward compatibility in 2.4 + // In master setLabelInfo/getLabelInfo/getLabelsByString should be virtual and _labelsInfo should be moved to FaceRecognizer + // that allows to avoid FaceRecognizer2 in master + class FaceRecognizer2 : public FaceRecognizer + { + protected: + // Stored pairs "label id - string info" + std::map _labelsInfo; + + public: + // Sets additional information as pairs label - info. + virtual void setLabelsInfo(const std::map& labelsInfo); + + // Gets string information by label + virtual string getLabelInfo(int label) const; + + // Gets labels by string + virtual vector getLabelsByString(const string& str); + }; + CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); CV_EXPORTS_W Ptr createFisherFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); CV_EXPORTS_W Ptr createLBPHFaceRecognizer(int radius=1, int neighbors=8, diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index 170f63668..f24e3ff4c 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -133,37 +133,18 @@ inline vector<_Tp> remove_dups(const vector<_Tp>& src) { return elems; } -// This class was introduced to avoid an addition of new virtual functions in FaceRecognizer class. -// It is safe for a binary compatibility. -class FaceRecognizerBase : public FaceRecognizer -{ -protected: - // Stored pairs "label id - string info" - std::map _labelsInfo; - -public: - // Sets additional information as pairs label - info. - virtual void setLabelsInfo(const std::map& labelsInfo); - - // Gets string information by label - virtual string getLabelInfo(int label) const; - - // Gets labels by string - virtual vector getLabelsByString(const string& str); -}; - -void FaceRecognizerBase::setLabelsInfo(const std::map& labelsInfo) +void FaceRecognizer2::setLabelsInfo(const std::map& labelsInfo) { _labelsInfo = labelsInfo; } -string FaceRecognizerBase::getLabelInfo(int label) const +string FaceRecognizer2::getLabelInfo(int label) const { std::map::const_iterator iter(_labelsInfo.find(label)); return iter != _labelsInfo.end() ? iter->second : ""; } -vector FaceRecognizerBase::getLabelsByString(const string& str) +vector FaceRecognizer2::getLabelsByString(const string& str) { vector labels; for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) @@ -177,7 +158,7 @@ vector FaceRecognizerBase::getLabelsByString(const string& str) // Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of // Cognitive Neuroscience 3 (1991), 71–86. -class Eigenfaces : public FaceRecognizerBase +class Eigenfaces : public FaceRecognizer2 { private: int _num_components; @@ -230,7 +211,7 @@ public: // faces: Recognition using class specific linear projection.". IEEE // Transactions on Pattern Analysis and Machine Intelligence 19, 7 (1997), // 711–720. -class Fisherfaces: public FaceRecognizerBase +class Fisherfaces: public FaceRecognizer2 { private: int _num_components; @@ -287,7 +268,7 @@ public: // patterns: Application to face recognition." IEEE Transactions on Pattern // Analysis and Machine Intelligence, 28(12):2037-2041. // -class LBPH : public FaceRecognizerBase +class LBPH : public FaceRecognizer2 { private: int _grid_x; @@ -404,21 +385,21 @@ void FaceRecognizer::load(const string& filename) { void FaceRecognizer::setLabelsInfo(const std::map& labelsInfo) { - FaceRecognizerBase* base = dynamic_cast(this); + FaceRecognizer2* base = dynamic_cast(this); CV_Assert(base != 0); base->setLabelsInfo(labelsInfo); } string FaceRecognizer::getLabelInfo(const int &label) { - FaceRecognizerBase* base = dynamic_cast(this); + FaceRecognizer2* base = dynamic_cast(this); CV_Assert(base != 0); return base->getLabelInfo(label); } vector FaceRecognizer::getLabelsByString(const string& str) { - FaceRecognizerBase* base = dynamic_cast(this); + FaceRecognizer2* base = dynamic_cast(this); CV_Assert(base != 0); return base->getLabelsByString(str); } From 02b32d86d342083dbc4327300a94f0bf7cb5b48f Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Mon, 9 Jun 2014 13:26:45 +0400 Subject: [PATCH 7/7] moving FaceRecognizer2 from public header to .cpp --- .../include/opencv2/contrib/contrib.hpp | 20 --- modules/contrib/src/facerec.cpp | 121 ++++++++++-------- 2 files changed, 69 insertions(+), 72 deletions(-) diff --git a/modules/contrib/include/opencv2/contrib/contrib.hpp b/modules/contrib/include/opencv2/contrib/contrib.hpp index f74d9ca49..5684ee242 100644 --- a/modules/contrib/include/opencv2/contrib/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib/contrib.hpp @@ -958,26 +958,6 @@ namespace cv vector getLabelsByString(const string& str); }; - // The FaceRecognizerBase class is introduced to keep the FaceRecognizer binary backward compatibility in 2.4 - // In master setLabelInfo/getLabelInfo/getLabelsByString should be virtual and _labelsInfo should be moved to FaceRecognizer - // that allows to avoid FaceRecognizer2 in master - class FaceRecognizer2 : public FaceRecognizer - { - protected: - // Stored pairs "label id - string info" - std::map _labelsInfo; - - public: - // Sets additional information as pairs label - info. - virtual void setLabelsInfo(const std::map& labelsInfo); - - // Gets string information by label - virtual string getLabelInfo(int label) const; - - // Gets labels by string - virtual vector getLabelsByString(const string& str); - }; - CV_EXPORTS_W Ptr createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); CV_EXPORTS_W Ptr createFisherFaceRecognizer(int num_components = 0, double threshold = DBL_MAX); CV_EXPORTS_W Ptr createLBPHFaceRecognizer(int radius=1, int neighbors=8, diff --git a/modules/contrib/src/facerec.cpp b/modules/contrib/src/facerec.cpp index f24e3ff4c..3f8aafbda 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -18,41 +18,6 @@ #include "precomp.hpp" #include -struct LabelInfo -{ - LabelInfo():label(-1), value("") {} - LabelInfo(int _label, const std::string &_value): label(_label), value(_value) {} - int label; - std::string value; - void write(cv::FileStorage& fs) const - { - fs << "{" << "label" << label << "value" << value << "}"; - } - void read(const cv::FileNode& node) - { - label = (int)node["label"]; - value = (std::string)node["value"]; - } - std::ostream& operator<<(std::ostream& out) - { - out << "{ label = " << label << ", " << "value = " << value << "}"; - return out; - } -}; - -static void write(cv::FileStorage& fs, const std::string&, const LabelInfo& x) -{ - x.write(fs); -} - -static void read(const cv::FileNode& node, LabelInfo& x, const LabelInfo& default_value = LabelInfo()) -{ - if(node.empty()) - x = default_value; - else - x.read(node); -} - namespace cv { @@ -133,29 +98,81 @@ inline vector<_Tp> remove_dups(const vector<_Tp>& src) { return elems; } -void FaceRecognizer2::setLabelsInfo(const std::map& labelsInfo) +// The FaceRecognizer2 class is introduced to keep the FaceRecognizer binary backward compatibility in 2.4 +// In master setLabelInfo/getLabelInfo/getLabelsByString should be virtual and _labelsInfo should be moved +// to FaceRecognizer, that allows to avoid FaceRecognizer2 in master +class FaceRecognizer2 : public FaceRecognizer { - _labelsInfo = labelsInfo; -} +protected: + // Stored pairs "label id - string info" + std::map _labelsInfo; -string FaceRecognizer2::getLabelInfo(int label) const -{ - std::map::const_iterator iter(_labelsInfo.find(label)); - return iter != _labelsInfo.end() ? iter->second : ""; -} - -vector FaceRecognizer2::getLabelsByString(const string& str) -{ - vector labels; - for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) +public: + // Sets additional information as pairs label - info. + virtual void setLabelsInfo(const std::map& labelsInfo) { - size_t found = (it->second).find(str); - if(found != string::npos) - labels.push_back(it->first); + _labelsInfo = labelsInfo; } - return labels; + + // Gets string information by label + virtual string getLabelInfo(int label) const + { + std::map::const_iterator iter(_labelsInfo.find(label)); + return iter != _labelsInfo.end() ? iter->second : ""; + } + + // Gets labels by string + virtual vector getLabelsByString(const string& str) + { + vector labels; + for(std::map::const_iterator it = _labelsInfo.begin(); it != _labelsInfo.end(); it++) + { + size_t found = (it->second).find(str); + if(found != string::npos) + labels.push_back(it->first); + } + return labels; + } + +}; + +// Utility structure to load/save face label info (a pair of int and string) via FileStorage +struct LabelInfo +{ + LabelInfo():label(-1), value("") {} + LabelInfo(int _label, const std::string &_value): label(_label), value(_value) {} + int label; + std::string value; + void write(cv::FileStorage& fs) const + { + fs << "{" << "label" << label << "value" << value << "}"; + } + void read(const cv::FileNode& node) + { + label = (int)node["label"]; + value = (std::string)node["value"]; + } + std::ostream& operator<<(std::ostream& out) + { + out << "{ label = " << label << ", " << "value = " << value << "}"; + return out; + } +}; + +static void write(cv::FileStorage& fs, const std::string&, const LabelInfo& x) +{ + x.write(fs); } +static void read(const cv::FileNode& node, LabelInfo& x, const LabelInfo& default_value = LabelInfo()) +{ + if(node.empty()) + x = default_value; + else + x.read(node); +} + + // Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of // Cognitive Neuroscience 3 (1991), 71–86. class Eigenfaces : public FaceRecognizer2