calcCovarMatrix cupport fot std::vectors of cv::Mat (#494)
authorMarina Kolpakova <no@email>
Thu, 12 Apr 2012 04:21:32 +0000 (04:21 +0000)
committerMarina Kolpakova <no@email>
Thu, 12 Apr 2012 04:21:32 +0000 (04:21 +0000)
modules/core/src/matmul.cpp
modules/core/test/test_math.cpp

index fc655b6..c634201 100644 (file)
@@ -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<cv::Mat> 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<cv::Mat>::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;
index 4d333c6..ffed098 100644 (file)
@@ -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<cv::Mat> 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<cv::Mat> 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. */