From c0f6e219bb0f4c770be8e54b46e2d7064887ef81 Mon Sep 17 00:00:00 2001 From: Marina Kolpakova Date: Thu, 12 Apr 2012 04:21:32 +0000 Subject: [PATCH] calcCovarMatrix cupport fot std::vectors of cv::Mat (#494) --- modules/core/src/matmul.cpp | 52 +++++++++++++++++++++++++++++++- modules/core/test/test_math.cpp | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index fc655b6..c634201 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -2098,7 +2098,7 @@ void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, { CV_Assert( data && nsamples > 0 ); Size size = data[0].size(); - int sz = size.width*size.height, esz = (int)data[0].elemSize(); + int sz = size.width * size.height, esz = (int)data[0].elemSize(); int type = data[0].type(); Mat mean; ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F); @@ -2116,6 +2116,7 @@ void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, } Mat _data(nsamples, sz, type); + for( int i = 0; i < nsamples; i++ ) { CV_Assert( data[i].size() == size && data[i].type() == type ); @@ -2135,6 +2136,55 @@ void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, void cv::calcCovarMatrix( InputArray _data, OutputArray _covar, InputOutputArray _mean, int flags, int ctype ) { + if(_data.kind() == _InputArray::STD_VECTOR_MAT) + { + std::vector src; + _data.getMatVector(src); + + CV_Assert( src.size() > 0 ); + + Size size = src[0].size(); + int type = src[0].type(); + + ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F); + + Mat _data(src.size(), size.area(), type); + + int i = 0; + for(vector::iterator each = src.begin(); each != src.end(); each++, i++ ) + { + CV_Assert( (*each).size() == size && (*each).type() == type ); + Mat dataRow(size.height, size.width, type, _data.ptr(i)); + (*each).copyTo(dataRow); + } + + Mat mean; + if( (flags & CV_COVAR_USE_AVG) != 0 ) + { + CV_Assert( _mean.size() == size ); + + if( mean.type() != ctype ) + { + mean = _mean.getMat(); + _mean.create(mean.size(), ctype); + Mat tmp = _mean.getMat(); + mean.convertTo(tmp, ctype); + mean = tmp; + } + + mean = _mean.getMat().reshape(1, 1); + } + + calcCovarMatrix( _data, _covar, mean, (flags & ~(CV_COVAR_ROWS|CV_COVAR_COLS)) | CV_COVAR_ROWS, ctype ); + + if( (flags & CV_COVAR_USE_AVG) == 0 ) + { + mean = mean.reshape(1, size.height); + mean.copyTo(_mean); + } + return; + } + Mat data = _data.getMat(), mean; CV_Assert( ((flags & CV_COVAR_ROWS) != 0) ^ ((flags & CV_COVAR_COLS) != 0) ); bool takeRows = (flags & CV_COVAR_ROWS) != 0; diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 4d333c6..ffed098 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2531,5 +2531,71 @@ protected: TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(); } +TEST(CovariationMatrixVectorOfMat, accuracy) +{ + unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16; + cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F); + int singleMatFlags = CV_COVAR_ROWS; + + cv::Mat gold; + cv::Mat goldMean; + cv::randu(src,cv::Scalar(-128), cv::Scalar(128)); + cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F); + std::vector srcVec; + for(size_t i = 0; i < vector_size; i++) + { + srcVec.push_back(src.row(i).reshape(0,col_problem_size)); + } + + cv::Mat actual; + cv::Mat actualMean; + cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F); + + cv::Mat diff; + cv::absdiff(gold, actual, diff); + cv::Scalar s = cv::sum(diff); + ASSERT_EQ(s.dot(s), 0.0); + + cv::Mat meanDiff; + cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff); + cv::Scalar sDiff = cv::sum(meanDiff); + ASSERT_EQ(sDiff.dot(sDiff), 0.0); +} + +TEST(CovariationMatrixVectorOfMatWithMean, accuracy) +{ + unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16; + cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F); + int singleMatFlags = CV_COVAR_ROWS | CV_COVAR_USE_AVG; + + cv::Mat gold; + cv::randu(src,cv::Scalar(-128), cv::Scalar(128)); + cv::Mat goldMean; + + cv::reduce(src,goldMean,0 ,CV_REDUCE_AVG, CV_32F); + + cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F); + + std::vector srcVec; + for(size_t i = 0; i < vector_size; i++) + { + srcVec.push_back(src.row(i).reshape(0,col_problem_size)); + } + + cv::Mat actual; + cv::Mat actualMean = goldMean.reshape(0, row_problem_size); + cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F); + + cv::Mat diff; + cv::absdiff(gold, actual, diff); + cv::Scalar s = cv::sum(diff); + ASSERT_EQ(s.dot(s), 0.0); + + cv::Mat meanDiff; + cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff); + cv::Scalar sDiff = cv::sum(meanDiff); + ASSERT_EQ(sDiff.dot(sDiff), 0.0); +} + /* End of file. */ -- 2.7.4