☰
相机标定与手眼标定全解析:从像素到三维坐标的完整链路
2026/10/19 3:17:30 网站建设 项目流程

1. 从像素到物理世界:相机标定到底在解决什么问题

做过视觉项目的人多半遇到过这种场景:摄像头拍到了一张图,你能准确说出某个特征点在图像里的像素坐标是第几行第几列,但一旦有人问你“这个点在真实世界里离镜头多远、在什么方位”,你就卡住了。相机标定要干的事,就是在这两个坐标系之间架一座桥,让像素坐标能换算成真实的三维空间坐标。

我最早接触这个概念是在一个机械臂抓取的小项目里。当时用了一个普通的工业相机,标定前抓取成功率大概只有六成,标定之后直接拉到九成以上。差别在哪?标定前系统只知道“目标在图像中间偏左”,标定后系统知道“目标在相机坐标系下X=0.23米、Y=-0.05米、Z=0.87米”。这个差距就是标定的价值。

相机标定本质上是在求解一组参数,这组参数描述了相机内部的成像特性(内参)和相机相对于某个世界坐标系的位置姿态(外参)。内参决定了三维空间中的点投影到图像平面上的方式,外参决定了相机在世界坐标系中的摆放位置和朝向。两者合在一起,才能完成从三维世界到二维图像、再从二维图像反推三维世界的完整映射。

适合看这篇内容的人包括:做机器人视觉引导的工程师、搞三维重建的开发者、做AR/VR定位的技术人员,以及任何需要从单目或双目图像中获取空间信息的从业者。即便你之前没接触过标定,只要了解基本的矩阵运算和坐标系概念,下面的内容应该能帮你把整个流程跑通。

2. 核心原理拆解:四个坐标系与两次坐标变换

2.1 四个坐标系的层级关系

要理解标定,先得把四个坐标系的关系理清楚。这四个坐标系从宏观到微观依次是:世界坐标系、相机坐标系、图像物理坐标系、图像像素坐标系。

世界坐标系是你自己定义的一个参考系,可以放在任何地方,比如放在标定板的第一个角点上,也可以放在机械臂的基座中心。相机坐标系以相机光心为原点,Z轴沿光轴方向指向拍摄场景,X轴和Y轴分别平行于图像平面的水平和垂直方向。图像物理坐标系在成像平面上,原点在光轴与成像平面的交点,单位是毫米。图像像素坐标系也在成像平面上,但原点在图像左上角,单位是像素。

从世界坐标系到相机坐标系是刚体变换,用旋转矩阵R和平移向量t描述。从相机坐标系到图像物理坐标系是透视投影,用焦距f描述。从图像物理坐标系到图像像素坐标系是缩放和平移,用像素当量dx、dy和主点坐标u0、v0描述。

2.2 内参矩阵的构成逻辑

把上面后两步变换合并,就得到了内参矩阵K。这个3x3的矩阵长这样:

K = [[fx, 0, u0], [ 0, fy, v0], [ 0, 0, 1]]

其中fx = f/dx,fy = f/dy,分别表示x和y方向上的等效焦距,单位是像素。u0和v0是主点坐标,理论上在图像中心附近,但实际由于装配误差会有偏移。

这里有个容易踩的坑:很多人以为fx和fy一定相等,实际上由于像素可能不是正方形、镜头可能有非对称畸变,两者往往有细微差异。我在一个项目里遇到过fx和fy差了将近8个像素的情况,如果强行设成相等,重投影误差会明显变大。

2.3 畸变模型为什么不可忽略

理想的小孔成像模型假设光线沿直线传播,但实际镜头尤其是广角镜头会产生畸变。主要分两类:径向畸变和切向畸变。

径向畸变让直线在图像边缘变弯,表现为桶形畸变或枕形畸变。切向畸变则是因为镜头和成像平面不完全平行导致的。标定时通常用k1、k2、k3描述径向畸变,用p1、p2描述切向畸变。

注意:如果你的应用场景只在图像中心区域工作,畸变可能不明显,可以不校正。但只要涉及图像边缘的测量,畸变校正就是必须的。我见过一个测量项目因为忽略了畸变,边缘区域的测量误差达到了3毫米以上。

3. 标定实操全流程:从准备到验证

3.1 标定板的选择与制作

