Merge pull request #402 from comdiv:comdiv

pull/466/head
Maksim Shabunin 9 years ago
commit 173512b921
  1. 20
      modules/face/include/opencv2/face.hpp
  2. 102
      modules/face/include/opencv2/face/predict_collector.hpp
  3. 29
      modules/face/src/eigen_faces.cpp
  4. 14
      modules/face/src/facerec.cpp
  5. 27
      modules/face/src/fisher_faces.cpp
  6. 27
      modules/face/src/lbph_faces.cpp
  7. 86
      modules/face/src/predict_collector.cpp

@ -48,6 +48,7 @@ the use of this software, even if advised of the possibility of such damage.
*/
#include "opencv2/core.hpp"
#include "face/predict_collector.hpp"
#include <map>
namespace cv { namespace face {
@ -255,7 +256,8 @@ public:
CV_WRAP virtual void update(InputArrayOfArrays src, InputArray labels);
/** @overload */
virtual int predict(InputArray src) const = 0;
CV_WRAP int predict(InputArray src) const;
/** @brief Predicts a label and associated confidence (e.g. distance) for a given input image.
@ -292,7 +294,18 @@ public:
model->predict(img, predicted_label, predicted_confidence);
@endcode
*/
CV_WRAP virtual void predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) const = 0;
CV_WRAP void predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) const;
/** @brief - if implemented - send all result of prediction to collector that can be used for somehow custom result handling
@param src Sample image to get a prediction from.
@param collector User-defined collector object that accepts all results
@param state - optional user-defined state token that should be passed back from FaceRecognizer implementation
To implement this method u just have to do same internal cycle as in predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) but
not try to get "best@ result, just resend it to caller side with given collector
*/
CV_WRAP virtual void predict(InputArray src, Ptr<PredictCollector> collector, const int state = 0) const = 0;
/** @brief Saves a FaceRecognizer and its model state.
@ -345,7 +358,8 @@ public:
info.
*/
CV_WRAP virtual std::vector<int> getLabelsByString(const String& str) const;
/** @brief threshhold parameter accessor - required for default BestMinDist collector */
virtual double getThreshold() const = 0;
protected:
// Stored pairs "label id - string info"
std::map<int, String> _labelsInfo;

@ -0,0 +1,102 @@
/*
By downloading, copying, installing or using the software you agree to this license.
If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2000-2015, Intel Corporation, all rights reserved.
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved.
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
Copyright (C) 2015, OpenCV Foundation, all rights reserved.
Copyright (C) 2015, Itseez Inc., all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall copyright holders or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
*/
#ifndef __OPENCV_PREDICT_COLLECTOR_HPP__
#define __OPENCV_PREDICT_COLLECTOR_HPP__
#include <cfloat>
#include "opencv2/core/cvdef.h"
#include "opencv2/core/cvstd.hpp"
namespace cv {
namespace face {
//! @addtogroup face
//! @{
/** @brief Abstract base class for all strategies of prediction result handling
*/
class CV_EXPORTS_W PredictCollector {
protected:
double _threshhold;
int _size;
int _state;
public:
/** @brief creates new predict collector with given threshhold */
PredictCollector(double threshhold = DBL_MAX) :_threshhold(threshhold) {};
CV_WRAP virtual ~PredictCollector() {}
/** @brief called once at start of recognition
@param size total size of prediction evaluation that recognizer could perform
@param state user defined send-to-back optional value to allow multi-thread, multi-session or aggregation scenarios
*/
CV_WRAP virtual void init(const int size, const int state = 0);
/** @brief called with every recognition result
@param label current prediction label
@param dist current prediction distance (confidence)
@param state user defined send-to-back optional value to allow multi-thread, multi-session or aggregation scenarios
@return true if recognizer should proceed prediction , false - if recognizer should terminate prediction
*/
CV_WRAP virtual bool emit(const int label, const double dist, const int state = 0); //not abstract while Python generation require non-abstract class
};
/** @brief default predict collector that trace minimal distance with treshhold checking (that is default behavior for most predict logic)
*/
class CV_EXPORTS_W MinDistancePredictCollector : public PredictCollector {
private:
int _label;
double _dist;
public:
/** @brief creates new MinDistancePredictCollector with given threshhold */
CV_WRAP MinDistancePredictCollector(double threshhold = DBL_MAX) : PredictCollector(threshhold) {
_label = 0;
_dist = DBL_MAX;
};
CV_WRAP bool emit(const int label, const double dist, const int state = 0);
/** @brief result label, 0 if not found */
CV_WRAP int getLabel() const;
/** @brief result distance (confidence) DBL_MAX if not found */
CV_WRAP double getDist() const;
/** @brief factory method to create cv-pointers to MinDistancePredictCollector */
CV_WRAP static Ptr<MinDistancePredictCollector> create(double threshold = DBL_MAX);
};
//! @}
}
}
#endif

