在OpenCV 2.2中使用C ++语法的PCA + SVM [英] PCA + SVM using C++ Syntax in OpenCV 2.2

查看:344
本文介绍了在OpenCV 2.2中使用C ++语法的PCA + SVM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题使用最新的C ++语法与Mat和PCA类获得PCA和Eigenfaces工作。较旧的C语法采用IplImage *数组作为参数来执行其处理,并且当前API仅接受由列或行格式化的Mat。我采取了行方法使用reshape函数来适应我的图像的矩阵适合单行。我最终想要获取这些数据,然后使用SVM算法来执行检测,但是当我这样做时,我的所有数据只是一个0的流。有人可以帮助我吗?我做错了什么?非常感谢!

I'm having problems getting PCA and Eigenfaces working using the latest C++ syntax with the Mat and PCA classes. The older C syntax took an array of IplImage* as a parameter to perform its processing and the current API only takes a Mat that is formatted by Column or Row. I took the Row approach using the reshape function to fit my image's matrix to fit in a single row. I eventually want to take this data and then use the SVM algorithm to perform detection, but when I do that all my data is just a stream of 0s. Can someone please help me out? What am I doing wrong? Thanks!

我看到这个问题,它有点相关,但我不知道解决方案是什么。

I saw this question and it's somewhat related, but I'm not sure what the solution is.

这基本上是我有:

vector<Mat> images; //This variable will be loaded with a set of images to perform PCA on.
Mat values(images.size(), 1, CV_32SC1); //Values are the corresponding values to each of my images.

int nEigens = images.size() - 1; //Number of Eigen Vectors.

//Load the images into a Matrix
Mat desc_mat(images.size(), images[0].rows * images[0].cols, CV_32FC1);
for (int i=0; i<images.size(); i++) {
  desc_mat.row(i) = images[i].reshape(1, 1);
}

Mat average;
PCA pca(desc_mat, average, CV_PCA_DATA_AS_ROW, nEigens);

Mat data(desc_mat.rows, nEigens, CV_32FC1); //This Mat will contain all the Eigenfaces that will be used later with SVM for detection

//Project the images onto the PCA subspace
for(int i=0; i<images.size(); i++) {
  Mat projectedMat(1, nEigens, CV_32FC1);
  pca.project(desc_mat.row(i), projectedMat);

  data.row(i) = projectedMat.row(0);
}

CvMat d1 = (CvMat)data;
CvMat d2 = (CvMat)values;

CvSVM svm;
svm.train(&d1, &d2);
svm.save("svmdata.xml");


推荐答案

etarion说的是正确的。

What etarion said is correct.

要复制列或行,您必须总是写:

To copy a column or row you always have to write:

Mat B = mat.col(i);
A.copyTo(B);

以下程序显示了如何在OpenCV中执行PCA。它将显示平均图像和前三个特征面。我在其中使用的图片可从 http://www.cl.cam.ac .uk / research / dtg / attarchive / facedatabase.html

The following program shows how to perform a PCA in OpenCV. It'll show the mean image and the first three Eigenfaces. The images I used in there are available from http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html:

#include "cv.h"
#include "highgui.h"

using namespace std;
using namespace cv;

Mat normalize(const Mat& src) {
    Mat srcnorm;
    normalize(src, srcnorm, 0, 255, NORM_MINMAX, CV_8UC1);
    return srcnorm;
}

int main(int argc, char *argv[]) {
    vector<Mat> db;

    // load greyscale images (these are from http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html)
    db.push_back(imread("s1/1.pgm",0));
    db.push_back(imread("s1/2.pgm",0));
    db.push_back(imread("s1/3.pgm",0));

    db.push_back(imread("s2/1.pgm",0));
    db.push_back(imread("s2/2.pgm",0));
    db.push_back(imread("s2/3.pgm",0));

    db.push_back(imread("s3/1.pgm",0));
    db.push_back(imread("s3/2.pgm",0));
    db.push_back(imread("s3/3.pgm",0));

    db.push_back(imread("s4/1.pgm",0));
    db.push_back(imread("s4/2.pgm",0));
    db.push_back(imread("s4/3.pgm",0));

    int total = db[0].rows * db[0].cols;

    // build matrix (column)
    Mat mat(total, db.size(), CV_32FC1);
    for(int i = 0; i < db.size(); i++) {
        Mat X = mat.col(i);
        db[i].reshape(1, total).col(0).convertTo(X, CV_32FC1, 1/255.);
    }

    // Change to the number of principal components you want:
    int numPrincipalComponents = 12;

    // Do the PCA:
    PCA pca(mat, Mat(), CV_PCA_DATA_AS_COL, numPrincipalComponents);

    // Create the Windows:
    namedWindow("avg", 1);
    namedWindow("pc1", 1);
    namedWindow("pc2", 1);
    namedWindow("pc3", 1);

    // Mean face:
    imshow("avg", pca.mean.reshape(1, db[0].rows));

    // First three eigenfaces:
    imshow("pc1", normalize(pca.eigenvectors.row(0)).reshape(1, db[0].rows));
    imshow("pc2", normalize(pca.eigenvectors.row(1)).reshape(1, db[0].rows));
    imshow("pc3", normalize(pca.eigenvectors.row(2)).reshape(1, db[0].rows));

    // Show the windows:
    waitKey(0);
}

,如果你想按行构建矩阵上面)使用这个代替:

and if you want to build the matrix by row (like in your original question above) use this instead:

// build matrix
Mat mat(db.size(), total, CV_32FC1);
for(int i = 0; i < db.size(); i++) {
    Mat X = mat.row(i);
    db[i].reshape(1, 1).row(0).convertTo(X, CV_32FC1, 1/255.);
}

并将PCA中的标志设置为

and set the flag in the PCA to:

CV_PCA_DATA_AS_ROW

。我用OpenCV C ++ API编写了一个关于机器学习的文档,其中包含了大多数分类器的示例,包括支持向量机。也许您可以从中获得一些灵感: http://www.bytefish.de/pdf/machinelearning.pdf

Regarding machine learning. I wrote a document on machine learning with the OpenCV C++ API that has examples for most of the classifiers, including Support Vector Machines. Maybe you can get some inspiration there: http://www.bytefish.de/pdf/machinelearning.pdf.

这篇关于在OpenCV 2.2中使用C ++语法的PCA + SVM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