我正在使用一些OpenCV摄像机校准代码,基本上与此相同:
obj_p[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) * chessboard_scale
已经进行了一些微小的更改,但它们并不是很重要。在这里,我添加了chessboard_scale
因子,它只是每个棋盘方块的真实尺寸-我想使用相机参数和PnP将图像像素坐标映射到感兴趣特征的真实空间位置,这为我们提供了一个现实的参考因素。
chessboard_size
只是一个列表,例如[4, 3]
,如果更改了,则可以轻松更改棋盘参考图像的大小。
将相机固定在一个位置上,并且相同的棋盘图像在相机场周围的不同位置保持在地板上,拍摄了9个图像帧,我们找到了棋盘角,运行calibrateCamera
功能就像上面的链接一样,相机矩阵,失真矩阵,平移和旋转矢量都保存到磁盘中。
然后我们可以获取相机矩阵等,并使用这些最适合的相机参数进行projectPoints
重投影,并检查其准确性-就像上面的示例一样。
Reprojection error: 0.33721979012691095
Reprojection error: 0.027728399041840827
Reprojection error: 0.07009944842650938
Reprojection error: 0.10604248297665374
Reprojection error: 0.09021003521251016
Reprojection error: 0.042449648057915984
Reprojection error: 0.7679437154358325
Reprojection error: 0.035574908785270136
Reprojection error: 0.04741923955415145
Mean reprojection error: 0.16940974084639945
还不错。这些数字看起来都很小,很好。就可见的桶形失真而言,传入的样本图像似乎更好-它经过了“校正”,并且图像中的直线特征实际上是直线,而不是曲线。
我们不希望校准图像集太小-因为这可能会过度拟合少量校准点并产生较差的整体拟合风险-大量校准点可能会提供即使重投影误差不像使用较小的数据集那样小,总的来说还是可以更精确地拟合-是吗?
现在,我们对这段代码进行一些修改-这是我做错的部分,或者我的期望是一个误解。
同一台摄像机,同一场景,同一棋盘。我从摄像机场景中拍摄了9个新帧,而棋盘位于地板上的不同位置(因此始终处于同一平面),而没有移动摄像机。
我现在已经以与以前完全相同的方式设置了对象点和图像点。
我已经像以前一样运行findChessboardCorners
来找到图像点,并且对象点是由numpy生成的已知矩形网格,其中每个交点的间距均为7cm。和上面一样。
现在,我已经使用projectPoints
来计算9张新图像的重投影误差。
calibrateCamera
这次不是 运行-我使用从calibrateCamera
的输出中存储的相同存储的摄像机矩阵,失真矩阵,平移矢量和旋转矢量。>
这些相机校准参数通常应该在整个相机领域都有意义,对吧?
但是我得到的重投影值非常大-根本不像选择校准的点那样接近零。
我希望看到与在projectPoints
所用的同一图像集上进行calibrateCamera
重投影测试时收到的值相似。
为什么这些很小的值不接近零?我想念什么?
Reprojection error: 161.98785675566046
Reprojection error: 255.77330602950087
Reprojection error: 131.31518741023095
Reprojection error: 205.71173597281907
Reprojection error: 119.54532276972036
Reprojection error: 329.7339468316268
Reprojection error: 33.164501816058596
Reprojection error: 371.8755721630314
Reprojection error: 358.59670901736973
Mean reprojection error: 218.63379319622425