相机标定是计算机视觉和机器视觉领域中的一个基础性任务,其主要目标是建立三维世界坐标系与二维图像坐标系之间的几何映射关系。通过标定可以获取相机的内部参数(如焦距、主点坐标、畸变系数等)和外部参数(相机相对于世界坐标系的位置和方向),从而为图像测量、三维重建、目标跟踪等任务提供准确的数学模型支持。
### 工作原理
相机成像的基本模型是一个透视投影模型,即针孔相机模型。该模型将三维空间中的点通过线性变换投影到二维图像平面上。在理想情况下,这种变换由相机的内参矩阵和外参矩阵共同决定。其中:
- **内参矩阵**包括焦距(fx, fy)、主点坐标(cx, cy)以及可能存在的畸变参数(如径向畸变、切向畸变等)。
- **外参矩阵**描述了相机在世界坐标系中的位置和姿态,通常由旋转矩阵R和平移向量T表示[^2]。
由于实际相机镜头存在制造误差或光学特性限制,导致图像出现畸变现象(如桶形畸变、枕形畸变等)。因此,在标定过程中还需估计这些畸变参数,以提高图像校正精度。
### 实施步骤
相机标定的具体实施流程通常包括以下几个关键步骤:
#### 1. 准备标定物
使用已知结构的标定板(如棋盘格图案),并将其固定在一个平面上作为标定对象。棋盘格因其角点易于检测且分布规则而被广泛采用[^3]。
#### 2. 图像采集
从不同角度拍摄多张标定板图像(建议至少10张以上),确保覆盖不同的旋转和平移状态。这样有助于提高标定结果的鲁棒性和准确性[^4]。
#### 3. 特征提取
对每张图像进行预处理后,利用算法自动检测并提取棋盘格角点的像素坐标。OpenCV等视觉库提供了高效的角点检测函数(如`findChessboardCorners`),可快速定位角点位置。为了进一步提升精度,还可以使用亚像素级角点优化方法(如`cornerSubPix`)[^4]。
#### 4. 参数估算
基于提取出的角点坐标数据,结合已知的标定板物理尺寸,构建方程组来求解相机的内参和外参。常见的标定方法有直接线性变换(DLT)、张正友平面标定法等。其中,张正友方法因其操作简便且精度较高,在实践中应用较为广泛。该方法首先忽略畸变影响,初步估算五个内参和六个外参;随后引入最小二乘法计算径向畸变系数,并通过极大似然法进一步优化所有参数,以获得更精确的结果[^3]。
#### 5. 畸变校正
根据标定得到的畸变参数,对原始图像进行去畸变处理。这一步骤可通过调用OpenCV中的`undistort`函数实现,输入原始图像及标定所得的相机矩阵和畸变系数即可输出校正后的图像[^4]。
#### 6. 标定验证
最后,应对标定结果进行验证,检查重投影误差是否在可接受范围内。重投影误差是指将三维世界点重新投影回图像平面时,其理论位置与实际检测到的角点位置之间的差异。若误差较大,则需重新调整拍摄条件或改进特征提取过程,直至满足精度要求[^2]。
### 示例代码:使用OpenCV进行相机标定
以下是一个简单的Python示例,展示如何使用OpenCV库执行相机标定任务:
```python
import cv2
import numpy as np
import glob
# 棋盘格尺寸 (列数 x 行数)
chessboard_size = (9, 6)
# 准备对象点,如 (0,0,0), (1,0,0), ..., (8,5,0)
objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
# 存储对象点和图像点的列表
objpoints = [] # 3D点
imgpoints = [] # 2D点
images = glob.glob('calibration_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:
objpoints.append(objp)
# 细化角点位置
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints.append(corners2)
# 绘制并显示找到的角点
cv2.drawChessboardCorners(img, chessboard_size, corners2, ret)
cv2.imshow('img', img)
cv2.waitKey(500)
cv2.destroyAllWindows()
# 相机标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# 输出相机矩阵和畸变系数
print("Camera Matrix:\n", mtx)
print("\nDistortion Coefficients:\n", dist)
# 对图像进行畸变校正
img = cv2.imread('calibration_images/left12.jpg')
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
# 使用remap进行校正
mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w, h), 5)
dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
# 显示校正结果
cv2.imshow('calibresult', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
上述代码展示了完整的标定流程,包括角点检测、参数估计、畸变校正等功能。用户可根据实际需求修改相关参数,并扩展至更多应用场景中。
---