标定板是标定的基准,它的精度直接决定了标定结果的精度。常见的有棋盘格标定板和圆点标定板两种。

棋盘格标定板的优势是角点检测算法成熟、亚像素精度高,OpenCV对它的支持也最好。圆点标定板的优势是对模糊和光照变化更鲁棒,但圆心提取的精度通常略低于棋盘格角点。

我一般推荐用棋盘格,具体参数选择上:格子数量建议在6x9到10x7之间,太少约束不够,太多检测容易出错。格子物理尺寸根据你的工作距离来定,工作距离近就用小格子,比如20毫米;工作距离远就用大格子,比如50毫米甚至100毫米。

制作标定板时,打印精度很关键。普通打印机打出来的棋盘格边缘会有毛刺,角点位置会有偏差。如果条件允许,建议用激光打印或者找专业厂家制作陶瓷或玻璃基底的标定板。我试过用普通A4纸打印的标定板,标定重投影误差在0.5像素左右,换成专业标定板后降到了0.15像素。

3.2 拍摄采集的实操要点

拍摄标定图像是整个流程中最需要耐心的环节。核心原则是:让标定板在图像中覆盖尽可能多的位置和角度。

具体操作上,我会这样安排拍摄:

  • 标定板在图像中心、左上、右上、左下、右下各拍一张,确保覆盖整个视场
  • 改变标定板的倾斜角度,前后左右各倾斜20到45度,每个角度拍2到3张
  • 改变标定板与相机的距离,从最近工作距离到最远工作距离均匀分布
  • 总共拍摄15到30张,太少约束不足,太多计算量大且收益递减

提示:拍摄时标定板必须完整出现在图像中,不能有遮挡。同时要保证标定板平面不要过度曝光或欠曝光,角点对比度要清晰。

有个细节很多人忽略:拍摄过程中相机不能动,标定板可以动;或者标定板固定,相机从不同角度拍。两种方式等价,但前者更适合手持相机场景,后者更适合相机固定的工业场景。

3.3 角点检测与参数求解

角点检测用OpenCV的findChessboardCorners函数,检测到粗略角点后用cornerSubPix做亚像素优化。亚像素优化的窗口大小一般设成11x11,迭代终止条件设成最大30次迭代或精度达到0.001。

参数求解用calibrateCamera函数,它内部用的是张正友标定法。这个方法的核心思想是:利用标定板平面上的已知点与其图像投影点之间的对应关系,先线性求解内参的初始值,再用最大似然估计做非线性优化。

