Use all cv::Mat in std::vector and change their value efficiently

asked 2017-03-21 07:32:01 -0600

lovaj gravatar image

I have a vector of matrices with the same number of columns, i.e. std::vector<cv::Mat> v and I want to apply a cv::PCA (without dimensionality reduction) using all of them. Finally, I want that the result is applied to original matrices too.

Code speaking, this is the only solution that I came so far:

std::vector<cv::Mat> v;
//fill v
cv::Mat bigMat;
for(size_t i=0; i<v.size(); i++)
  bigMat.push_back(v[i]);
cv::PCA pca(bigMat, cv::Mat(), CV_PCA_DATA_AS_ROW);
for(size_t i=0; i<v.size(); i++)
  bigMat = pca.project(bigMat);

But this doesn't effect v[i]. How can I do this efficiently? Notice that I have to use the projected version of bigMat later. This is the only solution that came to my mind:

cv::PCA pca(bigMat, cv::Mat(), CV_PCA_DATA_AS_ROW);
bigMat.release();
for (size_t i=0; i<v.size(); i++){
  v[i] = pca.project(v[i]);
  bigMat.push_back(v[i]);
}

But this is kinda ugly and I don't know how efficient could be. Is there any better solution (where efficiency is the top priority)?

If you wander, v[i] is the set of descriptors of the i-th image. If you ask yourself why there is no dimensionality reduction in my PCA, give a look at this paper.

edit retag flag offensive close merge delete

Comments

btw, your paper does mention dimensionality reduction (from 128 to 64)

then, this is for sure wrong:

for(size_t i=0; i<v.size(); i++)
     bigMat = pca.project(bigMat);

as you're recursively projecting the same Mat, while a plain:

 bigMat = pca.project(bigMat);

would do, imho.

then, please clarify: why dou you need both the mat vector and bigMat ? this seems excessive.

berak gravatar imageberak ( 2017-03-21 08:09:10 -0600 )edit
1

@berak thanks for your answer. The paper use multiple types of PCA, and some of them are about rotating the descriptors (without dimensionality reduction) to improve the encoding precision combined with power-law. I need bigMat because later I'm going to use it for k-means on the rotated descriptors using the vlfeat implementation, and so I pass as a pointer bigMat.data().

lovaj gravatar imagelovaj ( 2017-03-21 09:12:09 -0600 )edit

ok, still, why do you need to have the projections in a vector<Mat> ?

you could project bigMat once , and access each row vector like:

float *row = bigMat.row(i).ptr<float>();
berak gravatar imageberak ( 2017-03-21 09:31:42 -0600 )edit

@berak Thanks, following your tip I found an efficient workaround. Could you please give a look at this question?

lovaj gravatar imagelovaj ( 2017-03-21 13:53:52 -0600 )edit