cv::mean() and cv::calcCovarMatrix() returns different mean

asked 2018-08-28 13:25:09 -0500

Aiyyaa gravatar image

updated 2018-09-06 15:40:22 -0500

I have two pictures in grayscale of the same size MxN, img1 and img2. When I use function cv::mean() on these pictures, it returns one values. After that, I produce two column vectors of these pictures and get a matrix of size MNx2, samples. Then i use function cv:: calcCovarMatrix(). This function should return covariation matrix and matrix of mean values on each columns. But values of mean matrix of function cv:: calcCovarMatrix(). are differ from values returned from cv::mean() function. Here's my code.

   Mat img1 = imread( "sample.jpeg", 0 );
    Mat img2 = imread( "sample3.jpeg", 0 );

     cout<<mean(img1)<<endl;
    cout<<mean(img2)<<endl;

results are:

[127.303, 0, 0, 0]
[161.606, 0, 0, 0]

after that I use function cv::calcCovarMatrix():

int all_pixels = img1.cols*img1.rows;
Mat_<float> samples;
samples.create(all_pixels, 2);
int counter = 0;
for(int i = 0; i < img1.rows; i++){
for(int j = 0; j < img1.cols; j++){
samples.at<float>(0,counter) = img1.at<uchar>(i,j);
samples.at<float>(1,counter) = img2.at<uchar>(i,j);
counter++;
}
}
Mat cov, mu;
calcCovarMatrix(samples, cov, mu, COVAR_NORMAL | COVAR_ROWS);
cout << "mu: " << endl;
cout << mu << endl;

it returns :

mu: 
[63.65198211624441, 63.65911574764034]

Why these values are not the same as in cv::mean()?

I tried another way to copy data, and not I have different values of covariances and mean for different ways of copying data

When I used this new way to copy data, I get different results of covariance.

double av1 = mean(img1)[0];
    double av2 = mean(img2)[0];
    cout<<"mean1 = "<<av1<<", mean2 = "<<av2<<endl;

gives me:

mean1 = 127.303, mean2 = 161.606

and then I have two sample arrays, samplesOld and samplesNew. Old way of copying data:

 int all_pixels = img1.cols*img1.rows;
    cout<<"all_pixels = "<<all_pixels<<endl;
    Mat_<float> samplesOld;
    samplesOld.create(all_pixels, 2);
    int counter = 0;


    for(int i = 0; i < img1.rows; i++){
    for(int j = 0; j < img1.cols; j++){
    samplesOld.at<float>(0,counter) = (img1.at<uchar>(i,j));
    samplesOld.at<float>(1,counter) = (img2.at<uchar>(i,j) );
    counter++;
    }
    }

New way of copying data:

 Mat samplesNew;
    samplesNew.push_back(img1.reshape(1,1)); // img1, flattened, goes on the 1st row
    samplesNew.push_back(img2.reshape(1,1)); // img2 on the 2nd, etc.

    samplesNew.convertTo(samplesNew, CV_32F);

 transpose(samplesNew,samplesNew);

After that I have new arrays for covariances of old and new array samples arrays

Mat covOld, muOld;
cv::calcCovarMatrix(samplesOld, covOld, muOld, COVAR_NORMAL | COVAR_ROWS);

Mat covNew, muNew;
cv::calcCovarMatrix(samplesNew, covNew, muNew, COVAR_NORMAL | COVAR_ROWS);

covOld = covOld / (samplesOld.rows - 1);
covNew = covNew / (samplesNew.rows - 1);


cout << "\ncovOld: " << endl;
cout << covOld << endl;
cout << "covNew: " << endl;
cout << covNew << endl;

This gives me

covOld: 
[7215.396208855592, 7157.354438304864;
 7157.354438304864, 7215.581732969795]
covNew: 
[6327.103578936067, 1127.485398832948;
 1127.485398832948, 5500.445588341399]

and this

    cout << "\nmuOld: " << endl;
    cout << muOld << endl;

cout << "muNew: " << endl;
cout << muNew << endl;

gives me values:

muOld: 
[63.65198211624441, 63.65911574764034]
muNew: 
[127.3026130153999, 161.606000993542]

Here ... (more)

edit retag flag offensive close merge delete

Comments

why do you expect those to be the same ?

berak gravatar imageberak ( 2018-08-29 00:24:34 -0500 )edit

samples.at<float>(0,counter) <-- can you spot the overflow ?

please NEVER use for loops like that, to copy data !

berak gravatar imageberak ( 2018-08-29 00:38:26 -0500 )edit