string error_message = format("The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", n, labels.total());
CV_Error(CV_StsBadArg, error_message);
}
+ // clear existing model data
+ _labels.release();
+ _projections.clear();
// clip number of components to be valid
if((_num_components <= 0) || (_num_components > n))
_num_components = n;
_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.copyTo(_labels); // store labels for prediction
+ // store labels for prediction
+ labels.copyTo(_labels);
// save projections
for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
Mat p = subspaceProject(_eigenvectors, _mean, data.row(sampleIdx));
string error_message = format("Expected the labels in a matrix with one row or column! Given dimensions are rows=%s, cols=%d.", labels.rows, labels.cols);
CV_Error(CV_StsBadArg, error_message);
}
- // Get the number of unique classes (provide a cv::Mat overloaded version?)
+ // clear existing model data
+ _labels.release();
+ _projections.clear();
+ // get the number of unique classes (provide a cv::Mat overloaded version?)
vector<int> ll;
labels.copyTo(ll);
int C = (int) remove_dups(ll).size();
lda.eigenvalues().convertTo(_eigenvalues, CV_64FC1);
// Now calculate the projection matrix as pca.eigenvectors * lda.eigenvectors.
// Note: OpenCV stores the eigenvectors by row, so we need to transpose it!
- gemm(pca.eigenvectors, lda.eigenvectors(), 1.0, Mat(), 0.0, _eigenvectors, CV_GEMM_A_T);
+ gemm(pca.eigenvectors, lda.eigenvectors(), 1.0, Mat(), 0.0, _eigenvectors, GEMM_1_T);
// store the projections of the original data
for(int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++) {
Mat p = subspaceProject(_eigenvectors, _mean, data.row(sampleIdx));
writeFileNodeList(fs, "projections", _projections);
fs << "labels" << _labels;
}
+
//------------------------------------------------------------------------------
// LBPH
//------------------------------------------------------------------------------
if(_src.kind() != _InputArray::STD_VECTOR_MAT && _src.kind() != _InputArray::STD_VECTOR_VECTOR) {
string error_message = "The images are expected as InputArray::STD_VECTOR_MAT (a std::vector<Mat>) or _InputArray::STD_VECTOR_VECTOR (a std::vector< vector<...> >).";
CV_Error(CV_StsBadArg, error_message);
- } else if(_src.total() == 0) {
+ }
+ if(_src.total() == 0) {
string error_message = format("Empty training data was given. You'll need more than one sample to learn a model.");
CV_Error(CV_StsUnsupportedFormat, error_message);
} else if(_lbls.getMat().type() != CV_32SC1) {
// get the vector of matrices
vector<Mat> src;
_src.getMatVector(src);
- for (vector<Mat>::const_iterator image = src.begin(); image != src.end(); ++image) {
- if (image->channels() != 1) {
- string error_message = format("The images must be single channel (grayscale), but an image has %d channels.", image->channels());
- CV_Error(CV_StsUnsupportedFormat, error_message);
- }
- }
- // turn the label matrix into a vector
+ // get the label matrix
Mat labels = _lbls.getMat();
- CV_Assert( labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1));
+ // check if data is well- aligned
if(labels.total() != src.size()) {
- CV_Error(CV_StsUnsupportedFormat, "The number of labels must equal the number of samples.");
+ string error_message = format("The number of samples (src) must equal the number of labels (labels). Was len(samples)=%d, len(labels)=%d.", src.size(), _labels.total());
+ CV_Error(CV_StsBadArg, error_message);
+ }
+ // append labels to _labels matrix
+ for(int labelIdx = 0; labelIdx < labels.total(); labelIdx++) {
+ _labels.push_back(labels.at<int>(labelIdx));
}
- // store given labels
- labels.copyTo(_labels);
// store the spatial histograms of the original data
- for(size_t sampleIdx = 0; sampleIdx < src.size(); sampleIdx++) {
+ for(int sampleIdx = 0; sampleIdx < src.size(); sampleIdx++) {
// calculate lbp image
Mat lbp_image = elbp(src[sampleIdx], _radius, _neighbors);
// get spatial histogram from this lbp image
}
void LBPH::predict(InputArray _src, int &minClass, double &minDist) const {
- Mat src = _src.getMat();
- if (src.channels() != 1) {
- string error_message = format("The image must be single channel (grayscale), but the image has %d channels.", src.channels());
- CV_Error(CV_StsUnsupportedFormat, error_message);
+ 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?";
+ CV_Error(CV_StsBadArg, error_message);
}
+ Mat src = _src.getMat();
// get the spatial histogram from input image
Mat lbp_image = elbp(src, _radius, _neighbors);
Mat query = spatial_histogram(
// find 1-nearest neighbor
minDist = DBL_MAX;
minClass = -1;
- for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
+ for(int sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
- minClass = _labels.at<int>((int)sampleIdx);
+ minClass = _labels.at<int>(sampleIdx);
}
}
}