@ -41,11 +41,8 @@ public:
// in labels.
void train(InputArrayOfArrays src, InputArray labels);
// Predicts the label of a query image in src.
int predict(InputArray src) const;
// Predicts the label and confidence for a given sample.
void predict(InputArray _src, int &label, double &dist) const;
// Send all predict results to caller side for custom result handling
void predict(InputArray src, Ptr<PredictCollector> collector, const int state) const;
};
//------------------------------------------------------------------------------
@ -102,7 +99,7 @@ void Eigenfaces::train(InputArrayOfArrays _src, InputArray _local_labels) {
}
}
void Eigenfaces::predict(InputArray _src, int &minClass, double &minDist) const {
void Eigenfaces::predict(InputArray _src, Ptr<PredictCollector> collector, const int state) const {
// get data
Mat src = _src.getMat();
// make sure the user is passing correct data
@ -116,25 +113,15 @@ void Eigenfaces::predict(InputArray _src, int &minClass, double &minDist) const
CV_Error(Error::StsBadArg, error_message);
}
// project into PCA subspace
Mat q = LDA::subspaceProject(_eigenvectors, _mean, src.reshape(1,1));
minDist = DBL_MAX;
minClass = -1;
for(size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
Mat q = LDA::subspaceProject(_eigenvectors, _mean, src.reshape(1, 1));
collector->init((int)_projections.size(), state);
for (size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
double dist = norm(_projections[sampleIdx], q, NORM_L2);
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
int label = _labels.at<int>((int)sampleIdx);
if (!collector->emit(label, dist, state))return;
}
}
int Eigenfaces::predict(InputArray _src) const {
int label;
double dummy;
predict(_src, label, dummy);
return label;
}
Ptr<BasicFaceRecognizer> createEigenFaceRecognizer(int num_components, double threshold)
{
return makePtr<Eigenfaces>(num_components, threshold);

@ -72,6 +72,20 @@ void FaceRecognizer::save(const String &filename) const
fs.release();
}
int FaceRecognizer::predict(InputArray src) const {
int _label;
double _dist;
predict(src, _label, _dist);
return _label;
}
void FaceRecognizer::predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) const {
Ptr<MinDistancePredictCollector> collector = MinDistancePredictCollector::create(getThreshold());
predict(src, collector, 0);
label = collector->getLabel();
confidence = collector->getDist();
}
}
}

