66

我对相机校准技术完全陌生……我正在使用 OpenCV 棋盘技术……我正在使用 Quantum 的网络摄像头……

这是我的观察和步骤..

  1. 我保持每个国际象棋正方形边 = 3.5 厘米。它是一个 7 x 5 棋盘,内有6 x 4 个角。我在距网络摄像头 1 到 1.5 m 的距离处总共拍摄了 10 张不同视图/姿势的图像。
  2. 我正在按照Bradski的Learning OpenCV中的 C 代码进行校准。我的校准代码是

    cvCalibrateCamera2(object_points,image_points,point_counts,cvSize(640,480),intrinsic_matrix,distortion_coeffs,NULL,NULL,CV_CALIB_FIX_ASPECT_RATIO);
    
  3. 在调用此函数之前,我将沿固有矩阵的对角线的第一个和第二个元素设为一个,以保持焦距比恒定并使用CV_CALIB_FIX_ASPECT_RATIO

  4. 随着棋盘距离的变化,和fx几乎等于1。当我改变距离时,和的值在200到400之间。和在300到700之间。fyfx:fycxcyfxfy

  5. 目前我已经把所有的失真系数都归零了,因为我没有得到包括失真系数在内的好结果。我的原始图像看起来比未失真的图像帅!

我是否正确进行校准?CV_CALIB_FIX_ASPECT_RATIO我应该使用除?之外的任何其他选项。如果是,是哪一个?

4

2 回答 2

143

嗯,你在找“帅”还是“准”?

相机校准是计算机视觉中为数不多的可以直接用物理术语量化精度并通过物理实验验证的主题之一。通常的教训是(a)您的数字与您投入的努力(和金钱)一样好,并且(b)真正的准确性(与想象的相反)是昂贵的,因此您应该提前弄清楚您的应用程序确实需要精确度。

如果您查看即使非常便宜的镜头/传感器组合(百万像素及以上)的几何规格,很明显亚亚毫米校准精度在理论上可以在桌面空间内实现。只需计算(从相机传感器的规格表)跨越一个像素的立体角 - 你会被你钱包里的空间分辨率所迷惑。然而,实际上要达到接近理论精度的可重复性需要工作。

以下是一些建议(来自个人经验),可帮助您获得良好的国产设备校准体验。

  1. 如果您的方法使用平面目标(“棋盘”或类似目标),请制造一个好的目标。选择一个非常平坦的背衬(对于您提到的 5 毫米厚或更大的窗户玻璃尺寸非常好,尽管显然很脆弱)。验证其对另一个边缘(或者,更好的是激光束)的平整度。在不易拉伸的厚纸上打印图案。在胶合前将其打印在背衬上,并验证方形边确实非常接近正交。廉价的喷墨或激光打印机并非专为严格的几何精度而设计,不要盲目相信它们。最佳做法是使用专业的打印店(即使是 Kinko 的打印机也会比大多数家用打印机做得更好)。然后非常小心地将图案贴在背衬上,使用喷胶并用软布慢慢擦拭以避免气泡和拉伸。等待一天或更长时间,让胶水固化,胶纸应力达到长期稳定状态。最后用好的卡尺和放大镜测量拐角位置。您可能会得到一个“平均”平方大小的数字,但它必须是实际测量的平均值,而不是希望-n-祈祷的平均值。最佳实践是实际使用测量位置表。

  2. 注意您的温度和湿度变化:纸张从空气中吸收水分,背衬膨胀和收缩。令人惊讶的是,您可以找到许多文章报告亚毫米校准精度,而无需引用环境条件(或目标对它们的响应)。不用说,他们大多是垃圾。与普通金属板相比,玻璃的较低温度膨胀系数是首选前者作为背衬的另一个原因。

  3. 不用说,您必须禁用相机的自动对焦功能,如果它有:对焦会物理移动镜头内的一块或多块玻璃,从而(轻微)改变视野和(通常很多)镜头畸变和主点。

  4. 将相机放在不易振动的稳定支架上。根据应用程序的需要(而不是校准 - 校准程序和目标必须针对应用程序的需求进行设计,而不是相反),对焦(和 f-stop 镜头,如果它有光圈的话)。之后甚至不要触摸相机或镜头。如果可能,请避免使用“复杂”镜头——例如变焦镜头或广角镜头。例如,变形镜头需要的模型比现有的 OpenCV 提供的模型要复杂得多。

  5. 进行大量测量和图片。每个图像需要数百个测量值(角)和数十个图像。在数据方面,越多越好。10x10 棋盘是我会考虑的绝对最小值。我通常以 20x20 的速度工作。

  6. 拍照时跨越校准体积。理想情况下,您希望您的测量值均匀分布在您将使用的空间体积中。最重要的是,确保在某些图片中相对于焦轴显着倾斜目标- 校准您需要“看到”一些真实透视缩短的焦距。为获得最佳效果,请使用可重复的机械夹具来移动目标。一个好的是单轴转盘,它会给你一个很好的目标运动先验模型。

  7. 拍照时尽量减少振动和相关的运动模糊。

  8. 使用良好的照明。真的。令人惊讶的是,我经常看到人们在游戏后期意识到您需要大量的光子来校准相机:-) 使用漫反射环境照明,并将其从视野两侧的白卡上反射回来。

  9. 观察你的角落提取代码在做什么。在图像顶部绘制检测到的角位置(例如在 Matlab 或 Octave 中),并判断它们的质量。使用严格的阈值及早去除异常值比信任捆绑调整代码中的鲁棒性更好。

  10. 如果可以的话,约束你的模型。例如,如果您没有充分的理由相信您的镜头明显偏离图像中心,请不要尝试估计主要点,只需在第一次尝试时将其固定在图像中心即可。主点位置通常很难观察到,因为它本质上非线性失真的中心以及与目标到相机平移的图像平面平行的分量混淆。要做到这一点,需要一个精心设计的程序,该程序产生三个或更多独立的场景消失点,并且一个很好的包围非线性失真。同样,除非您有理由怀疑镜头焦轴确实相对于传感器平面倾斜,否则请将相机矩阵的 (1,2) 分量固定为零。一般来说,请使用满足您的测量应用需求的最简单模型(这就是 Ockam 的剃须刀)。

  11. 当您从优化器获得具有足够低 RMS 误差的校准解决方案时(通常为十分之几像素,另请参见下面 Josh 的答案),绘制残差的 XY 模式(predicted_xy - 所有图像中每个角的测量 xy)看看它是否是以 (0, 0) 为中心的圆形云。异常值的“团块”或残差云的不圆度正在发出警报,表明存在非常错误的情况 - 可能是由于角检测或匹配不良或镜头畸变模型不合适而导致的异常值。

  12. 拍摄额外的图像以验证解决方案的准确性 - 使用它们来验证镜头畸变是否实际被消除,并且校准模型预测的平面单应性实际上与从测量角恢复的平面单应性相匹配。

