Question

I'm trying to port some Matlab code to OpenCV, part of it involves getting the covariance matrix

Octave example:

octave:1> A=[-1, 1, 2; -2, 3, 1; 4, 0, 3;]
A =

  -1   1   2
  -2   3   1
   4   0   3

octave:2> cov(A)
ans =

   10.3333   -4.1667    3.0000
   -4.1667    2.3333   -1.5000
    3.0000   -1.5000    1.0000

OpenCV version:

Mat_<double> A(3,3);  A << -1, 1, 2, -2, 3, 1 , 4, 0, 3;
Mat Sw, mea;
calcCovarMatrix( A, Sw, mea, cv::COVAR_NORMAL|cv::COVAR_ROWS );
cerr << Sw << endl;

[20.66666666666666, -8.333333333333334, 6;
 -8.333333333333334, 4.666666666666667, -3;
 6, -3, 2]

As you can see, similar, but a factor 2 in the OpenCV version . Any obvious mistake here?


switching the ROWS/COLS flag is the same as transposing the input:

calcCovarMatrix( A, Sw, mea, cv::COVAR_NORMAL|cv::COVAR_COLS );
[4.666666666666666, 5.666666666666666, -2.666666666666667;
 5.666666666666666, 12.66666666666667, -9.666666666666666;
 -2.666666666666667, -9.666666666666666, 8.666666666666666]

calcCovarMatrix( A.t(), Sw, mea, cv::COVAR_NORMAL|cv::COVAR_COLS );
[20.66666666666666, -8.333333333333334, 6;
 -8.333333333333334, 4.666666666666667, -3;
 6, -3, 2]
Was it helpful?

Solution

In the definition of the openCv calcCovMatrix there is a variable that is not being explicitly considered called "scale". Matlab evaluates E[(x-mu)(x-mu)'] so it must be dividing by nSmaples-1=3-1=2 (one can prove that dividing by nSamples-1 instead of nSamples this estimator is not biased - this does not make any real difference when nSamples grows) . On the other hand, openCv treats this differently and it depends on the flag.

UPDATE: Matlab also scales with the number of samples, but it is not the default. This is not the default, because as I told before it is not unbiased. So if you want to scale as the same way of matlab, you can use the option that changes the scale CV_COVAR_SCALE provided by @AldurDisciple and multiply by (nSamples)/(nSample-1) or just divide by (nSamples-1). However, it is very common as well to divide by nSamples since this is not a very serious problem, because usually nSamples is large and the difference between 1/nSamples and 1/(nSamples-1) is really small.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top