@ -36,11 +36,8 @@ public:
// in labels.
void train(InputArrayOfArrays src, InputArray labels);
// Predicts the label of a query image in src.
int predict(InputArray src) const;
// Predicts the label and confidence for a given sample.
void predict(InputArray _src, int &label, double &dist) const;
// Send all predict results to caller side for custom result handling
void predict(InputArray src, Ptr<PredictCollector> collector, const int state) const;
};
// Removes duplicate elements in a given vector.
@ -123,7 +120,7 @@ void Fisherfaces::train(InputArrayOfArrays src, InputArray _lbls) {
}
}
void Fisherfaces::predict(InputArray _src, int &minClass, double &minDist) const {
void Fisherfaces::predict(InputArray _src, Ptr<PredictCollector> collector, const int state) const {
Mat src = _src.getMat();
// check data alignment just for clearer exception messages
if(_projections.empty()) {
@ -137,24 +134,14 @@ void Fisherfaces::predict(InputArray _src, int &minClass, double &minDist) const
// project into LDA subspace
Mat q = LDA::subspaceProject(_eigenvectors, _mean, src.reshape(1,1));
// find 1-nearest neighbor
minDist = DBL_MAX;
minClass = -1;
for(size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
collector->init((int)_projections.size(), state);
for (size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
double dist = norm(_projections[sampleIdx], q, NORM_L2);
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
int label = _labels.at<int>((int)sampleIdx);
if (!collector->emit(label, dist, state))return;
}
}
int Fisherfaces::predict(InputArray _src) const {
int label;
double dummy;
predict(_src, label, dummy);
return label;
}
Ptr<BasicFaceRecognizer> createFisherFaceRecognizer(int num_components, double threshold)
{
return makePtr<Fisherfaces>(num_components, threshold);

@ -91,11 +91,8 @@ public:
// corresponding labels in labels.
void update(InputArrayOfArrays src, InputArray labels);
// Predicts the label of a query image in src.
int predict(InputArray src) const;
// Predicts the label and confidence for a given sample.
void predict(InputArray _src, int &label, double &dist) const;
// Send all predict results to caller side for custom result handling
void predict(InputArray src, Ptr<PredictCollector> collector, const int state = 0) const;
// See FaceRecognizer::load.
void load(const FileStorage& fs);
@ -386,7 +383,7 @@ void LBPH::train(InputArrayOfArrays _in_src, InputArray _in_labels, bool preserv
}
}
void LBPH::predict(InputArray _src, int &minClass, double &minDist) const {
void LBPH::predict(InputArray _src, Ptr<PredictCollector> collector, const int state) const {
if(_histograms.empty()) {
// throw error if no data (or simply return -1?)
String error_message = "This LBPH model is not computed yet. Did you call the train method?";
@ -402,24 +399,14 @@ void LBPH::predict(InputArray _src, int &minClass, double &minDist) const {
_grid_y, /* grid size y */
true /* normed histograms */);
// find 1-nearest neighbor
minDist = DBL_MAX;
minClass = -1;
for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
collector->init((int)_histograms.size(), state);
for (size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
double dist = compareHist(_histograms[sampleIdx], query, HISTCMP_CHISQR_ALT);
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int) sampleIdx);
}
int label = _labels.at<int>((int)sampleIdx);
if (!collector->emit(label, dist, state))return;
}
}
int LBPH::predict(InputArray _src) const {
int label;
double dummy;
predict(_src, label, dummy);
return label;
}
Ptr<LBPHFaceRecognizer> createLBPHFaceRecognizer(int radius, int neighbors,
int grid_x, int grid_y, double threshold)
{

@ -0,0 +1,86 @@
/*
By downloading, copying, installing or using the software you agree to this license.
If you do not agree to this license, do not download, install,
copy or use the software.
License Agreement
For Open Source Computer Vision Library
(3-clause BSD License)
Copyright (C) 2000-2015, Intel Corporation, all rights reserved.
Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved.
Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
Copyright (C) 2015, OpenCV Foundation, all rights reserved.
Copyright (C) 2015, Itseez Inc., all rights reserved.
Third party copyrights are property of their respective owners.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the copyright holders nor the names of the contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are disclaimed.
In no event shall copyright holders or contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused
and on any theory of liability, whether in contract, strict liability,
or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.
*/
#include "opencv2/face/predict_collector.hpp"
#include "opencv2/core/cvstd.hpp"
namespace cv {
namespace face {
void PredictCollector::init(const int size, const int state) {
//reserve for some-how usage in descendants
_size = size;
_state = state;
}
bool PredictCollector::emit(const int, const double, const int state) {
if (_state == state) {
return false; // if it's own session - terminate it while default PredictCollector does nothing
}
return true;
}
bool MinDistancePredictCollector::emit(const int label, const double dist, const int state) {
if (_state != state) {
return true; // it works only in one (same) session doesn't accept values for other states
}
if (dist < _threshhold && dist < _dist) {
_label = label;
_dist = dist;
}
return true;
}
int MinDistancePredictCollector::getLabel() const {
return _label;
}
double MinDistancePredictCollector::getDist() const {
return _dist;
}
Ptr<MinDistancePredictCollector> MinDistancePredictCollector::create(double threshold) {
return Ptr<MinDistancePredictCollector>(new MinDistancePredictCollector(threshold));
}
}
}
Loading…
Cancel
Save