使用opencv

时间:2019-03-18 11:22:17

标签: opencv camera-calibration coordinate-transformation

我正在使用opencv校准网络摄像头。因此,我所做的就是将网络摄像头固定在钻机上,以使其保持静态,并且我使用了棋盘校准图案并将其移动到相机前面,并使用检测到的点来计算校准。因此,正如我们在许多opencv示例(https://docs.opencv.org/3.1.0/dc/dbb/tutorial_py_calibration.html)中可以找到的

现在,这为我提供了相机固有矩阵以及旋转和平移组件,用于将这些棋盘视图中的每一个从棋盘空间映射到世界空间。

但是,我感兴趣的是全局外部矩阵,也就是说,一旦我移除了棋盘格,我希望能够在图像场景中指定一个点,即x,y及其高度,并给我指定位置世界空间。据我了解,我既需要内部矩阵也可以使用外部矩阵。如何从这里开始计算外在矩阵?是否可以使用在棋盘校准步骤中已经收集的测量值来计算外部矩阵?

1 个答案:

答案 0 :(得分:2)

让我放置一些背景信息。考虑以下图片(来自https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html):

enter image description here

相机已“连接”刚性参照系(Xc,Yc,Zc)。成功执行的固有校准可让您将点(Xc,Yc,Zc)转换为其在图像(u,v)上的投影,以及点(u,v)在图像中的投影到(Xc,Yc,Zc)中的光线(您只能将其放大至缩放比例)。

在实践中,您要将相机放置在外部“世界”参照系中,我们称其为(X,Y,Z)。然后有一个刚性变换,由旋转矩阵 R 和平移矢量 T 表示,例如:

|Xc|    |X|
|Yc|= R |Y| + T
|Zc|    |Z|

这是外部校准(也可以写为4x4矩阵,也就是外部矩阵)。

现在,答案。要获取 R T ,您可以执行以下操作:

  1. 固定您的世界参考系,例如,地面可以是(x,y)平面,然后为其选择原点。

  2. 在此参考系中设置一些坐标已知的点,例如,地板上正方形网格中的点。

  3. 拍照并获取相应的2D图像坐标。

  4. 使用solvePnP通过以下参数获取旋转和平移:

    • objectPoints:世界参考系中的3D点。
    • imagePoints:图像中对应的2D点与objectPoints的顺序相同
    • cameraMatris:您已经拥有的内在矩阵。
    • distCoeffs:您已经拥有的失真系数。
    • rvec tvec :这些将是输出。
    • useExtrinsicGuess:错误
    • 标志:您可以使用CV_ITERATIVE
  5. 最后,使用Rodrigues函数从 rvec 获得 R

您至少需要3个非共线的点和相应的3D-2D坐标才能使solvePnP起作用(link),但是更好。为了获得高质量的点,您可以打印一个大的棋盘图案,将其平放在地板上,然后用作网格。重要的是图像中的图案不要太小(越大,校准越稳定)。

而且,非常重要:对于内在校准,您使用了具有一定大小正方形的象棋图案,但是您告诉算法(该算法对每种图案都执行solvePnPs),每个正方形的大小为 1 。这不是很明显,但是在示例代码的第10行中完成,其中使用坐标0,1,2,...:

构建网格

objp [:,:2] = np.mgrid [0:7,0:6] .T.reshape(-1,2)

外部校准的世界范围必须与此匹配,因此您有几种可能性:

  1. 使用相同的比例,例如通过使用相同的网格或通过以相同的比例测量“世界”平面的坐标。在这种情况下,您的“世界”规模将不合适。

  2. 推荐:以正确的比例重做固有校准,例如:

    objp [:,:2] =(size_of_a_square * np.mgrid [0:7,0:6])。T.reshape(-1,2)

    其中size_of_a_square是正方形的实际大小。

  3. (尚未执行此操作,但从理论上讲是可能的,如果您无法执行此操作,请执行2)通过缩放fx和fy重用固有校准。这是可能的,因为相机可以看到所有比例尺,并且正方形的声明大小仅会更改fx和fy(每个正方形的姿势中的 T ,但这是另一个故事)。如果正方形的实际大小为 L ,则在调用solvePnP之前,先替换fx和fy L fx和L fy。