于 2012-10-10T13:55:19.337 回答
43

这是一个相当晚的答案,但对于来自谷歌的人来说:

检查校准精度的正确方法是使用 OpenCV 提供的重投影误差。我不确定为什么在答案或评论中没有提到这一点,您不需要手动计算 - 它是calibrateCamera. 在 Python 中,它是第一个返回值(后面是相机矩阵等)。

重投影误差是使用固有系数投影点的位置与它们在真实图像中的位置之间的 RMS 误差。 通常,您应该期望 RMS 误差小于 0.5 像素——我通常可以使用机器视觉相机获得大约 0.1 像素。许多计算机视觉论文中都使用了重投影误差,没有一种更容易或更准确的方法来确定您的校准有多好。

除非您有立体系统,否则您只能确定某物在 3D 空间中的位置,直到一条射线,而不是一个点。然而,由于可以计算出每个平面校准图像的姿态,因此可以计算出每个棋盘角应该落在图像传感器上的位置。校准过程(或多或少)试图找出这些光线落在哪里,并将所有不同校准图像的误差最小化。在 Zhang 的原始论文和随后的评估中,大约 10-15 张图像似乎就足够了;在这一点上,错误并没有随着添加更多图像而显着降低。

其他软件包(如 Matlab)将为您提供每个固有的误差估计,例如焦距、投影中心。我一直无法让 OpenCV 吐出这些信息,但也许它就在某个地方。相机校准现在在 Matlab 2014a 中是原生的,但您仍然可以使用非常受计算机视觉用户欢迎的相机校准工具箱。

http://www.vision.caltech.edu/bouguetj/calib_doc/

目视检查是必要的,但在处理结果时还不够。寻找最简单的事情是,世界上的直线在您未失真的图像中变得笔直。除此之外,仅通过查看输出图像就无法真正确定您的相机是否校准良好。

Francesco提供的套路很好,照着做。我使用架板作为我的飞机,图案印在海报纸上。确保图像曝光良好 - 避免镜面反射!我使用标准的 8x6 模式,我尝试过更密集的模式,但我还没有看到准确性的提高,以至于它有所作为。

我认为这个答案对于大多数想要校准相机的人来说应该足够了——实际上,除非你试图校准像鱼眼这样的异国情调的东西,或者你出于教育原因这样做,OpenCV/Matlab 就是你所需要的。张的方法被认为足够好,几乎所有计算机视觉研究人员都在使用它,其中大多数人要么使用 Bouguet 的工具箱,要么使用 OpenCV。

于 2014-06-09T11:33:33.023 回答