我一直在我的 OpenCV 和 OpenGL 组件之间来回切换,我不确定这两者中的哪一个应该更正。
使用 OpenCV 相机校准产生 fx, fy 的纵横比约为 1,这将对应于正方形大小的图像。我的校准输出:
...
image_width: 640
image_height: 480
board_width: 6
board_height: 9
square_size: 5.
flags: 0
camera_matrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 6.6244874649105122e+02, 0., 3.4060477796553954e+02,
0., 6.4821741696313484e+02, 2.5815418044786418e+02,
0., 0., 1. ]
distortion_coefficients: !!opencv-matrix
rows: 5
cols: 1
dt: d
data: [ -1.1832005538154940e-01, 1.2254891816651683e+00, 3.8133468645674677e-02, 1.3073747832019200e-02, -3.9497162757084490e+00 ]
但是,我的图像宽度是 640x480,正如您在校准输出中看到的那样。
当我在框架中检测到棋盘并使用 OpenGL 绘制棋盘时,OpenGL 在高度上呈现正常但在宽度方向上拉伸,因此它不适合棋盘的实际位置。肯定能解决它的是将校准的 fx 分量乘以 480/640,但我不知道这是否可行。
我该如何纠正这个问题?用图像大小缩放校准值,或者在 OpenGL 中做些什么来修复它?
编辑
捕获和显示是有区别的。我使用经过校准的智能手机拍摄图像,智能手机会吐出 640x480 的图像。
为了找到棋盘,我使用了如上所示的内在函数,它们是经过校准的。
那么,不管我给OpenGL哪个纵横比,让它是fx/fy、640/480或者fx/fy * 640/480,都是错误的。在 OpenGL 中投射回来的棋盘,使得 OpenGL 投射回来的东西在宽度方向上被拉伸。
它在 OpenGL 中看起来完全正确的唯一方法是,如果我使用 fx=640, fy=480来查找 chessboard。这也是错误的,因为现在我完全忽略了相机的内在特性......
编辑2
我的意思是,无论我如何设置传递给 gluPerspective 的纵横比,它都不正确。
gluPerspective( /* field of view in degree */ m_fovy,
/* aspect ratio */ 1.0/m_aspect_ratio,
/* Z near */ 1.0, /* Z far */ 1000.0);
我为 m_aspect_ratio 的值所做的尝试:
- OpenCV的calibrationMatrixValues的输出纵横比
- fx/fy
- 640/480
- fx/fy * 640/480
- 校准矩阵值的输出 * 640/480
一切似乎都搞砸了宽度。请注意,在我的屏幕截图中,棋盘的原点是图像的最上角:它放置正确,图像中的最底角也是如此。这是一个缩放问题..
编辑3
这真的是非常非常愚蠢的事情。我正在为 OpenGL 设置纵横比,如下所示:
gluPerspective( /* field of view in degree */ m_fovy,
/* aspect ratio */ 1.0/m_aspect_ratio,
/* Z near */ 1.0, /* Z far */ 1000.0);
和设置
m_aspect_ratio = viewportpixelheight / viewportpixelwidth;
没有意识到viewportpixelheight
andviewportpixelwidth
是整数,所以我正在做整数除法,结果要么为 1,要么(交换它们时)为 0。