2

I'm using OpenCV v2.4.1

And this is the code I'm using

#include "opencv2/opencv.hpp"
#include <iostream>
#include <fstream>
#include <sstream>

using namespace cv;
using namespace std;

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);
    if (!file)
        throw std::exception();
    string line, path, classlabel;
    while (getline(file, line)) {
        stringstream liness(line);
        getline(liness, path, separator);
        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("at.txt");
    // 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;
}

contents of at.txt input file :

./at/s10/2.pgm;9 ./at/s10/7.pgm;9 ./at/s10/6.pgm;9 ./at/s10/9.pgm;9 ./at/s10/5.pgm;9

Now the problem is , as long as I'm using this pgm files , It works fine . But when I specify any jpg file instead of pgm I get following 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

So far Im able to trace that error is coming from Fisherfaces.train() --> cv::Mat.reShape()

But I'm clueless , what could be the reason . Please help.

  • This solution worked for me . http://stackoverflow.com/questions/2623163/opencv-2-0-c-api-using-imshow-returns-unhandled-exception-and-bad-flag Earlier I had both release and Debug lib added in project properties. Now I have removed all the released libs and it's working flawlessly :-) – Sandeep Mishra Jun 10 '12 at 06:26
  • Since you found the solution, you can post that as the answer and accept it :) – F21 Jun 11 '12 at 03:27

2 Answers2

2

This solution worked for me!

Earlier I had both release and Debug lib added in project properties. Now I have removed all the released libs and it's working flawlessly.

ArtemStorozhuk
  • 8,715
  • 4
  • 35
  • 53
0

When you build the fisherface 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

Sage
  • 13
  • 5