Merge pull request #1004 from jet47:fix-bug-3068

pull/1005/merge
Roman Donchenko 12 years ago committed by OpenCV Buildbot
commit c4974a2511
  1. 57
      modules/core/src/matmul.cpp

@ -2855,9 +2855,9 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp
if( _mean.data ) if( _mean.data )
{ {
CV_Assert( _mean.size() == mean_sz ); CV_Assert( _mean.size() == mean_sz );
_mean.convertTo(mean, ctype); _mean.convertTo(mean, ctype);
covar_flags |= CV_COVAR_USE_AVG; covar_flags |= CV_COVAR_USE_AVG;
} }
calcCovarMatrix( data, covar, mean, covar_flags, ctype ); calcCovarMatrix( data, covar, mean, covar_flags, ctype );
@ -2901,6 +2901,36 @@ PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComp
return *this; return *this;
} }
template <typename T>
int computeCumulativeEnergy(const Mat& eigenvalues, double retainedVariance)
{
CV_DbgAssert( eigenvalues.type() == DataType<T>::type );
Mat g(eigenvalues.size(), DataType<T>::type);
for(int ig = 0; ig < g.rows; ig++)
{
g.at<T>(ig, 0) = 0;
for(int im = 0; im <= ig; im++)
{
g.at<T>(ig,0) += eigenvalues.at<T>(im,0);
}
}
int L;
for(L = 0; L < eigenvalues.rows; L++)
{
double energy = g.at<T>(L, 0) / g.at<T>(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) PCA& PCA::computeVar(InputArray _data, InputArray __mean, int flags, double retainedVariance)
{ {
Mat data = _data.getMat(), _mean = __mean.getMat(); 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 // compute the cumulative energy content for each eigenvector
Mat g(eigenvalues.size(), ctype);
for(int ig = 0; ig < g.rows; ig++)
{
g.at<float>(ig,0) = 0;
for(int im = 0; im <= ig; im++)
{
g.at<float>(ig,0) += eigenvalues.at<float>(im,0);
}
}
int L; int L;
for(L = 0; L < eigenvalues.rows; L++) if (ctype == CV_32F)
{ L = computeCumulativeEnergy<float>(eigenvalues, retainedVariance);
double energy = g.at<float>(L, 0) / g.at<float>(g.rows - 1, 0); else
if(energy > retainedVariance) L = computeCumulativeEnergy<double>(eigenvalues, retainedVariance);
break;
}
L = std::max(2, L);
// use clone() to physically copy the data and thus deallocate the original matrices // use clone() to physically copy the data and thus deallocate the original matrices
eigenvalues = eigenvalues.rowRange(0,L).clone(); eigenvalues = eigenvalues.rowRange(0,L).clone();

Loading…
Cancel
Save