Open Cv fisherfaces

2019-05-04 04:49发布

问题:

I have this problem,

when i run with vs2010 (debug) (open cv 2.4.0) facerec_demo.cpp gaves me the program this error

OpenCV Error: Image step is wrong (The matrix is not continuous, thus its number of rows can not be changed) in unknown function, file ......\src\opencv\modul es\core>\src\matrix.cpp, line 801

This error derives me to this line in facerec.cpp
(Fisherfaces::train(InputArray src, InputArray _lbls)

Mat data = asRowMatrix(src, CV_64FC1); <-- this gets a exeption, not handled.

and a i use at pgm img database and this is my original *facerec_demo.cpp* file

#include "stdafx.h" 
#include <opencv2/opencv.hpp>


#include <iostream>
#include <fstream>

#include <vector>
#include <string>
#include <sstream>

using namespace cv;
using namespace std;


vector<string> split_at_commas(const string& row)
{
  vector<string> res;
  istringstream buf(row);
  string s;
  while (getline(buf, s, ';'))
    res.push_back(s);
  return res;
}

Mat toGrayscale(InputArray _src) {
    Mat src = _src.getMat();
    // only allow one channel
    if(src.channels() != 1)
        CV_Error(CV_StsBadArg, "Only Matrices with one channel are supported");
    // create and return normalized image
    Mat dst;
    cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
    return dst;
}

void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
    //std::ifstream file(filename.c_str(), ifstream::in);
    std::ifstream file(_T("D:\\Users\\PC ACER\\Documents\\mycsv4.csv"));
    if (!file)
        throw std::exception();
    string line="", path="", classlabel="";
    while (getline(file, line)) {
        //vector<string> values = split_at_commas(line);
        stringstream liness(line);
        getline(liness, path, ';');
        getline(liness, classlabel);
        images.push_back(imread(path, 0));
        labels.push_back(atoi(classlabel.c_str()));
    }
}

int main(int argc, const char *argv[]) {
    // check for command line arguments
    if (argc != 2) {
        cout << "usage: " << argv[0] << " <csv.ext>" << endl;
        exit(1);
    }
    // path to your CSV
    string fn_csv = string(argv[1]);
    // images and corresponding labels
    vector<Mat> images;
    vector<int> labels;
    // read in the data
    try {
        read_csv(fn_csv, images, labels);
    } catch (exception&) {
        cerr << "Error opening file \"" << fn_csv << "\"." << endl;
        exit(1);
    }
    // get width and height
    //int width = images[0].cols;
    int height = images[0].rows;
    // get test instances
    Mat testSample = images[images.size() - 1];
    int testLabel = labels[labels.size() - 1];
    // ... and delete last element
    images.pop_back();
    labels.pop_back();
    // build the Fisherfaces model
    Ptr<FaceRecognizer> model = createFisherFaceRecognizer();
    model->train(images, labels);
    // test model
    int predicted = model->predict(testSample);
    cout << "predicted class = " << predicted << endl;
    cout << "actual class = " << testLabel << endl;
    // get the eigenvectors
    Mat W = model->eigenvectors();
    // show first 10 fisherfaces
    for (int i = 0; i < min(10, W.cols); i++) {
        // get eigenvector #i
        Mat ev = W.col(i).clone();
    // reshape to original size AND normalize between [0...255]
    Mat grayscale = toGrayscale(ev.reshape(1, height));
        // show image (with Jet colormap)
    Mat cgrayscale;
        applyColorMap(grayscale, cgrayscale, COLORMAP_JET);
        imshow(format("%d", i), cgrayscale);
    }
    waitKey(0);
    return 0;
}

回答1:

I see you are using OpenCV 2.4.0. As the developer I admit the confusion is my fault: I didn't thoroughly check the input data passed to the training method back then, so people passing wrongly aligned data got error messages like yours. Most likely the error you see happens, because your training images don't have equal size. This is necessary for the Eigenfaces and Fisherfaces algorithm (not for the Local Binary Patterns Histograms). OpenCV 2.4.0 just tries to reshape the data to a matrix and blows up with the error message you see; OpenCV 2.4.2 instead checks (before training) if the input data is correctly aligned and throws a meaningful exception... with a very clear message.

This post assumes it could also be due to linking the OpenCV libraries:

  • Getting OpenCV Error "Image step is wrong" in Fisherfaces.train() method

If it's not linking the libraries it might be due to the image size. Resizing your training images, can easily be done OpenCV with cv::resize:

  • http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html#resize

But you probably should consider to switch to OpenCV 2.4.2, where all this is added:

  • http://opencv.org/opencv-v2-4-2-released.html

This version also comes with an extensive documentation at:

  • http://docs.opencv.org/trunk/modules/contrib/doc/facerec/index.html

However if you can't change to OpenCV 2.4.2 and you'll need to stay with OpenCV 2.4.0, then you could also use libfacerec:

  • https://github.com/bytefish/libfacerec

This is the project, that got merged into OpenCV. I made sure it works with OpenCV 2.4.0 and it'll leave you with exactely the same interface as the OpenCV 2.4.2 version. So once you feel like updating to OpenCV 2.4.2, you'll only switch the includes.



回答2:

I got the same OpenCv error, I try all help that I find here, and it still gives me an exception (exception happend on .Predict() statement).

Problem was in the size of images. Size of an Images must be less then 100px (<100px) (not sure if exactly less then 100,maybe 100 would still work).

I change my pictures size of 150:150 to 80:80 and its working!

Hope I help someone, because this was annoying error.



回答3:

I answered this question on another post but I want to make sure people searching for help with this error are sure to find the answer.

when you make the model

Ptr<FaceRecognizer> model = createFisherFaceRecognizer();

You need to pass two params

createFisherFaceRecognizer(int num_components=0, double threshold=DBL_MAX);

This page has more information on how createFisherFaceRecognizer works