相机标定在自动驾驶中的作用、标定方法详解及代码说明
在自动驾驶系统中,相机是核心传感器之一,用于实时捕捉环境图像(如车道线、行人、车辆等)。相机标定是确定相机内参(如焦距、主点)和外参(如相机相对于车辆坐标系的位置和方向)的过程。其作用至关重要:
- 环境感知的准确性:通过标定,可以将图像像素坐标转换为真实世界坐标,实现精确的距离测量和目标定位。例如,估算前方车辆的距离或检测车道宽度。
- 传感器融合的基础:自动驾驶系统通常融合相机、LiDAR和雷达数据。相机标定提供坐标转换参数,确保多传感器数据对齐,提高感知可靠性。
- 畸变校正:相机镜头可能引入径向或切向畸变,标定后能校正图像,避免误检(如弯曲的车道线)。
- 实时决策支持:标定后的相机数据用于路径规划和避障算法,提升系统安全性和鲁棒性。
下面,我将分步骤详细说明相机标定的步骤和方法,并提供一个Python代码示例。标定方法基于张正友标定法(Zhang's method),这是一种广泛使用的技术,使用棋盘格图案进行标定。整个过程分为6个步骤。
相机标定步骤和方法详解
相机标定包括内参标定(相机自身特性)和外参标定(相机姿态)。标准步骤如下:
-
准备标定板:
- 方法:使用已知尺寸的棋盘格图案(如黑白方格),尺寸需精确测量(例如,每个方格边长ddd)。棋盘格应平整,避免反光。
- 原理:棋盘格的角点(corners)提供已知的世界坐标点,用于建立图像坐标到世界坐标的映射。世界坐标系通常定义在棋盘格平面上(Z=0Z=0Z=0),原点在棋盘格一角。
- 关键点:采集多张图像(至少10-20张),覆盖相机视场不同位置和角度,确保标定鲁棒性。
-
采集图像:
- 方法:将标定板置于相机视场中,从不同视角(平移、旋转)拍摄多张图像。确保图像清晰,棋盘格完整可见。
- 原理:每张图像对应一个姿态,提供多个点对(图像点(u,v)(u,v)(u,v)和世界点(X,Y,0)(X,Y,0)(X,Y,0)),用于求解相机参数。
- 数学基础:相机投影模型为:
s[uv1]=K[Rt][XY01] s \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = K \begin{bmatrix} R & t \end{bmatrix} \begin{bmatrix} X \\ Y \\ 0 \\ 1 \end{bmatrix} s uv1 =K[Rt] XY01
其中sss是尺度因子,KKK是内参矩阵(含焦距fx,fyf_x, f_yfx,fy和主点cx,cyc_x, c_ycx,cy),RRR和ttt是旋转矩阵和平移向量(外参),(X,Y)(X,Y)(X,Y)是世界坐标。
-
检测角点:
- 方法:在每张图像中自动检测棋盘格角点。常用算法如Harris角点检测或OpenCV的优化方法。
- 原理:角点坐标用于构建点对应关系。例如,图像点(u,v)(u,v)(u,v)对应世界点(X,Y,0)(X,Y,0)(X,Y,0),其中XXX和YYY以方格尺寸ddd为单位(如点(i,j)(i,j)(i,j)对应X=i⋅dX=i \cdot dX=i⋅d, Y=j⋅dY=j \cdot dY=j⋅d)。
- 关键点:需精确亚像素级定位,减少误差。使用迭代优化提高精度。
-
计算内参和畸变系数:
- 方法:基于所有图像的角点数据,求解内参矩阵KKK和畸变系数(径向k1,k2,k3k_1, k_2, k_3k1,k2,k3和切向p1,p2p_1, p_2p1,p2)。使用最小二乘法优化。
- 原理:通过Homography矩阵估计初始KKK,然后迭代优化。目标是最小化重投影误差:
min∑i∑j∥pij−p^ij∥2 \min \sum_{i} \sum_{j} \| p_{ij} - \hat{p}{ij} \|^2 mini∑j∑∥pij−p^ij∥2
其中pijp{ij}pij是检测到的角点,p^ij\hat{p}_{ij}p^ij是投影点。 - 关键点:内参包括K=[fx0cx0fycy001]K = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix}K= fx000fy0cxcy1 ,畸变系数用于校正图像。
-
计算外参(可选但自动驾驶中关键):
-
方法:在自动驾驶中,外参标定确定相机相对于车辆坐标系(如车体中心)的位姿。使用已知世界点(如标定板在车辆上的固定位置)求解RRR和ttt。
-
原理:基于PnP(Perspective-n-Point)算法,如OpenCV的
solvePnP
函数。输入内参和点对,输出旋转向量和平移向量。 -
数学:外参将相机坐标转换到车辆坐标:
XcYcZc\]=R\[XvYvZv\]+t \\begin{bmatrix} X_c \\\\ Y_c \\\\ Z_c \\end{bmatrix} = R \\begin{bmatrix} X_v \\\\ Y_v \\\\ Z_v \\end{bmatrix} + t XcYcZc =R XvYvZv +t 其中(Xv,Yv,Zv)(X_v, Y_v, Z_v)(Xv,Yv,Zv)是车辆坐标。
-
方法:计算重投影误差(平均像素误差),理想值应小于0.5像素。使用测试图像验证畸变校正效果。
-
原理:通过标定参数重新投影角点,比较与原图像的偏差。高误差表明标定失败,需重新采集图像。
-
关键点:在自动驾驶中,还需实车测试(如测量已知距离物体的误差)。
-
代码举例说明
以下是一个Python代码示例,使用OpenCV库实现相机内参标定(包括畸变校正)。代码基于张正友方法,适用于单个相机。假设已有棋盘格图像集(存储在images/
目录)。代码步骤对应上述方法。
python
import cv2
import numpy as np
import glob
# 步骤1: 准备参数
chessboard_size = (9, 6) # 棋盘格内角点数量 (width, height)
square_size = 0.025 # 每个方格边长 (单位:米)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 步骤2: 准备世界坐标点 (假设棋盘格在Z=0平面)
obj_points = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
obj_points[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) * square_size
# 存储所有图像的点对应
obj_points_list = [] # 世界点
img_points_list = [] # 图像点
# 步骤3: 加载图像并检测角点
images = glob.glob('images/*.jpg') # 假设图像路径
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 查找角点
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
if ret:
obj_points_list.append(obj_points)
# 亚像素优化
corners_refined = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
img_points_list.append(corners_refined)
# 步骤4: 计算内参和畸变系数
ret, K, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(
obj_points_list, img_points_list, gray.shape[::-1], None, None
)
# 输出结果
print("内参矩阵 K:\n", K)
print("畸变系数:", dist_coeffs.flatten())
# 步骤5: 验证 (示例: 校正一张测试图像)
test_img = cv2.imread('images/test.jpg')
h, w = test_img.shape[:2]
new_K, roi = cv2.getOptimalNewCameraMatrix(K, dist_coeffs, (w,h), 1, (w,h))
undistorted_img = cv2.undistort(test_img, K, dist_coeffs, None, new_K)
# 保存或显示结果
cv2.imwrite('undistorted.jpg', undistorted_img)
print("标定完成!重投影误差:", ret) # ret 是平均误差
代码解释:
- 输入 :需要一组棋盘格图像(存储在
images/
目录),每个图像包含完整棋盘格。chessboard_size
是内角点数(如9x6),square_size
是物理尺寸(单位米)。 - 输出 :内参矩阵KKK(包含fx,fy,cx,cyf_x, f_y, c_x, c_yfx,fy,cx,cy)和畸变系数,用于后续图像校正。
- 关键函数 :
cv2.findChessboardCorners
:检测角点。cv2.cornerSubPix
:提高角点精度。cv2.calibrateCamera
:计算相机参数。cv2.undistort
:应用畸变校正。
- 注意事项 :实际自动驾驶中,需扩展外参标定(使用
solvePnP
),并集成到感知模块。代码需在真实环境中测试。
总结
相机标定是自动驾驶感知系统的基石,确保图像数据准确映射到真实世界。通过上述步骤(准备标定板、采集图像、检测角点、计算参数、验证结果),结合代码示例,您可以实现可靠的标定。在实际应用中,建议使用专业工具(如ROS或MATLAB标定工具箱)并定期重新标定以适应硬件变化。如果您有特定场景问题,我可以进一步优化解释!