从零到一:OAK相机标定背后的数学原理与视觉几何解密
在计算机视觉的世界里,相机标定是构建机器视觉系统的基石。无论是自动驾驶车辆的感知模块、工业机器人的精准定位,还是增强现实应用的虚实融合,都离不开精确的相机参数。OAK相机作为一款集成了深度计算能力的智能视觉设备,其标定过程不仅涉及传统相机的内参外参计算,更融合了立体视觉和神经网络加速的独特特性。理解这些参数背后的数学原理,就像掌握了一把打开三维视觉大门的钥匙,让我们能够将二维图像中的像素点准确地映射到真实世界的三维坐标中。
对于初学者而言,相机标定可能看起来像是一堆复杂矩阵和数学公式的堆砌。但实际上,每个参数都有其明确的物理意义和几何解释。本文将带你深入探索相机标定的数学本质,从最基本的针孔相机模型开始,逐步解析内参矩阵、畸变模型、外参变换的几何意义,并结合OAK相机的实际参数输出,让你不仅知道如何操作,更理解为什么需要这些参数以及它们如何影响最终的视觉感知效果。
1. 相机成像的几何基础:从三维世界到二维图像
相机标定的核心在于建立三维世界点与二维图像点之间的数学映射关系。这个过程可以用针孔相机模型来理解,这是一个简化但非常有效的模型。
在针孔相机模型中,光线从场景中的点通过一个小孔(光圈)投射到成像平面上。设三维空间中的点坐标为(X, Y, Z),其在图像平面上的投影坐标为(u, v),则根据相似三角形原理,我们可以得到以下关系:
u = f * X / Z + c_x
v = f * Y / Z + c_y
其中f是焦距,表示相机光学中心到成像平面的距离,(c_x, c_y)是主点坐标,通常位于图像中心。这个简单的模型为我们提供了相机成像的基本几何关系,但实际应用中我们需要用矩阵形式来表达这种变换,这就是内参矩阵的由来。
内参矩阵K将相机坐标系中的三维点转换到图像像素坐标系:
K = [[f_x, 0, c_x],
[0, f_y, c_y],
[0, 0, 1 ]]
这里的f_x和f_y分别表示x和y方向的焦距,以像素为单位。为什么会有两个不同的焦距值?这是因为相机传感器的像素可能不是完美的正方形,导致x和y方向的缩放因子略有不同。
提示:在实际的OAK相机标定结果中,你可能会看到类似
K: [1479.458984, 0.0, 950.694458, 0.0, 1477.587158, 530.697632, 0.0, 0.0, 1.0]的数据,这就是内参矩阵的扁平化表示,依次对应K[0,0], K[0,1], K[0,2], K[1,0], ... 直到K[2,2]。
2. 畸变模型:应对现实世界的光学缺陷
理想化的针孔模型在现实中会遇到各种光学畸变问题。透镜的物理特性会导致图像出现扭曲,主要表现为径向畸变和切向畸变两大类。
径向畸变是由透镜形状引起的,表现为图像点沿着径向方向的位移。它又可分为桶形畸变和枕形畸变:
- 桶形畸变:图像边缘向内弯曲,像桶的形状
- 枕形畸变:图像边缘向外弯曲,像枕头的形状
切向畸变则是由透镜制造和安装过程中的偏差引起的,表现为图像点沿着切向方向的位移。
为了校正这些畸变,我们使用畸变系数模型。最常用的是Brown-Conrady模型,使用5个参数(k1, k2, k3, p1, p2)来描述畸变:
x_corrected = x(1 + k1*r² + k2*r⁴ + k3*r⁶) + 2*p1*x*y + p2*(r² + 2*x²)
y_corrected = y(1 + k1*r² + k2*r⁴ + k3*r⁶) + p1*(r² + 2*y²) + 2*p2*x*y
其中r² = x² + y²,x和y是归一化的图像坐标(相对于主点)。
在OAK相机的标定输出中,畸变参数D可能包含多个值,如[-1.87286, 16.683033, 0.001053, -0.002063, 61.878521, -2.158907, 18.424637, 57.682858, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]。前5个通常对应k1, k2, p1, p2, k3,后续参数可能用于更复杂的畸变模型或保留位。
理解畸变模型的重要性在于,它让我们能够将实际拍摄的有畸变图像校正为符合针孔模型的无畸变图像,为后续的几何计算提供准确的基础。
3. 外参变换:多相机系统的空间关系
对于OAK这样的多相机系统,外参变换至关重要。外参描述了相机之间的相对位置和姿态关系,包括旋转和平移两部分。
旋转矩阵R是一个3×3的正交矩阵,表示从一个坐标系到另一个坐标系的旋转变换。它有以下特性:
- R是正交矩阵:RᵀR = I,其中I是单位矩阵
- 行列式|R| = 1,保证是纯旋转(无反射)
- 有3个自由度,通常用欧拉角或旋转向量表示
平移向量T是一个3×1的向量,表示从一个坐标系原点到另一个坐标系原点的位移。
外参变换将点从世界坐标系转换到相机坐标系:
[X_c] [R T] [X_w]
[Y_c] = [ ] [Y_w]
[Z_c] [0 1 ] [Z_w]
[1 ] [1 ]
在立体视觉系统中,如OAK相机的左右目相机,外参特别重要。它们定义了两个相机之间的基线距离和相对朝向,这是计算深度信息的基础。
OAK相机的外参标定结果通常以JSON格式存储,包含了每个相机相对于其他相机的位置和姿态信息:
{
"extrinsics": {
"to_cam": "CAM_C",
"specTranslation": {
"x": -7.5,
"y": 0,
"z": 0
},
"rotation": {
"r": 0,
"p": 0,
"y": 0
}
}
}
这个例子显示了一个相机相对于另一个相机的变换:x方向平移-7.5单位(可能是毫米或厘米),旋转角度均为0,表示两个相机只有水平方向的位移,这正是理想立体相机配置。
4. 标定方法比较:张正友法与ChArUco板方法
相机标定有多种方法,最著名的是张正友标定法(Zhang's method)和基于ChArUco板的方法。两者各有特点,适用于不同场景。
张正友标定法是传统且广泛使用的方法,使用简单的黑白棋盘格作为标定板。其主要优点包括:
- 只需要打印一张棋盘格图案,成本低廉
- 算法成熟,实现稳定
- 适用于大多数常规相机标定场景
标定过程包括多角度拍摄棋盘格图像,然后通过最小二乘法或最大似然估计优化相机参数。
ChArUco板结合了棋盘格和ArUco标记的优点,在棋盘格交点位置放置ArUco标记。这种方法在部分遮挡情况下仍能工作,因为即使部分标记被遮挡,其他标记仍能提供足够的对应点信息。
对于OAK相机,官方提供了专门的标定工具和脚本,支持多种标定模式:
python3 calibrate.py -s 2.75 -ms 2.05 -brd OAK-D -cd 0 -c 1 -mst 1
参数说明:
-s 2.75: 标定板上方格大小为2.75厘米-ms 2.05: 标记大小为2.05厘米-brd OAK-D: 设备板类型为OAK-D-cd 0: 拍摄照片前的倒计时为0秒-c 1: 每次显示多边形时拍摄1张照片-mst 1: 使用ChArUco标记
两种方法的数学本质都是通过已知的世界坐标点和对应的图像点,求解相机参数。这个过程可以表述为一个最小二乘优化问题,目标是使重投影误差最小化:
min Σ‖x_i - π(K, D, R, T, X_i)‖²
其中π是投影函数,将世界点X_i投影到图像平面,x_i是实际观测到的图像点。
5. OAK相机标定实战与参数解析
现在让我们结合OAK相机的实际标定输出,深入解析每个参数的实际意义和应用场景。
首先,通过ROS环境可以获取OAK相机的完整标定信息:
# 创建并构建depthai-ros工作空间
mkdir -p dai_ws/src
cd dai_ws/src
git clone https://gitee.com/oakchina/depthai-ros.git
cd ..
source /opt/ros/melodic/setup.bash
rosdep install --from-paths src --ignore-src -r -y
catkin_make
source devel/setup.bash
# 启动相机节点
roslaunch depthai_examples mobile_publisher.launch camera_model:=OAK-D
# 查看相机内参信息
rostopic echo -n 1 /mobilenet_publisher/color/camera_info
典型的OAK相机标定结果包含以下关键参数:
内参矩阵K:[1479.458984, 0.0, 950.694458, 0.0, 1477.587158, 530.697632, 0.0, 0.0, 1.0]
转换为矩阵形式:
K = [[1479.46, 0, 950.69],
[0, 1477.59, 530.70],
[0, 0, 1 ]]
这告诉我们:
- f_x = 1479.46像素,f_y = 1477.59像素(x和y方向焦距略有不同)
- 主点坐标(c_x, c_y) = (950.69, 530.70),接近图像中心(640, 360)但略有偏移
- skew系数为0,表示像素是矩形的
畸变参数D:[-1.87286, 16.683033, 0.001053, -0.002063, 61.878521, ...]
前5个参数对应:
- k1 = -1.87286(较大的负值表示较强的桶形畸变)
- k2 = 16.683033(正值补偿高阶畸变)
- p1 = 0.001053(较小的切向畸变)
- p2 = -0.002063(较小的切向畸变)
- k3 = 61.878521(非常大的正值,补偿高阶径向畸变)
旋转矩阵R:接近单位矩阵,表示相机坐标系与标定板坐标系之间的旋转很小
投影矩阵P:[1479.458984, 0.0, 950.694458, 0.0, 0.0, 1477.587158, 530.697632, 0.0, 0.0, 0.0, 1.0, 0.0]
P矩阵将三维点投影到图像平面,同时考虑了内参和外参。对于单目相机,P矩阵的最后一列通常为0,表示没有立体基线信息。
6. 标定质量评估与参数验证
完成标定后,如何评估标定质量至关重要。重投影误差是最直接的评估指标,它衡量的是标定板上的点通过相机模型投影到图像平面后,与实际检测到的点之间的差异。
重投影误差的计算公式为:
error = 1/N Σ‖x_i - π(K, D, R, T, X_i)‖
其中N是点的总数,x_i是实际图像点,π(...)是投影函数,X_i是对应的世界坐标点。
理想情况下,重投影误差应该小于0.5像素。如果误差过大,可能的原因包括:
- 标定板图像数量不足或角度分布不均匀
- 标定板检测算法出错
- 相机模型过于简单,无法描述实际光学特性
除了数值评估,可视化检查也很重要。可以将校正后的图像与原始图像对比,观察直线是否真的变直了;或者将标定板点的重投影位置叠加到原图像上,直观查看误差分布。
对于OAK相机的多相机系统,还需要检查相机之间外参的一致性。例如,左右目相机之间的基线距离应该与硬件设计值一致,旋转矩阵应该反映相机的实际相对朝向。
在实际项目中,我发现定期重新标定相机是保证视觉系统精度的关键。温度变化、机械振动甚至时间推移都可能影响相机参数。建立标定流程的标准化和自动化,能够大大提高视觉系统的维护效率和可靠性。
7. 标定参数的实际应用与优化策略
相机标定参数最终要服务于实际应用,如三维重建、物体测量、姿态估计等。了解如何正确使用这些参数至关重要。
去畸变处理是大多数视觉应用的第一步。使用OpenCV的undistort函数可以方便地校正图像畸变:
import cv2
import numpy as np
# 标定参数
K = np.array([[1479.46, 0, 950.69],
[0, 1477.59, 530.70],
[0, 0, 1]])
D = np.array([-1.87286, 16.683033, 0.001053, -0.002063, 61.878521])
# 读取图像
image = cv2.imread("oak_image.jpg")
h, w = image.shape[:2]
# 计算最优新相机矩阵和ROI
new_K, roi = cv2.getOptimalNewCameraMatrix(K, D, (w, h), 1, (w, h))
# 校正图像
undistorted = cv2.undistort(image, K, D, None, new_K)
# 裁剪图像
x, y, w, h = roi
undistorted = undistorted[y:y+h, x:x+w]
三维重建需要同时使用内参和外参。对于立体视觉系统,首先使用内参去畸变和校正图像,然后计算视差图,最后通过三角测量得到深度信息:
# 立体校正
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(
left_K, left_D, right_K, right_D, image_size, R, T)
# 创建校正映射
left_map1, left_map2 = cv2.initUndistortRectifyMap(
left_K, left_D, R1, P1, image_size, cv2.CV_16SC2)
right_map1, right_map2 = cv2.initUndistortRectifyMap(
right_K, right_D, R2, P2, image_size, cv2.CV_16SC2)
# 应用校正映射
left_rectified = cv2.remap(left_image, left_map1, left_map2, cv2.INTER_LINEAR)
right_rectified = cv2.remap(right_image, right_map1, right_map2, cv2.INTER_LINEAR)
# 计算视差图
stereo = cv2.StereoSGBM_create(minDisparity, numDisparities, blockSize)
disparity = stereo.compute(left_rectified, right_rectified)
# 转换为深度图
depth = cv2.reprojectImageTo3D(disparity, Q)
参数优化是一个持续的过程。在实际使用中,可以考虑以下策略:
- 多条件标定:在不同光照、温度条件下分别标定,建立参数与环境的关系模型
- 在线标定:对于长期运行的系统,实现周期性自动标定或在线标定
- 参数插值:对于变焦相机,在不同焦距下标定,使用时根据当前焦距插值计算参数
- 模型扩展:对于高端应用,考虑使用更复杂的相机模型,如鱼眼模型或全光学模型
OAK相机作为硬件加速的视觉平台,其标定参数可以直接加载到设备上,在图像数据输出前就完成校正和深度计算,大大减轻主机处理负担。这种设计使得OAK相机在嵌入式系统和实时应用中具有显著优势。
理解相机标定的数学原理不仅有助于正确使用标定参数,还能在参数异常时快速定位问题根源,在系统设计时做出更合理的权衡。无论是选择标定方法、评估标定质量,还是在实际应用中有效利用标定结果,深厚的理论基础都是不可替代的。
1062



被折叠的 条评论
为什么被折叠?



