JTIM
JTIM

Reputation: 2771

PCA output eigenvectors and eigenvalues

I have created a PCA solution in Matlab, which works. I am now in the middle of converting it to c++, where I use OpenCV's function cv::PCA. Where I found in a link that you could extract the mean, eigenvalues and eigenvectors using:

// Perform a PCA:
cv::PCA pca(data, cv::Mat(), CV_PCA_DATA_AS_ROW, num_components);

// And copy the PCA results:
cv::Mat mean = pca.mean.clone();
cv::Mat eigenvalues = pca.eigenvalues.clone();
cv::Mat eigenvectors = pca.eigenvectors.clone();

Which compiles and runs. But when I want to use the values and look into the size and allocation, I get a size of the input data, which seems odd, i.e.

cv::Size temp= eigenvectors.size();
//temp has the same size as data.size();

In my mind the eigenvectors should be defined by the num_components and in my 3D space, should only be 3x3 size, i.e. 9 elements. Can anybody explain the reasoning behind the data sizes of pca.x.clone()?

Also what is the correct way of doing matrix operation in opencv and c++, based on the documentation it seems like you can use operators with cv::Mat. Using the above extraction of the pca information can you do:

cv::Mat Z = data - mean; //according to documentation http://stackoverflow.com/questions/10936099/matrix-multiplication-in-opencv
cv::Mat res = Z*eigenvectors;

It has crashed in my tests on runtime, probably because of the issue with "misinterpretation"/"interpretation" of the size.

Question The basic question is how to use the pca opencv function correctly?

Edit Another way that I have tested is to use the following code:

cv::PCA pca_analysis(mat, cv::Mat(), CV_PCA_DATA_AS_ROW, num_components);
cv::Point3d cntr = cv::Point3d(static_cast<double>(pca_analysis.mean.at<double>(0, 0)),
        static_cast<int>(pca_analysis.mean.at<double>(0, 1)), static_cast<double>(pca_analysis.mean.at<double>(0, 2)));
//Store the eigenvalues and eigenvectors
vector<cv::Point3d> eigen_vecs(num_components);
vector<double> eigen_val(num_components);
for (int i = 0; i < num_components; ++i)
{
    eigen_vecs[i] = cv::Point3d(pca_analysis.eigenvectors.at<double>(0, i*num_components),
            pca_analysis.eigenvectors.at<double>(0, i * num_components + 1), pca_analysis.eigenvectors.at<double>(0, i*num_components + 2));
    eigen_val[i] = pca_analysis.eigenvalues.at<double>(0,i);
}

When I compare the results from the above code with my Matlab implementation then the cntr seems to be plausible (under percentage difference). But the eigenvectors and eigenvalues are just zero, when I look at them in the debugger. This seems to go back to my original question of how to extract and understand pca's output.

Can anybody clarify what I am missing?

Upvotes: 1

Views: 1907

Answers (1)

Lamar Latrell
Lamar Latrell

Reputation: 1669

I came across your question when searching for how to access the eigenvalues and eigenvectors.

I personally needed to see the full information and would expect that myself. So, it's possible that the developers expected my use-case to more likely than yours.

In any case, as they are sorted you can take the first 'num_components' eigenvalues/eigenvectors as being the information you are after.

Also, from your perspective - i.e. if it worked as you expect it to - think about the converse: If you wanted to see the full info, how would you? The developers would have to implement a new parameter...

Upvotes: 1

Related Questions