FaceRecognizer class is now derived from Algorithm, therefore it's possible to set and retrieve the parameters using conventional Algorithm::set and Algorithm::get methods
This commit is contained in:
parent
fd68cc768a
commit
41c932f306
@ -918,7 +918,7 @@ namespace cv
|
|||||||
void lda(InputArray src, InputArray labels);
|
void lda(InputArray src, InputArray labels);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CV_EXPORTS FaceRecognizer
|
class CV_EXPORTS FaceRecognizer : public Algorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! virtual destructor
|
//! virtual destructor
|
||||||
@ -970,6 +970,8 @@ namespace cv
|
|||||||
};
|
};
|
||||||
|
|
||||||
CV_EXPORTS void applyColorMap(InputArray src, OutputArray dst, int colormap);
|
CV_EXPORTS void applyColorMap(InputArray src, OutputArray dst, int colormap);
|
||||||
|
|
||||||
|
CV_EXPORTS bool initModule_contrib();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class Eigenfaces : public FaceRecognizer
|
|||||||
private:
|
private:
|
||||||
int _num_components;
|
int _num_components;
|
||||||
vector<Mat> _projections;
|
vector<Mat> _projections;
|
||||||
vector<int> _labels;
|
Mat _labels;
|
||||||
Mat _eigenvectors;
|
Mat _eigenvectors;
|
||||||
Mat _eigenvalues;
|
Mat _eigenvalues;
|
||||||
Mat _mean;
|
Mat _mean;
|
||||||
@ -125,17 +125,7 @@ public:
|
|||||||
// See FaceRecognizer::save.
|
// See FaceRecognizer::save.
|
||||||
void save(FileStorage& fs) const;
|
void save(FileStorage& fs) const;
|
||||||
|
|
||||||
// Returns the eigenvectors of this PCA.
|
AlgorithmInfo* info() const;
|
||||||
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; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Belhumeur, P. N., Hespanha, J., and Kriegman, D. "Eigenfaces vs. Fisher-
|
// Belhumeur, P. N., Hespanha, J., and Kriegman, D. "Eigenfaces vs. Fisher-
|
||||||
@ -150,7 +140,7 @@ private:
|
|||||||
Mat _eigenvalues;
|
Mat _eigenvalues;
|
||||||
Mat _mean;
|
Mat _mean;
|
||||||
vector<Mat> _projections;
|
vector<Mat> _projections;
|
||||||
vector<int> _labels;
|
Mat _labels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using FaceRecognizer::save;
|
using FaceRecognizer::save;
|
||||||
@ -185,17 +175,7 @@ public:
|
|||||||
// See FaceRecognizer::save.
|
// See FaceRecognizer::save.
|
||||||
virtual void save(FileStorage& fs) const;
|
virtual void save(FileStorage& fs) const;
|
||||||
|
|
||||||
// Returns the eigenvectors of this Fisherfaces model.
|
AlgorithmInfo* info() const;
|
||||||
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; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Face Recognition based on Local Binary Patterns.
|
// Face Recognition based on Local Binary Patterns.
|
||||||
@ -217,7 +197,7 @@ private:
|
|||||||
int _neighbors;
|
int _neighbors;
|
||||||
|
|
||||||
vector<Mat> _histograms;
|
vector<Mat> _histograms;
|
||||||
vector<int> _labels;
|
Mat _labels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using FaceRecognizer::save;
|
using FaceRecognizer::save;
|
||||||
@ -271,6 +251,7 @@ public:
|
|||||||
int grid_x() const { return _grid_x; }
|
int grid_x() const { return _grid_x; }
|
||||||
int grid_y() const { return _grid_y; }
|
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)
|
if(_lbls.getMat().type() != CV_32SC1)
|
||||||
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
||||||
// get labels
|
// 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
|
// observations in row
|
||||||
Mat data = asRowMatrix(src, CV_64FC1);
|
Mat data = asRowMatrix(src, CV_64FC1);
|
||||||
// number of samples
|
// number of samples
|
||||||
@ -310,7 +292,7 @@ void Eigenfaces::train(InputArray src, InputArray _lbls) {
|
|||||||
// dimensionality of data
|
// dimensionality of data
|
||||||
//int d = data.cols;
|
//int d = data.cols;
|
||||||
// assert there are as much samples as labels
|
// 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!");
|
CV_Error(CV_StsBadArg, "The number of samples must equal the number of labels!");
|
||||||
// clip number of components to be valid
|
// clip number of components to be valid
|
||||||
if((_num_components <= 0) || (_num_components > n))
|
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
|
_mean = pca.mean.reshape(1,1); // store the mean vector
|
||||||
_eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row
|
_eigenvalues = pca.eigenvalues.clone(); // eigenvalues by row
|
||||||
transpose(pca.eigenvectors, _eigenvectors); // eigenvectors by column
|
transpose(pca.eigenvectors, _eigenvectors); // eigenvectors by column
|
||||||
_labels = labels; // store labels for prediction
|
labels.copyTo(_labels); // store labels for prediction
|
||||||
// save projections
|
// save projections
|
||||||
for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
|
for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
|
||||||
Mat p = subspaceProject(_eigenvectors, _mean, data.row(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);
|
double dist = norm(_projections[sampleIdx], q, NORM_L2);
|
||||||
if(dist < minDist) {
|
if(dist < minDist) {
|
||||||
minDist = dist;
|
minDist = dist;
|
||||||
minClass = _labels[sampleIdx];
|
minClass = _labels.at<int>(sampleIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return minClass;
|
return minClass;
|
||||||
@ -354,7 +336,7 @@ void Eigenfaces::load(const FileStorage& fs) {
|
|||||||
fs["eigenvectors"] >> _eigenvectors;
|
fs["eigenvectors"] >> _eigenvectors;
|
||||||
// read sequences
|
// read sequences
|
||||||
readFileNodeList(fs["projections"], _projections);
|
readFileNodeList(fs["projections"], _projections);
|
||||||
readFileNodeList(fs["labels"], _labels);
|
fs["labels"] >> _labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Eigenfaces::save(FileStorage& fs) const {
|
void Eigenfaces::save(FileStorage& fs) const {
|
||||||
@ -365,7 +347,7 @@ void Eigenfaces::save(FileStorage& fs) const {
|
|||||||
fs << "eigenvectors" << _eigenvectors;
|
fs << "eigenvectors" << _eigenvectors;
|
||||||
// write sequences
|
// write sequences
|
||||||
writeFileNodeList(fs, "projections", _projections);
|
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)
|
if(_lbls.getMat().type() != CV_32SC1)
|
||||||
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
||||||
// get data
|
// get data
|
||||||
vector<int> labels = _lbls.getMat();
|
Mat labels = _lbls.getMat();
|
||||||
Mat data = asRowMatrix(src, CV_64FC1);
|
Mat data = asRowMatrix(src, CV_64FC1);
|
||||||
|
|
||||||
|
CV_Assert( labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1));
|
||||||
|
|
||||||
// dimensionality
|
// dimensionality
|
||||||
int N = data.rows; // number of samples
|
int N = data.rows; // number of samples
|
||||||
//int D = data.cols; // dimension of samples
|
//int D = data.cols; // dimension of samples
|
||||||
// assert correct data alignment
|
// 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).");
|
CV_Error(CV_StsUnsupportedFormat, "Labels must be given as integer (CV_32SC1).");
|
||||||
// compute the Fisherfaces
|
// 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
|
// clip number of components to be a valid number
|
||||||
if((_num_components <= 0) || (_num_components > (C-1)))
|
if((_num_components <= 0) || (_num_components > (C-1)))
|
||||||
_num_components = (C-1);
|
_num_components = (C-1);
|
||||||
@ -395,7 +383,7 @@ void Fisherfaces::train(InputArray src, InputArray _lbls) {
|
|||||||
// store the total mean vector
|
// store the total mean vector
|
||||||
_mean = pca.mean.reshape(1,1);
|
_mean = pca.mean.reshape(1,1);
|
||||||
// store labels
|
// store labels
|
||||||
_labels = labels;
|
labels.copyTo(_labels);
|
||||||
// store the eigenvalues of the discriminants
|
// store the eigenvalues of the discriminants
|
||||||
lda.eigenvalues().convertTo(_eigenvalues, CV_64FC1);
|
lda.eigenvalues().convertTo(_eigenvalues, CV_64FC1);
|
||||||
// Now calculate the projection matrix as pca.eigenvectors * lda.eigenvectors.
|
// 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);
|
double dist = norm(_projections[sampleIdx], q, NORM_L2);
|
||||||
if(dist < minDist) {
|
if(dist < minDist) {
|
||||||
minDist = dist;
|
minDist = dist;
|
||||||
minClass = _labels[sampleIdx];
|
minClass = _labels.at<int>(sampleIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return minClass;
|
return minClass;
|
||||||
@ -435,7 +423,7 @@ void Fisherfaces::load(const FileStorage& fs) {
|
|||||||
fs["eigenvectors"] >> _eigenvectors;
|
fs["eigenvectors"] >> _eigenvectors;
|
||||||
// read sequences
|
// read sequences
|
||||||
readFileNodeList(fs["projections"], _projections);
|
readFileNodeList(fs["projections"], _projections);
|
||||||
readFileNodeList(fs["labels"], _labels);
|
fs["labels"] >> _labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See FaceRecognizer::save.
|
// See FaceRecognizer::save.
|
||||||
@ -447,7 +435,7 @@ void Fisherfaces::save(FileStorage& fs) const {
|
|||||||
fs << "eigenvectors" << _eigenvectors;
|
fs << "eigenvectors" << _eigenvectors;
|
||||||
// write sequences
|
// write sequences
|
||||||
writeFileNodeList(fs, "projections", _projections);
|
writeFileNodeList(fs, "projections", _projections);
|
||||||
writeFileNodeList(fs, "labels", _labels);
|
fs << "labels" << _labels;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// LBPH
|
// LBPH
|
||||||
@ -630,7 +618,7 @@ void LBPH::load(const FileStorage& fs) {
|
|||||||
fs["grid_y"] >> _grid_y;
|
fs["grid_y"] >> _grid_y;
|
||||||
//read matrices
|
//read matrices
|
||||||
readFileNodeList(fs["histograms"], _histograms);
|
readFileNodeList(fs["histograms"], _histograms);
|
||||||
readFileNodeList(fs["labels"], _labels);
|
fs["labels"] >> _labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See FaceRecognizer::save.
|
// See FaceRecognizer::save.
|
||||||
@ -641,7 +629,7 @@ void LBPH::save(FileStorage& fs) const {
|
|||||||
fs << "grid_y" << _grid_y;
|
fs << "grid_y" << _grid_y;
|
||||||
// write matrices
|
// write matrices
|
||||||
writeFileNodeList(fs, "histograms", _histograms);
|
writeFileNodeList(fs, "histograms", _histograms);
|
||||||
writeFileNodeList(fs, "labels", _labels);
|
fs << "labels" << _labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LBPH::train(InputArray _src, InputArray _lbls) {
|
void LBPH::train(InputArray _src, InputArray _lbls) {
|
||||||
@ -651,11 +639,12 @@ void LBPH::train(InputArray _src, InputArray _lbls) {
|
|||||||
vector<Mat> src;
|
vector<Mat> src;
|
||||||
_src.getMatVector(src);
|
_src.getMatVector(src);
|
||||||
// turn the label matrix into a vector
|
// turn the label matrix into a vector
|
||||||
vector<int> labels = _lbls.getMat();
|
Mat labels = _lbls.getMat();
|
||||||
if(labels.size() != src.size())
|
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.");
|
CV_Error(CV_StsUnsupportedFormat, "The number of labels must equal the number of samples.");
|
||||||
// store given labels
|
// store given labels
|
||||||
_labels = labels;
|
labels.copyTo(_labels);
|
||||||
// store the spatial histograms of the original data
|
// store the spatial histograms of the original data
|
||||||
for(size_t sampleIdx = 0; sampleIdx < src.size(); sampleIdx++) {
|
for(size_t sampleIdx = 0; sampleIdx < src.size(); sampleIdx++) {
|
||||||
// calculate lbp image
|
// calculate lbp image
|
||||||
@ -690,7 +679,7 @@ int LBPH::predict(InputArray _src) const {
|
|||||||
double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
|
double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
|
||||||
if(dist < minDist) {
|
if(dist < minDist) {
|
||||||
minDist = dist;
|
minDist = dist;
|
||||||
minClass = _labels[sampleIdx];
|
minClass = _labels.at<int>(sampleIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return minClass;
|
return minClass;
|
||||||
@ -713,4 +702,34 @@ Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius, int neighbors,
|
|||||||
return new LBPH(radius, neighbors, grid_x, grid_y);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user