Ask Your Question


asked 2016-06-15 12:37:24 -0500

RPH gravatar image

Hi, I am trying to reduce the dimensionality of my feature set using PCA and then classification using SVM.

I have created and populated my feature matrix and label matrix :

  Mat labels(875, 1, CV_32F);

  Mat trainingData(875, 23040, CV_32F);

Where each row corresponds to an image and each column is a feature. The features are histogram bins (256) from multiple regions in the image (90 regions). 90x256 = 23040.

I now want to reduce the 23040 features to something less before training, say 512 features. I have this:

/*Reduce dimensionality using PCA*/

Mat projection_result;

PCA pca(trainingData, Mat(), CV_PCA_DATA_AS_ROW,512);

pca.project(trainingData, projection_result);


CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::RBF;

SVM.train_auto(projection_result, labels, Mat(), Mat(), params);"trainedData_test.xml");

My question is, is this correct ? And how would I now use prediction with PCA ?

/*Load SVM*/


/*Populate test matrix*/

  Mat testData(1, 23040, CV_32F);

/*PCA ???*/


int label = SVM.predict(projection_result ???);

Thanks !

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2016-06-16 04:16:28 -0500

berak gravatar image

updated 2016-06-17 01:35:33 -0500

"is this correct ?"

yes, looks fine.

"And how would I now use prediction with PCA ? "

the very same way you treated your train data. you will have to keep the pca object around (at least the transposed eigenvectors and the mean) and project your test vector into pca space:

Mat testData(1, 23040, CV_32F);
Mat test_projected;
pca.project(testData, test_projected); // should result in a 512 x 1 Mat
int label = SVM.predict(test_projected);
// btw, naming your instance "SVM" is a bad idea, since there is already a class with that name

(actually, all PCA::project() does is: result = (input - mean) * eigenvecs.t())


since you probably want to save the trained svm model, you need to save the PCA, too:

// to disk:
FileStorage fs("pca.xml", FileStorage::WRITE);
fs.release(); // flush

// and back:
PCA pca;
FileStorage fs("pca.xml", FileStorage::READ);;
edit flag offensive delete link more


Thanks for the answer !

How would I go about using it if I wanted to save the SVM for later testing ? I assume one cannot save the whole PCA object (like with the SVM), so is it easy to save and re-use the mean and eigenvectors ?

Thanks !

RPH gravatar imageRPH ( 2016-06-16 16:26:23 -0500 )edit

^^ ah, right, i knew there was something amiss !

(please see edit)

berak gravatar imageberak ( 2016-06-17 00:28:09 -0500 )edit

Thanks for all the help guys ! I'll test it out in the coming days and post back if it gives any issues...Thanks

RPH gravatar imageRPH ( 2016-06-18 13:07:22 -0500 )edit

yes,please report back, curious, how you're doing ;)

berak gravatar imageberak ( 2016-06-18 13:22:38 -0500 )edit

Hi, I have tried to implement the code however I get the error:

"cv::PCA has no member write"

What is the problem do you think ? Thanks

RPH gravatar imageRPH ( 2016-06-28 13:01:50 -0500 )edit

@RPH what is your OpenCV version?

sturkmen gravatar imagesturkmen ( 2016-06-28 13:05:29 -0500 )edit

Hi, it is version 2.4.12

RPH gravatar imageRPH ( 2016-06-28 13:09:26 -0500 )edit

the code in the answer should work! please share the code you tried

sturkmen gravatar imagesturkmen ( 2016-06-28 13:20:51 -0500 )edit

@sturkmen I am using 32bit version if that makes a difference. The problem is with the .write line.

RPH gravatar imageRPH ( 2016-06-28 13:23:59 -0500 )edit

just tried like:

PCA pca;
FileStorage fs("pca.xml", FileStorage::WRITE);
fs.release(); // flush
sturkmen gravatar imagesturkmen ( 2016-06-28 13:33:16 -0500 )edit

@sturkmen@berak Yes I get an error with that exact code. I also get an error with Could I be missing some header file ? I don't think that version 2.4.12 includes the write or read member functions. How else can I re-use the PCA object for later testing ? Thanks

RPH gravatar imageRPH ( 2016-06-28 13:58:57 -0500 )edit

you were right. write and read not available on 2.4

sturkmen gravatar imagesturkmen ( 2016-06-28 16:59:22 -0500 )edit

Thought as much. Would the method outlined here work fine: link text ?. Thanks

RPH gravatar imageRPH ( 2016-06-28 17:04:14 -0500 )edit

/* When Training */
Mat trainingData = Mat(213, 21504, CV_32F, cv::Scalar(0)); //assume populated
Mat projection_result;
PCA pca(trainingData, Mat(), CV_PCA_DATA_AS_ROW, 512);
pca.project(trainingData, projection_result);
FileStorage fs(pca_filename, FileStorage::WRITE);
fs << "mean" << pca.mean;
fs << "e_vectors" << pca.eigenvectors;
fs << "e_values" << pca.eigenvalues;
CvSVM svm;
svm.train(projection_result, labels, Mat(), Mat(), params);

RPH gravatar imageRPH ( 2016-06-28 17:28:20 -0500 )edit

/* When Testing */
Mat testData = Mat(1, 21504, CV_32FC1, cv::Scalar(0)); //Assume populated
PCA pca;
FileStorage fs(pca_filename, FileStorage::READ);
fs["mean"] >> pca.mean;
fs["e_vectors"] >> pca.eigenvectors;
fs["e_values"] >> pca.eigenvalues;
Mat test_projected;
pca.project(testData, test_projected); // should result in a 512 x 1 Mat
int label = svm.predict(test_projected);

RPH gravatar imageRPH ( 2016-06-28 17:35:33 -0500 )edit

@sturkmen@berak Does the code above look alright ? Thanks

RPH gravatar imageRPH ( 2016-06-29 11:07:31 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower


Asked: 2016-06-15 12:37:24 -0500

Seen: 915 times

Last updated: Jun 17 '16