Python相机校准

3
我有一张图片I1,不是我拍摄的,是从Google下载的。

enter image description here

我将已知的单应性矩阵H应用于I1,得到以下图像I2。

enter image description here

我假设一个相机拍摄了以上的I2图像。我不知道这个相机的相机矩阵,我想要找到它。为了找到这个相机矩阵mtx,我使用了OpenCV相机校准方法:ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None,flags=cv2.CALIB_FIX_ASPECT_RATIO|cv2.CALIB_FIX_K1|cv2.CALIB_FIX_K2|cv2.CALIB_FIX_K3|cv2.CALIB_FIX_K4|cv2.CALIB_FIX_K5)
这是通过正方形和它的真实世界和图像坐标完成的。我选择图像I1中的一个正方形,并使用单应性H获取在I2中该正方形的对应角点。由于我知道在I2中的这些对应点形成了一个正方形,我应该能够从这些点中获取相机矩阵。然而,当我在图像中的不同位置取同一个正方形时,我得到了不同的相机矩阵。这是为什么?我做错了什么,我该如何修复?如何计算正确的相机矩阵?
下面是一个示例。对于这两个选择的方块,我从calibrateCamera函数中得到了不同的mtx值。

enter image description here enter image description here

注意:上面图片中的红点不是I1中完美正方形的角点。我只是粗略标记它们来传达我的观点,即当我取两个不同位置但大小相同的正方形时,我得到的相机矩阵值是不同的。

1个回答

4
这是一个关于校准和计算几何的重要问题。如果你使用不同的对应点重复进行校准,可能会有三个原因导致内部矩阵不同。
1. 对应点存在噪声。 2. 相机校准问题是欠定的。这意味着没有足够的对应信息来唯一解决所有相机参数。 3. 相机校准使用不精确或过于严格的相机模型。
原因1很明显。如果对应点受到测量噪声的影响,则通常会在使用不同的对应点集时获得不同的校准结果。这是因为在校准期间,通过优化处理相机参数以最佳拟合对应点。当存在噪声时,最佳拟合因测量误差而异。
原因2发生在尝试使用不充分信息进行校准时。例如,如果每个图像只有三个对应点,则校准问题是欠定的。您可以通过计算参数来思考这个问题。三个对应点为校准方程提供了6个约束条件(对于每个对应点的x和y位置各两个)。现在,在我们进行校准时,必须联合估计校准对象的姿态(每个图像具有6个自由度)以及内部未知量(焦距、主点、畸变等)。因此,未知数比约束条件多,可能会有无限多种校准结果!因此,如果您选择不同的三个对应点集,则返回的校准结果(如果有)将永远不正确并且通常不相同。
原因3更加微妙。请记住,可以通过指定具有不同数量未知内部参数的相机来进行校准。在具有非常有限的校准信息的情况下,通常最好减少未知量。例如,如果使用单个图像进行校准,则平面校准对象每个图像最多提供8个校准约束条件(因为单应性具有8个自由度)。需要6个约束条件来获得平面的姿态,因此每个图像还剩下2个约束条件。如果您只有一个图像,则当存在超过2个未知数时(例如,焦距和镜头畸变),则无法进行校准。因此,如果我们想要使用单个图像进行校准,必须减少未知量。
在您的情况中,您已将未知量减少到单个焦距(f = fx = fy)和相机的主点。这是3个未知数,但请记住,仅使用单个图像进行校准意味着最多只能有2个内部未知数。因此,您面临着欠定的问题(请参见上述原因2)。
现在,您可能会决定将主点修正到图像中心,这是常见的做法,因为它通常是真实主点的很好近似。现在,您有一个1个未知内部参数(f)的校准问题。重要的问题是,如果我们尝试使用单个图像和4个无噪声对应来校准f,我们能否期望使用不同的对应集获得相同的值?您可能认为是,但答案是否定的。原因是因为校准过程将解决一个过约束的问题(8个约束和7个未知数)。它通常会通过函数最小化过程来解决此问题(如OpenCV的calibrateCamera方法所做的那样)。在OpenCV中,它是通过最小化重新投影误差来完成的。这个解决方案将取决于您提供的对应关系。这相当棘手,因此考虑另一个问题,即您正在尝试将一条直线拟合到略微弯曲的线上的点上。直线是数据的过度简化模型。如果我们尝试从中采样两个点将该线拟合到曲线数据上,则最佳拟合解决方案将取决于采样哪些点。在您的特定情况下,您可以通过使用具有完全2个未知数的内部矩阵,通过删除固定宽高比的标志并将主点固定到图像中心来消除问题2和3。

好的。感谢您清晰的解释。我有两个问题。第一,我是否正确理解cameraCalibration函数会自动将主点固定在图像中心,并自动使用cx和cy作为图像宽度和高度的一半?第二,如果我需要决定相机矩阵的值,您认为我应该怎么做?我应该取一个任意的正方形,然后使用从那里得到的相机矩阵吗? - RaviTej310
默认情况下,主点会被更改(优化)。为了防止这种情况,您可以使用cv::CALIB_FIX_PRINCIPAL_POINT标志。您应该记住,为了调试目的,检查calibrateCamera中的矩阵以确保正确设置标志并使用正确的相机矩阵输入总是一个好主意。如果您按照我的答案末尾建议的做法,您应该能够进行校准,并且对于任何一组对应关系都是相同的。 - Toby Collins
太棒了!我已经测试过了,它似乎有效。你推荐哪些资源来获取这些知识?请问你学习这些东西的地方在哪里? - RaviTej310
1
很高兴这些问题得到了澄清。我已经从事计算机视觉研究多年了(已经超过10年了!),并发表了关于校准/姿态估计的论文。知识来自经验(我本周刚加入SO,以回馈社区),以及在计算几何和数值优化方面的坚实基础。Hartley和Zisserman的书《多视角几何》可以说是获得这种基础的最佳地点 - 不一定要覆盖全部内容,但确实可以真正深入理解你不确定的关键主题。 - Toby Collins
太棒了!非常感谢你的帮助和建议。我会尝试阅读那本书。 - RaviTej310
我在这里提出了一个相关的问题:https://dev59.com/51YM5IYBdhLWcg3w1S7d。如果可能,请查看一下。 - RaviTej310

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接