4. 相机模型与标定基础
在无人机 AprilTag 视觉定位与降落系统中,相机是唯一的“眼睛”。如果相机模型不准确,即使 AprilTag 检测算法再稳定,解算出的位姿也会出现系统性偏差,最终导致降落点漂移甚至失败。本节从针孔相机模型出发,逐步建立内参、外参、畸变模型的概念,并给出张正友标定法的完整实操流程。
一、针孔相机模型:三维到二维的投影
针孔相机模型是最常用的成像近似模型。它假设光线从物体表面出发,穿过一个理想的小孔,在成像平面上形成倒立的像。在数学上,我们通常把成像平面放在光心前方,得到正立的像,便于计算。
设空间中一点 P = (X, Y, Z) 位于相机坐标系下,其投影到像素平面的坐标为 (u, v),则投影关系为:
u = fx * (X / Z) + cx
v = fy * (Y / Z) + cy
其中 fx、fy 是以像素为单位的焦距,cx、cy 是主点坐标。写成矩阵形式:
[u] [fx 0 cx] [X/Z]
[v] = [0 fy cy] [Y/Z]
[1] [0 0 1] [ 1 ]
这个 3×3 矩阵就是相机的内参矩阵 K。它只与相机自身结构有关,与相机在空间中的位置和姿态无关。
二、内参与外参:相机位姿的完整描述
内参描述“相机如何把光线映射成像素”,外参描述“相机在世界坐标系中的位置和朝向”。世界坐标系下一点 Pw 投影到像素的完整过程为:
p = K * [R | t] * Pw
其中 R 是 3×3 旋转矩阵,t 是 3×1 平移向量,合称外参。在无人机降落场景中,AprilTag 固定在降落平台上,相机随无人机运动,外参就是我们需要实时估计的位姿。内参一旦标定完成,通常在整个飞行任务中保持不变。
三、畸变模型:真实镜头的偏差
真实镜头并非理想针孔,广角镜头尤其明显。常见畸变包括径向畸变和切向畸变。径向畸变使直线向外弯曲(桶形)或向内弯曲(枕形),切向畸变由镜头与成像平面不平行引起。
OpenCV 常用畸变系数为 k1, k2, p1, p2, k3。去畸变公式可简化为:
x_distorted = x(1 + k1*r^2 + k2*r^4 + k3*r^6) + 2*p1*x*y + p2*(r^2 + 2*x^2)
y_distorted = y(1 + k1*r^2 + k2*r^4 + k3*r^6) + p1*(r^2 + 2*y^2) + 2*p2*x*y
对于无人机视觉定位,建议使用畸变较小的镜头,并在标定后启用去畸变,否则 Tag 边缘会被拉伸,角点检测精度下降。
四、张正友标定法:从棋盘格到内参
张正友标定法使用平面棋盘格,在多个不同姿态下拍摄图像,利用棋盘格角点的已知世界坐标与检测到的像素坐标之间的对应关系,求解内参和畸变系数。其核心步骤为:
- 打印棋盘格标定板,固定在平整表面。
- 从不同角度、距离拍摄 15~25 张图像,覆盖画面各个区域。
- 检测每张图中的棋盘格角点。
- 构建单应矩阵,求解内参初值。
- 考虑畸变,进行非线性优化,得到最终内参和畸变系数。
- 计算重投影误差,评估标定质量。
重投影误差是衡量标定好坏的关键指标。通常要求平均重投影误差小于 0.5 像素,若大于 1 像素,说明图像质量差、角点检测不准或标定板姿态覆盖不足。
五、标定实操:OpenCV 代码与参数
以下为使用 OpenCV 进行相机标定的核心代码片段:
import cv2
import numpy as np
# 棋盘格内角点数量,例如 9x6
pattern_size = (9, 6)
objp = np.zeros((pattern_size[0]*pattern_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)
objpoints = [] # 3D 点
imgpoints = [] # 2D 点
images = ["calib_01.jpg", "calib_02.jpg", "calib_03.jpg"]
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)
if ret:
objpoints.append(objp)
corners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1),
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001))
imgpoints.append(corners2)
ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(
objpoints, imgpoints, gray.shape[::-1], None, None)
print("内参矩阵 K:\n", K)
print("畸变系数 dist:\n", dist)
标定完成后,将 K 和 dist 保存为 YAML 或 JSON 文件,供 AprilTag 检测与位姿解算使用。在无人机上,建议使用全局快门相机,避免卷帘快门在运动过程中造成几何畸变。
六、标定质量检查与常见误区
| 检查项 | 合格标准 | 常见问题 |
|---|---|---|
| 重投影误差 | < 0.5 像素 | 角点检测不准、图像模糊 |
| 标定图像数量 | 15~25 张 | 过少导致参数不稳定 |
| 姿态覆盖 | 倾斜、旋转、远近均有 | 只拍正面,畸变参数不准 |
| 标定板平整度 | 平面误差 < 0.1 mm | 打印纸弯曲,角点坐标失真 |
| 焦距一致性 | fx ≈ fy | 像素非方形或图像被裁剪 |
七、场景案例:AprilTag 降落中的标定影响
假设无人机在 3 米高度检测到 AprilTag,Tag 实际边长为 0.16 米。若焦距标定误差为 5%,则解算出的高度误差约为 0.15 米,水平位置误差也会同比放大。在最后 0.5 米降落阶段,这种误差可能导致无人机偏离平台边缘。因此,标定不是“一次性任务”,而是视觉定位精度的地基。
建议在每次更换相机、调整焦距、改变分辨率后,重新执行张正友标定,并记录重投影误差。将标定文件与飞行日志一起归档,便于问题复现与精度复盘。
总结来看,针孔模型给出投影骨架,内参决定像素映射,外参描述相机位姿,畸变模型修正真实镜头偏差,张正友标定法把这一切从理论变成可执行的参数。只有把标定做扎实,AprilTag 检测与降落控制才有可靠的输入。