diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 5988363d3c..05a0c55524 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -2855,9 +2855,9 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp if( _mean.data ) { - CV_Assert( _mean.size() == mean_sz ); + CV_Assert( _mean.size() == mean_sz ); _mean.convertTo(mean, ctype); - covar_flags |= CV_COVAR_USE_AVG; + covar_flags |= CV_COVAR_USE_AVG; } calcCovarMatrix( data, covar, mean, covar_flags, ctype ); @@ -2901,6 +2901,36 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp return *this; } +template +int computeCumulativeEnergy(const Mat& eigenvalues, double retainedVariance) +{ + CV_DbgAssert( eigenvalues.type() == DataType::type ); + + Mat g(eigenvalues.size(), DataType::type); + + for(int ig = 0; ig < g.rows; ig++) + { + g.at(ig, 0) = 0; + for(int im = 0; im <= ig; im++) + { + g.at(ig,0) += eigenvalues.at(im,0); + } + } + + int L; + + for(L = 0; L < eigenvalues.rows; L++) + { + double energy = g.at(L, 0) / g.at(g.rows - 1, 0); + if(energy > retainedVariance) + break; + } + + L = std::max(2, L); + + return L; +} + PCA& PCA::computeVar(InputArray _data, InputArray __mean, int flags, double retainedVariance) { Mat data = _data.getMat(), _mean = __mean.getMat(); @@ -2977,26 +3007,11 @@ PCA& PCA::computeVar(InputArray _data, InputArray __mean, int flags, double reta } // compute the cumulative energy content for each eigenvector - Mat g(eigenvalues.size(), ctype); - - for(int ig = 0; ig < g.rows; ig++) - { - g.at(ig,0) = 0; - for(int im = 0; im <= ig; im++) - { - g.at(ig,0) += eigenvalues.at(im,0); - } - } - int L; - for(L = 0; L < eigenvalues.rows; L++) - { - double energy = g.at(L, 0) / g.at(g.rows - 1, 0); - if(energy > retainedVariance) - break; - } - - L = std::max(2, L); + if (ctype == CV_32F) + L = computeCumulativeEnergy(eigenvalues, retainedVariance); + else + L = computeCumulativeEnergy(eigenvalues, retainedVariance); // use clone() to physically copy the data and thus deallocate the original matrices eigenvalues = eigenvalues.rowRange(0,L).clone();