我正在尝试将一些Matlab代码移植到OpenCV,其中一部分涉及到获取协方差矩阵
倍频程示例:
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版本:
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]
正如你所看到的,类似,但在OpenCV版本中是一个因子2。这里有明显的错误吗?
切换ROWS/COLS标志与转换输入相同:
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]
在openCv calcCovMatrix的定义中,有一个变量没有被明确认为是"scale"。Matlab评估E[(x-mu)(x-mu)'],因此它必须除以nSmaples-1=3-1=2(可以证明除以nSamples-1而不是nSamples,该估计器没有偏差-当nSamples增长时,这不会产生任何实际差异)。另一方面,openCv对此有不同的处理方式,这取决于标志。
更新:Matlab也会随样本数量而缩放,但它不是默认值。这不是默认的,因为正如我之前所说的那样,这是不公正的。因此,如果你想以与matlab相同的方式进行缩放,你可以使用更改@AldurDisciple提供的缩放CV_COVAR_scale的选项,并乘以(nSamples)/(nSample-1)或仅除以(nSamples-1)。然而,除以nSamples也是非常常见的,因为这不是一个非常严重的问题,因为通常nSamples很大,而1/nSamples和1/(nSamples-1)之间的差异非常小。