调用时的关键参数包括:

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera( object_points, # 世界坐标系中的三维点 image_points, # 图像中的二维点 image_size, # 图像尺寸 None, # 初始内参矩阵,None表示自动计算 None, # 初始畸变系数 flags=cv2.CALIB_FIX_K3 # 根据实际情况选择是否固定某些参数 )

flags的选择有讲究。如果标定图像数量少,建议固定k3,避免过拟合。如果图像数量充足且畸变明显,可以让k3自由优化。

3.4 重投影误差的解读与验证

calibrateCamera返回的ret就是重投影误差,单位是像素。这个值表示的是:用标定得到的内参和外参,把世界坐标系中的标定点重新投影到图像上,与检测到的实际角点位置之间的平均距离。

一般来说,重投影误差在0.1到0.3像素之间算优秀,0.3到0.5像素算合格,超过0.5像素就需要检查问题。但要注意,这个值受图像分辨率影响很大。高分辨率图像上0.5像素可能对应很小的物理误差,低分辨率图像上0.3像素可能对应较大的物理误差。

验证标定质量不能只看重投影误差。我通常会做两件事:一是用标定参数去校正一张没参与标定的图像,看畸变校正效果是否合理;二是用标定参数做实际测量,比如测量一个已知尺寸的物体,看测量值与真实值的偏差。

4. 手眼标定:当相机遇上机械臂

4.1 手眼标定的两种构型

如果你的应用场景是机械臂抓取,那光有相机标定还不够,还需要手眼标定。手眼标定要解决的是相机坐标系和机械臂末端坐标系之间的变换关系。

两种构型:eye-in-hand和eye-to-hand。eye-in-hand是相机装在机械臂末端,跟着机械臂一起动;eye-to-hand是相机固定在外部,机械臂在相机视野内运动。

eye-in-hand的标定方程是AX=XB,其中A是机械臂末端的运动变换,B是相机看到的标定板运动变换,X是待求的相机到末端的变换。eye-to-hand的标定方程是AX=ZB,其中X是末端到标定板的变换,Z是相机到机械臂基座的变换。

4.2 标定数据采集的注意事项

手眼标定的数据采集比单纯相机标定更讲究。核心要求是:机械臂的运动要尽可能覆盖工作空间,且旋转运动要足够丰富。

我一般会让机械臂走12到20个位姿,每个位姿下拍摄一张标定板图像。位姿的选择上,平移范围要覆盖整个工作空间,旋转角度至少在正负30度范围内变化。如果旋转运动太少,旋转矩阵的求解会不稳定。

注意:机械臂运动到位后要等完全停稳再拍照,否则图像会有运动模糊,角点检测精度会下降。我吃过这个亏,有次赶时间没等停稳就拍,结果重投影误差一直下不来,排查了半天才发现是运动模糊导致的。

4.3 标定结果的验证方法

手眼标定做完后,验证方法很直接:让机械臂去抓一个已知位置的目标,看抓取误差。如果误差在1到2毫米以内,说明标定合格。如果误差大,先检查相机标定的重投影误差,再检查手眼标定的数据质量。

另一个验证方法是:用标定结果计算标定板在机械臂基座坐标系中的位置,然后让机械臂末端去触碰标定板的几个角点,看实际触碰位置和计算位置的偏差。

5. 常见问题排查与避坑指南

5.1 重投影误差偏大的排查思路

重投影误差大是最常见的问题,排查顺序建议如下:

排查项可能原因解决方法
标定板图像质量模糊、过曝、欠曝重新拍摄,保证角点清晰
角点检测标定板部分遮挡或出界剔除不合格图像
标定板平整度打印纸不平整使用硬质基底标定板
畸变模型畸变严重但模型阶数不够增加k3或使用有理模型
图像数量太少或位姿分布不均增加图像,均匀分布位姿

我遇到过一次重投影误差始终在0.8像素左右的情况,换了标定板、重新拍了三次都没改善。后来发现是相机镜头没拧紧,有轻微松动。所以排查时也要检查硬件安装是否牢固。

5.2 标定结果不稳定的处理

有时候标定结果会不稳定,比如两次标定得到的内参差异较大。这通常是因为标定图像位姿分布不合理,导致某些参数的可观测性差。

解决办法是增加标定板的倾斜角度变化。如果所有图像中标定板都近似平行于图像平面,那焦距和主点的求解会耦合在一起,结果就不稳定。让标定板在正负45度范围内充分倾斜,可以解耦这些参数。

5.3 实际测量精度不达标的调优

标定重投影误差很小,但实际测量精度不达标,这种情况也很常见。原因通常不在标定本身,而在以下几个方面:

  • 工作距离太远,导致像素当量太大,一个像素对应的物理尺寸太大
  • 标定时的距离与实际工作距离差异大,外参外推误差大
  • 目标点提取精度不够,比如用边缘检测提取的点精度低于标定板角点
  • 环境因素,比如温度变化导致镜头焦距微变

针对这些情况,我的经验是:尽量让标定时的距离和角度接近实际工作条件;如果测量精度要求高,考虑用更高分辨率的相机或者更长的焦距;对于温度敏感的场景,可能需要定期重新标定。

6. 从标定到三维坐标计算的完整链路

6.1 单目相机的三维坐标计算

单目相机标定完成后,从像素坐标反推三维坐标需要额外的约束。因为单张图像丢失了深度信息,一个像素点对应的是空间中的一条射线,而不是一个点。

要确定三维坐标,通常有两种方式:一是已知目标在某个平面上的约束,比如目标在传送带上,传送带平面在世界坐标系中的方程已知;二是已知目标的某些几何尺寸,比如已知目标是一个直径10厘米的球。

以平面约束为例,计算过程是:先用标定参数把像素坐标转换成相机坐标系下的归一化坐标,再结合平面方程求解射线与平面的交点,最后通过外参转换到世界坐标系。

6.2 双目相机的三维坐标计算

双目相机通过两个相机同时拍摄,利用视差计算深度。标定需要分别标定左右相机,再标定两者之间的相对位置关系。

双目标定的关键是立体校正,让左右图像的极线水平对齐。校正后,同一个目标点在左右图像中的行坐标相同,列坐标之差就是视差。深度Z = f * B / d,其中f是焦距,B是基线距离,d是视差。

提示:双目系统的精度很大程度上取决于基线距离。基线越长,同样视差误差对应的深度误差越小。但基线太长会导致左右图像重叠区域减小,所以需要根据工作距离折中。

6.3 坐标转换的代码实现

从像素坐标到世界坐标的完整转换,用OpenCV实现大概是这样的:

import numpy as np import cv2 # 假设已经标定得到内参和畸变系数 # mtx, dist = ... # 像素坐标 pixel_point = np.array([[[u, v]]], dtype=np.float32) # 去畸变 undistorted = cv2.undistortPoints(pixel_point, mtx, dist) # 归一化坐标 x_norm = undistorted[0][0][0] y_norm = undistorted[0][0][1] # 假设目标在Z=0平面上(世界坐标系) # 需要外参R, t # 构造射线方向 ray_dir = np.array([x_norm, y_norm, 1.0]) ray_dir = np.linalg.inv(mtx) @ np.array([u, v, 1.0]) # 结合平面方程求解 # ...

实际使用时,外参的获取方式取决于具体场景。如果是固定相机看固定平面,外参可以通过标定板一次性确定。如果是相机运动,外参需要实时估计。

7. 标定精度的进阶优化策略

7.1 多相机联合标定

当系统中有多个相机时,单独标定每个相机再标定它们之间的相对关系,误差会累积。更好的做法是联合标定,把所有相机的参数放在一个优化问题里同时求解。

联合标定的优势是能利用所有相机之间的约束,提高整体精度。实现上可以用ceres solver或者g2o这类优化库,把重投影误差作为目标函数,所有参数作为优化变量。

7.2 在线标定与自标定

传统标定需要专门的标定板和流程,在一些应用场景中不方便。在线标定利用场景中的已知结构或者相机运动本身来估计参数,不需要专门的标定物。

自标定的核心思想是利用图像之间的对应点约束来求解内参。比如用SIFT或ORB提取特征点,匹配后通过基础矩阵或单应矩阵约束来估计焦距和主点。但自标定的精度通常低于传统标定,适合对精度要求不高的场景。

7.3 温度与振动补偿

在高精度工业场景中,温度变化会导致镜头和相机结构微小变形,振动会导致相机位置偏移。这些因素都会让标定参数失效。

补偿方法包括:在相机附近安装温度传感器,建立温度与参数漂移的模型;定期用标准件做校验,发现偏差及时修正;机械结构上做隔振设计,减少振动影响。

我在一个精密测量项目里的做法是:每工作4小时用标准件校验一次,如果偏差超过阈值就重新标定。虽然麻烦,但保证了测量数据的可靠性。

8. 我踩过的坑与实操心得

说几个实际项目中踩过的坑,希望能帮你省点时间。

第一个坑是标定板打印精度。早期为了省事用普通打印机打棋盘格,标定重投影误差一直在0.4像素左右下不来。后来借了一块专业标定板,同样的流程跑下来直接降到0.12像素。标定板本身的精度是标定精度的上限,这个钱不能省。

第二个坑是拍摄时的光照。有次在车间现场标定,顶部有强光直射标定板,导致部分角点过曝,检测出来的角点位置有偏移。后来用遮光板挡了一下,问题解决。标定时的光照要均匀柔和,避免直射光和反光。

第三个坑是忽略畸变模型的适用性。有个项目用了鱼眼镜头,但标定时用的是普通畸变模型,结果边缘区域校正效果很差。鱼眼镜头需要用专门的鱼眼畸变模型,OpenCV里有对应的fisheye模块。

第四个坑是手眼标定时机械臂运动不够丰富。有次只让机械臂做了平移运动,旋转角度很小,结果标定出来的旋转矩阵误差很大。后来补做了几个大角度旋转的位姿,精度才达标。

最后分享一个实用技巧:标定完成后,把标定参数和当时的温度、工作距离、标定板型号都记录下来。下次如果发现精度下降,可以快速判断是哪个因素变化导致的,不用从头排查。这个习惯帮我节省了很多现场调试的时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询