相机标定基础 - 内参与畸变校正实用指南
什么是相机标定 - 为什么需要它
相机标定是确定相机内部参数(焦距、主点、畸变系数)的过程。这些参数描述了三维世界中的点如何映射到二维图像平面上。准确的标定是计算机视觉中测量、三维重建、增强现实等应用的基础。
为什么需要标定:所有真实相机的镜头都会引入畸变(直线变弯曲);不同相机的焦距和传感器尺寸不同,影响投影关系;精确的测量和三维重建要求已知相机的精确几何模型。
标定的应用场景:自动驾驶中的障碍物距离估计、工业检测中的尺寸测量、AR 应用中虚拟物体的正确放置、全景图像拼接中的畸变校正、立体视觉中的深度计算。
相机标定(Camera Calibration)是估计一组参数、用数学方式描述相机光学与几何特性的处理。需要标定的场合包括:三维测量(用立体视觉或 Structure from Motion 精确测距)、AR(把虚拟物体准确放置到现实世界中)、自动驾驶(从相机图像估计到障碍物的距离)、机器人视觉(把机械臂坐标系与相机坐标系对应起来)、畸变校正(去除广角镜头的桶形畸变以获得准确图像)。相机参数分为两类:内参(Intrinsic)是焦距、主点、畸变系数等相机固有的光学特性;外参(Extrinsic)是旋转矩阵与平移向量,表示相机在世界坐标系中的位置与姿态。
针孔相机模型 - 投影的数学描述
针孔相机模型是描述三维到二维投影的基本数学模型。假设光线通过一个无限小的孔(针孔)投射到成像平面上。
内参矩阵 K:3x3 矩阵,包含焦距(fx, fy,以像素为单位)和主点坐标(cx, cy,图像中心的像素位置)。将相机坐标系中的三维点投影到像素坐标。
外参:旋转矩阵 R(3x3)和平移向量 t(3x1),描述相机在世界坐标系中的位姿。将世界坐标转换为相机坐标。
投影方程:s * [u, v, 1]^T = K * [R | t] * [X, Y, Z, 1]^T。其中 (X,Y,Z) 是世界坐标,(u,v) 是像素坐标,s 是缩放因子。
针孔模型的局限:不考虑镜头畸变(真实镜头会弯曲直线)、不考虑景深(所有距离都清晰)、不考虑光学像差。实际应用中需要在针孔模型基础上添加畸变模型。
内参矩阵 K 写作 K = [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]:fx、fy 是以像素为单位的焦距,fx = f × sx(f 为物理焦距 mm,sx 为 x 方向的像素密度 pixel/mm);cx、cy 是主点(光轴与像面的交点)的像素坐标,理想情况下位于图像中心,实际会偏离数个像素。常见相机的内参举例:iPhone 14 Pro(主摄)fx ≈ 3,000 px、cx ≈ 2,016 px、cy ≈ 1,512 px(4,032 × 3,024 分辨率);GoPro Hero 11 因为是广角、焦距短,fx ≈ 1,500 px;工业相机(5MP、8mm 镜头)fx ≈ 2,800 px。
镜头畸变模型 - 径向畸变与切向畸变
真实镜头会引入两种主要畸变:径向畸变和切向畸变。
径向畸变:由镜头的球面形状引起。分为桶形畸变(图像边缘向外膨胀,广角镜头常见)和枕形畸变(图像边缘向内收缩,长焦镜头常见)。用多项式模型描述:r_distorted = r * (1 + k1*r² + k2*r⁴ + k3*r⁶),其中 r 是到图像中心的距离,k1/k2/k3 是畸变系数。
切向畸变:由镜头与传感器不完全平行引起。使图像产生倾斜效果。用两个参数 p1、p2 描述。通常比径向畸变小得多。
OpenCV 畸变模型:使用 5 个参数 (k1, k2, p1, p2, k3) 描述畸变。对于鱼眼镜头,使用等距投影模型(4 个参数 k1-k4)。
畸变的影响:在图像边缘最明显(距中心越远畸变越大)。对于普通镜头,中心区域畸变可忽略;对于广角和鱼眼镜头,畸变非常显著,必须校正。
径向畸变(Radial Distortion)是随着离镜头中心的距离而产生的畸变:桶形畸变(Barrel)为 k1 < 0,广角镜头容易出现;枕形畸变(Pincushion)为 k1 > 0,长焦镜头容易出现。公式为 x_distorted = x(1 + k1*r² + k2*r⁴ + k3*r⁶) 与 y_distorted = y(1 + k1*r² + k2*r⁴ + k3*r⁶),其中 r² = x² + y²(归一化坐标下到中心的距离)。常见取值:广角镜头 k1 ≈ -0.3、标准镜头 k1 ≈ -0.05、长焦镜头 k1 ≈ 0.01。切向畸变(Tangential Distortion)在镜头与传感器不完全平行时产生,公式为 x_distorted = x + 2*p1*x*y + p2*(r² + 2*x²) 与 y_distorted = y + p1*(r² + 2*y²) + 2*p2*x*y,常见取值 p1、p2 ≈ ±0.001。高质量镜头可以忽略,但廉价镜头与 Web 摄像头必须校正;像 GoPro 这类超广角镜头,有时还需要更高次的畸变系数(k4、k5、k6)或薄棱镜模型。
Zhang 标定法的操作步骤
张正友标定法(Zhang's Method)是最广泛使用的相机标定方法,使用平面棋盘格图案作为标定板。
准备工作:打印高质量的棋盘格图案(建议 9x6 或 11x8 内角点),贴在平整的硬板上。确保打印精度(方格尺寸误差小于 0.1mm)。
拍摄标定图像:从不同角度和距离拍摄 15-25 张棋盘格照片。覆盖图像的各个区域(不要只拍中心)。包含不同的倾斜角度(15-45°)。确保棋盘格完全在画面内且清晰。
角点检测:使用 OpenCV 的 findChessboardCorners() 检测棋盘格内角点。cornerSubPix() 进一步精确到亚像素精度。检测失败的图像应排除。
标定计算:cv2.calibrateCamera() 输入所有图像的角点坐标和对应的世界坐标,输出内参矩阵 K、畸变系数和每张图像的外参。
评估精度:计算重投影误差(将三维点用标定结果投影回图像,与检测到的角点比较)。好的标定重投影误差应小于 0.5 像素,优秀的小于 0.1 像素。
Zhang 法(2000 年)只要从多个角度拍摄平面图案(棋盘格),就能估计出相机的全部参数。所需器材:棋盘格图案(推荐内部角点数 9x6 或 10x7);图案的平面性很重要,应贴在厚纸板或亚克力板上;方格尺寸要准确测量(例如 25mm)。拍摄要点:最少 10 张、推荐 20-30 张;把图案倾斜到各种角度(±45° 左右);改变位置让图案分布到整幅图像,也要出现在图像边缘(对畸变估计很重要);使用对焦清晰的图像。OpenCV 的实现步骤是:用 cv2.findChessboardCorners() 检测角点,用 cv2.cornerSubPix() 校正到亚像素精度,建立三维点(棋盘格上的已知坐标)与二维点(检测到的角点)的对应,再用 cv2.calibrateCamera() 同时估计全部参数。质量用重投影误差(Reprojection Error)评估:良好的标定为 0.1-0.5 像素,允许范围是 1.0 像素以下,超过 1.0 时需要重新检查拍摄条件与角点检测。
畸变校正的实现与应用
标定完成后,使用获得的参数对图像进行畸变校正。
OpenCV 畸变校正:cv2.undistort(img, K, dist_coeffs) 一步完成校正。或使用 initUndistortRectifyMap() + remap() 两步法,预计算映射表后可以高速处理多张图像。
校正后的图像特征:直线恢复为直线(最直观的验证方法);图像边缘可能出现黑色区域(畸变校正后的有效区域小于原图);可以选择裁剪黑边或保留完整校正区域。
应用场景:
- 测量应用:校正后的图像中像素距离与真实距离成正比,可以进行精确测量
- 拼接应用:校正畸变后的图像更容易进行特征匹配和拼接
- AR 应用:正确的相机参数确保虚拟物体与真实场景对齐
- 立体视觉:双目标定后进行极线校正,使对应点搜索简化为一维问题
校正的实现有两种方法:方法 1 是每帧调用 cv2.undistort(),写法简单但每帧都要重新计算,视频处理时效率低;方法 2 是 cv2.initUndistortRectifyMap() + cv2.remap(),预先计算映射表并复用,映射只需算一次,remap 很快(1080p 约 3ms)。校正后的图像尺寸:畸变校正会让图像边缘缺失,因此用 cv2.getOptimalNewCameraMatrix() 计算新的相机矩阵,alpha=0 完全去除黑色区域(图像变小)、alpha=1 保留全部像素(残留黑色区域),按用途在 0-1 之间调整 alpha。鱼眼镜头的校正:普通畸变模型无法应对 180° 以上视角的鱼眼镜头,OpenCV 的 cv2.fisheye 模块使用等距投影模型,用 cv2.fisheye.calibrate() 与 cv2.fisheye.undistortImage() 即可完成超广角镜头的标定与校正。标定结果可以保存为 YAML 或 JSON 格式、在应用中读取使用,用 OpenCV 的 cv2.FileStorage 类可以轻松保存与读取。
高精度标定技巧与故障排除
提高标定精度和解决常见问题的实用建议。
提高精度的技巧:
- 使用更大的标定板(覆盖更多图像区域)
- 增加拍摄数量(20 张以上)
- 确保标定板绝对平整(弯曲会引入系统误差)
- 覆盖图像的边缘区域(畸变在边缘最大,需要更多约束)
- 使用高分辨率图像和精确的亚像素角点检测
- 固定光圈(改变光圈会轻微改变焦距)
常见问题:
- 重投影误差过大(>1 像素):检查标定板平整度、排除模糊图像、增加图像数量
- 角点检测失败:调整光照避免反光、确保对比度足够、检查棋盘格尺寸参数是否正确
- 校正后图像扭曲:可能是标定板尺寸参数错误或角点顺序不一致
在线标定:对于需要实时更新标定的场景(如温度变化导致焦距漂移),可以使用场景中的已知几何特征(如建筑物的直线)进行在线自标定。
高精度标定的补充要点:直射光与阴影会降低角点检测精度;使用 50 张以上图像可以获得统计上更稳定的估计;图案要覆盖到图像四角,只集中在中央会降低畸变系数的估计精度;若可以假设 fx = fy(正方形像素),用 cv2.CALIB_FIX_ASPECT_RATIO 标志添加约束。故障排查方面,重投影误差偏大(> 1.0px)的原因通常是图像模糊、图案不平整或角点检测错误。自动标定方面,SLAM(Simultaneous Localization and Mapping)系统会通过特征点的跟踪自动估计相机参数,即自标定;ORB-SLAM3 与 COLMAP 具备从场景中的自然特征点估计内参的功能。