啥是雅克比啊?
前段时间,在进行双目视觉项目时,出现了这么一个很磨人的报错:
CALIB_CHECK_COND - Ill-conditioned matrix for input array
这是一个断言异常,而3.4.1以下的版本,对应的异常信息提示为:
Assertion failed (svd.w.at<double>(0) / svd.w.at<double>((int)svd.w.total() - 1) < thresh_cond)
在源码中,可以定位到cv::internal::CalibrateExtrinsics函数,而发生断言异常的代码如下:
if (check_cond)
{
SVD svd(JJ_kk, SVD::NO_UV);
if(svd.w.at<double>(0) / svd.w.at<double>((int)svd.w.total() - 1) > thresh_cond )
CV_Error( cv::Error::StsInternal, format("CALIB_CHECK_COND - Ill-conditioned matrix for input array %d",image_idx));
}
当其计算JJ_kk矩阵的特征根时,最大特征值远大于(通过thresh_cond来度量)最小特征值时,即抛出断言异常;而JJ_kk来源于projectPoints函数计算得到的雅克比矩阵。不防参考下官方文档这雅克比矩阵是个啥:
- jacobian – Optional output 2Nx(10+<numDistCoeffs>) jacobian matrix of derivatives of image points with respect to components of the rotation vector, translation vector, focal lengths, coordinates of the principal point and the distortion coefficients. In the old interface different components of the jacobian are returned via different output parameters.
也就是说,这个雅克比参数是图像坐标点关于R、T、焦距、坐标中心和畸变系数的导数/偏导数。那么,这又有特征值什么事呢?
这其实类似于PCA,如果以上变量中,比如R的值,其不是image points坐标的因变量,那么其explained_variance_ratio就很低。也就是说图像点坐标的变化跟R值无关,或者说极弱相关,就会造成某个特征值为零或者接近于0;然而这是不正确的,因为理论上图像点坐标与R值是明显相关的。因此当检查特征值时,发现异常时,即可认为所输入的点对不能用于计算内外参。
那么如何解决这样的问题呢?
通常会遇到这个问题,我们可以大部分确认的是,采集标定图像的流程步骤都是正常的,那么就是采集到的image points点过于密集了,导致计算得到的偏导数由于信噪比过低而完全被噪声覆盖掉了(啥?噪声?是的,像素坐标其实是离散的,所以会有采样误差,因此产生噪声),通常首先可以删掉断言报错时对应的图像对。
而如果删掉异常图像对后,图像对数目不足时,需要补充采集图像,此时一定要注意尽量保证棋盘格在双目的视野中均占据较大像素区域。也就是使得A=Area左(棋盘格)+Area右(棋盘格)尽量大。
参考文献:
http://mini.eastday.com/mobile/181004122725427.html
https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
|