[英]PCA + SVM using C++ Syntax in OpenCV 2.2
I'm having problems getting PCA and Eigenfaces working using the latest C++ syntax with the Mat and PCA classes. 我在使用Mat和PCA类使用最新的C ++语法时遇到了PCA和Eigenfaces的问题。 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.
较旧的C语法将IplImage *数组作为参数来执行其处理,而当前API仅采用由Column或Row格式化的Mat。 I took the Row approach using the reshape function to fit my image's matrix to fit in a single row.
我采用了Row方法,使用reshape函数来拟合我的图像矩阵以适合单行。 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.
我最终想要获取这些数据然后使用SVM算法来执行检测,但是当我这样做时,我的所有数据都只是一个0流。 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. 我看到了这个问题并且它有些相关,但我不确定解决方案是什么。
This is basically what I have: 这基本上就是我所拥有的:
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");
What etarion said is correct. etarion说的是正确的。
To copy a column or row you always have to write: 要复制列或行,您必须始终写:
Mat B = mat.col(i);
A.copyTo(B);
The following program shows how to perform a PCA in OpenCV. 以下程序显示了如何在OpenCV中执行PCA。 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 :
我在那里使用的图像可以从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.);
}
and set the flag in the PCA to: 并将PCA中的标志设置为:
CV_PCA_DATA_AS_ROW
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.
我使用OpenCV C ++ API编写了一个关于机器学习的文档,其中包含大多数分类器的示例,包括支持向量机。 Maybe you can get some inspiration there: http://www.bytefish.de/pdf/machinelearning.pdf .
也许你可以在那里得到一些灵感: http : //www.bytefish.de/pdf/machinelearning.pdf 。
data.row(i) = projectedMat.row(0);
This will not work. 这不行。
operator=
is a shallow copy, meaning no data is actually copied. operator=
是浅拷贝,意味着实际上没有复制数据。 Use 采用
cv::Mat sample = data.row(i); // also a shallow copy, points to old data!
projectedMat.row(0).copyTo(sample);
The same also for: 同样也适用于:
desc_mat.row(i) = images[i].reshape(1, 1);
I would suggest looking at the newly checked in tests in svn head 我建议在svn head中查看新检查的测试
modules/core/test/test_mat.cpp 模块/核心/测试/ test_mat.cpp
online here : https://code.ros.org/svn/opencv/trunk/opencv/modules/core/test/test_mat.cpp 在线: https : //code.ros.org/svn/opencv/trunk/opencv/modules/core/test/test_mat.cpp
has examples for PCA in the old c and new c++ 在旧c和新c ++中有PCA的例子
Hope that helps! 希望有所帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.