过年拍全家福,十几口人站成扇形,一位摄影师根本拍不全。于是请来六位摄影师,每人负责一段,从左到右把所有人完整收进镜头。回家拼照片时却发现:左边和中间的照片都拍到了二舅,但二舅的胳膊在左边照片里偏上、在中间照片里偏下;最左边和最右边的接缝处,连背景窗帘都错开了。为什么?因为每位摄影师的站位、镜头朝向、焦距各不相同,拍出的照片天然不在同一个“坐标系”里。要让六张照片严丝合缝,必须搞清楚每位摄影师:站在哪(位置)、脸朝哪(朝向)、镜头焦距多少(内参)——这就是标定。若大家各拍各的,拼出来就是歪扭的怪图;精确标定后再做联合微调,就能得到一张天衣无缝的全家福。这正是多相机标定要解决的全部问题。
多相机标定是自动驾驶环视、机器人感知与三维重建的“地基工程”。掌握它,你就拿到了让多个传感器协同工作的核心钥匙,是感知与定位岗位的必备技能。
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
多相机标定概述
导演要请六位摄影师合力拍一张全家福,第一步不是按快门,而是给每个人建档:你站在哪里、镜头朝向哪个方向、焦距调到多少、画面中心对准哪。这份“摄影师档案”对应到相机,就是外参(位置与朝向)和内参(焦距与主点)。多相机标定要做的,就是把每台相机的内外参精确估计出来,让所有相机共享同一个世界坐标系,拼出的图才不会错位。
相机的内参矩阵 \(K\) 只与镜头和感光芯片有关,决定了三维空间点如何投影成图像像素,相当于摄影师的镜头体质。外参 \(R\) 和 \(t\) 描述相机在世界坐标中的旋转与平移,\(R\) 是摄影师的转身角度,\(t\) 是摄影师的站位偏移。常见的多相机系统有三种构型:双目像两位摄影师一左一右拍同一场景;环视像六位摄影师背靠背围成一圈;阵列像摄影棚里一排相机同时拍摄。标定的目标,就是让同一个三维点在所有相机图像中的投影位置和真实观测位置完全一致,这一关系由相机投影模型描述。
建档完成后,导演手里有六份精确的摄影师档案,拼图工程已经成功了一半——剩下的工作,就是让这些档案在真实拍摄中经得起考验。
- 三维点 \(\tilde{X}\)世界坐标系里的一个空间点,比如全家福里二舅的鼻尖。
- 外参 \([R \ t]\)把世界坐标转换到相机坐标。\(R\) 是旋转(摄影师转身角度),\(t\) 是平移(摄影师站位)。
- 内参 \(K\)把相机坐标投影到像素平面,包含焦距 \(f_x, f_y\) 和主点 \(c_x, c_y\)。
- 像素点 \(\tilde{x}\)最终图像上的像素齐次坐标。
标定策略设计
正式开拍前先彩排:把一块黑白相间的棋盘格立在大厅中央,让每位摄影师从不同远近、不同角度各拍二十来张。这块棋盘格就是标定板,它是所有相机共同的“参照物”。多相机标定的策略设计,本质上就是设计这场彩排:用什么板、怎么拍、拍多少、哪些照片要扔掉。
首先是标定板选择。棋盘格和圆点阵列最常用,因为它们有大量精确可检测的角点,且图案刚性稳定,不会像纸片在潮湿空气中那样扭曲。其次是采集流程:每个相机要拍 10~30 张,覆盖不同距离、不同倾角。特别要注意覆盖要求——标定板不能只出现在画面中央,还要出现在视场边缘和四角,否则镜头边缘的畸变参数完全没有数据支撑,拼接处会像照片四周的桶形变形一样弯曲。最后是误差控制:模糊、过曝、强反光的照片直接删除,它们会让角点检测偏移几个像素,污染整个标定结果。
单相机标定中,标定板平面到图像平面的映射由一个单应矩阵 \(H\) 描述,它把外参的旋转列向量 \(r_1, r_2\) 与平移 \(t\) 一起编码进来。
彩排结束,导演手里攒下几百张标定照片。接下来要做的事,就像拿到照片后找出“两张照片里的二舅是不是同一个人”——这正是重叠区域匹配要解决的难题。
- 标定板点 \(\tilde{X}_{board}\)标定板平面上的点,令其 \(Z=0\) 来简化模型。
- 单应矩阵 \(H\)平面到图像的一一映射,由内参 \(K\) 与外参的前两列旋转 \(r_1, r_2\) 和平移 \(t\) 组成。
- 缩放因子 \(s\)齐次坐标里的缩放量,用于把结果归一化到真实像素坐标。
重叠区域匹配
六位摄影师的照片要拼成一张,前提是相邻两张照片必须拍到同一个人或同一件物体。这个公共区域叫视场重叠。如果两位摄影师完全各拍各的、没有任何重叠,他们的照片就失去了对齐的锚点——相当于拼图缺少了连接块。因此,布设相机时第一件事就是保证相邻相机的视场有足够重叠。
有了重叠区域,接下来要找“同名点”:左边照片里的二舅鼻尖,和中间照片里的二舅鼻尖,必须是同一个物理点。做法是先在每张图像上提取特征(角点、斑点等显著结构),并为每个特征生成一串“身份证号”——描述子。两个描述子越相似,越可能是同一个三维点的投影。这个相似度用距离来衡量,通常取欧氏距离:
不过只看“长得像”还不够——照片里可能有两位长得很像的亲戚。这时就要用 RANSAC 等几何校验方法,根据相机之间的极线约束把误匹配成对剔除掉。找到足够的可靠同名点后,所有连接相机的“桥梁”就搭好了,接下来就是最关键的全局微调。
- 描述子 \(D_i\)相机一图像中某个特征点的描述子向量,相当于一张脸的“特征清单”。
- 描述子 \(D_j\)相机二图像中候选匹配点的描述子向量。
- 欧氏距离逐维度求差平方、求和、开根号,衡量两个向量“像不像”。
- 匹配判定距离小于阈值就认为是同名点,否则丢弃。
全局捆绑调整(Bundle Adjustment)
六张照片铺在大桌上,接缝处仍有毫米级错位。导演喊了一声“一起微调”:一号摄影师往左挪半步,三号镜头右转一度,五号焦距微调一点点……每个人都只动一点,直到所有接缝都完美闭合。这个“所有人一起微调”的过程,就是 Bundle Adjustment(捆绑调整,简称 BA)。"Bundle" 指的是从所有相机光心射向所有三维点的光线束,调整就是让这些光线束在三维空间中精确交会。
BA 的核心是误差模型——重投影误差:把三维点用当前的内外参投影到图像上,得到“预测像素位置”,再和实际检测到的像素位置比较,差异就是误差。优化变量包括所有相机内参 \(K_i\)、外参 \(R_i, t_i\) 以及所有三维点 \(X_j\)。损失函数通常用平方误差并配合鲁棒核函数 \(\rho\)(如 Huber 核),让误匹配的离群点不至于把优化结果带偏。迭代收敛后,接缝处的错位被均匀分摊到所有相机上,整个环闭合了。
微调完毕,导演一声“收工”,全家福的所有接缝都对上了。但现场拍摄的规矩和日后的维护,同样决定这张照片能完美多久。
- 下标 \(i, j\)\(i\) 是第 \(i\) 个相机,\(j\) 是第 \(j\) 个三维点。
- 投影函数 \(\pi\)把三维点 \(X_j\) 用相机 \(i\) 的内外参投影到图像平面。
- 重投影误差观测像素位置与投影像素位置之差,这是优化的“裁判”。
- 鲁棒核 \(\rho\)对误差做非线性缩放,削弱误匹配(离群点)的影响。
- 双重求和与最小化遍历所有相机的所有可见点,把所有误差加起来,在所有参数上求最小。
工程实践要点
拍全家福的现场有很多规矩:三脚架必须锁紧、灯光要稳定不闪烁、光滑的地板要铺上防反光垫。多相机标定的工程实践,同样是一套关于“现场纪律”的经验。
首先是标定环境:相机要固定在刚性支架上,标定过程中不能有任何震动;标定板的材料要选刚性好的,比如陶瓷或玻璃基板,避免纸张变形。其次是光照控制,这是新手最容易翻车的地方:光照不均匀会让标定板角点检测偏移,强反光会让圆点阵列“凭空消失”,所以要用均匀光源并避免高反光表面。鲁棒性方面,要采集多组样本、剔除坏帧,并做交叉验证——留出部分图像不参与优化,看误差是否反弹。最后是重标定时机:相机一旦拆装、经历剧烈温差或碰撞,外参就会漂移,必须重新标定,就像全家福拍完几年后家庭成员变了,得重新组织拍摄。
判断标定质量,最常用的指标是重投影误差的均方根(RMS):
把现场的规矩都做到位,标定结果才稳定可靠。最后的悬念是:这张完美全家福,到底能用来干什么?
- 单点误差 \(e_i\)第 \(i\) 个角点的检测位置与投影位置之间的向量长度。
- 平方平均把所有误差平方后求平均,放大大误差的权重。
- 开根号得到与像素同量纲的 RMS 值,方便设定阈值。
- 阈值判定\(e_{RMS} < 0.5\) 像素认为合格,否则需要重新采集或检查标定板。
应用案例
一张天衣无缝的全家福,可以印成挂历、裱成横轴、剪成拜年视频。多相机标定的成果同样支撑着一大批上层应用,每一个都离不开“坐标系对齐”这个地基。
最直接的应用是全景拼接。车载环视系统用 4~8 个鱼眼相机围成一圈,标定后把各自画面投影到统一的地面平面上,形成车辆周围 360 度的俯视全景图,倒车入库时一眼看清所有障碍物。第二类是立体视觉:双目相机标定后,同一物体在左右图像上的像素差异叫视差,视差越大物体越近。深度由下面这个简洁的公式给出:
第三类应用是 SLAM 初始化:多目相机在启动瞬间就能从多个视角同时观测到足够多的特征点,一次性三角化出可靠的地图点,比单目相机需要“先动起来才能建图”快得多,也更稳健。从全景影像到三维重建,多相机标定就像全家福那根看不见的“缝线”,把每一帧画面牢牢缝在一起。
- 焦距 \(f\)以像素为单位的镜头焦距。
- 基线 \(b\)左右相机光心之间的距离,相当于两只眼睛的距离。
- 视差 \(d\)同名点在左右图像上的横坐标之差。
- 深度 \(Z\)逆推得到的物距,视差越大,物体越近。
AI 应用场景
自动驾驶环视感知系统
阶段:感知与定位
解决的问题:传统方式依赖单颗前视摄像头,存在大面积盲区,倒车和窄路会车时极易刮蹭。AI 环视方案用 4 颗鱼眼相机覆盖车身四周,但若相机外参不准,拼接出的俯视图会出现车辆“错位分身”,反而误导驾驶员。多相机标定让所有鱼眼画面精确对齐到车身坐标系,生成无缝 360° 鸟瞰图,再交给 BEV(鸟瞰视角)感知模型做障碍物检测。
具体案例:某量产车型在自动泊车功能开发中,发现右后视镜相机在颠簸路试后外参漂移了 0.8°,导致泊车路径偏差 12 厘米。工程师用标定间内的棋盘格靶标重新标定全部四颗相机,再以全局 BA 将环闭合,泊车精度恢复到 3 厘米以内。
虚拟制作影棚多相机阵列
阶段:三维重建与渲染
解决的问题:电影虚拟制作需要几十台相机同步拍摄演员,实时重建人体三维模型。每台相机只有标定准确,重建出的点云才能“长”在演员身上,而不是飘在空中。多相机标定提供每个相机的内外参,后续的神经渲染(NeRF 类方法)才能把多视角图像编码到同一空间。
具体案例:某虚拟摄影棚布设 36 台同步相机,标定后发现外围相机重投影误差高达 2.3 像素,重建的人脸出现“果冻抖动”。团队重新采集 40 组标定板数据,覆盖视场边缘,并用全局 BA 联合优化 36 台相机外参,误差降至 0.4 像素,重建结果稳定清晰。
机器人手眼与多目协作标定
阶段:机器人感知与控制
解决的问题:机械臂要抓取一个杯子,需要知道“相机看见的杯子”在机器人坐标系里的准确位置。多相机标定不仅包括相机间标定,还包括相机与机械臂基座的坐标变换。标定后用重投影误差评估整体精度,避免抓取时“眼睛看到的”和“手摸到的”对不上。
具体案例:3C 装配产线上,两台工业相机从不同角度引导机械臂插接排线。由于产线换型频繁,相机被反复拆装,每次换型后 5 分钟即可用内置标定板完成自动重标定,将插接成功率从 91% 提升到 99.6%。
Python 演示
import numpy as npfrom scipy.optimize import least_squares def project(X, R, t, K): """Project a 3D point to pixel coordinates.""" cam = R @ X + t pix = K @ (cam / cam[2]) return pix[:2] def euler_rotation(vec): """Build rotation matrix from Euler angles.""" rx, ry, rz = vec Rx = np.array([[1.0, 0.0, 0.0], [0.0, np.cos(rx), -np.sin(rx)], [0.0, np.sin(rx), np.cos(rx)]]) Ry = np.array([[np.cos(ry), 0.0, np.sin(ry)], [0.0, 1.0, 0.0], [-np.sin(ry), 0.0, np.cos(ry)]]) Rz = np.array([[np.cos(rz), -np.sin(rz), 0.0], [np.sin(rz), np.cos(rz), 0.0], [0.0, 0.0, 1.0]]) return Rz @ Ry @ Rx K = np.array([[600.0, 0.0, 320.0], [0.0, 600.0, 240.0], [0.0, 0.0, 1.0]])delta_gt = np.array([0.0, 0.045, 0.0, 0.5, 0.0, 0.0])R_gt = euler_rotation(delta_gt[:3])t_gt = delta_gt[3:] rng = np.random.default_rng(7)world_pts = rng.uniform(-1.0, 1.0, (20, 3))world_pts[:, 2] += 3.0obs2 = np.array([project(X, R_gt, t_gt, K) + rng.normal(0.0, 0.5, 2) for X in world_pts]) def residuals(delta): R = euler_rotation(delta[:3]) t = delta[3:] err = [] for X, p in zip(world_pts, obs2): err.extend(project(X, R, t, K) - p) return np.array(err) coarse = delta_gt + rng.normal(0.0, 0.05, 6)err_before = np.mean(np.abs(residuals(coarse)))result = least_squares(residuals, coarse, method='lm')err_after = np.mean(np.abs(residuals(result.x))) print('粗标定平均重投影误差: %.3f px' % err_before)print('BA 优化后平均重投影误差: %.3f px' % err_after)
pix = K @ (cam / cam[2])把相机坐标除以深度得到归一化坐标,再乘内参得到像素坐标,这是投影模型的核心一行。def euler_rotation(vec)用三个欧拉角构造旋转矩阵,让优化参数只有 6 维(3 旋转 + 3 平移)。world_pts[:, 2] += 3.0把随机三维点放到相机前方 3 米处,模拟真实的标定板角点分布。obs2 = ... + rng.normal(0.0, 0.5, 2)给相机二的观测加上 0.5 像素的高斯噪声,模拟真实检测误差。def residuals(delta)计算每个点投影位置与观测位置的差,这正是 BA 的“裁判”——重投影误差。least_squares(residuals, coarse, method='lm')用 Levenberg-Marquardt 算法最小化残差,是全局 BA 的经典求解器。err_before` 与 `err_after优化前粗标定误差大,优化后误差逼近噪声水平,直观展现 BA 的威力。
常见误区
误区总觉得相机装好、标定做完,这个结果就能永远用下去,之后只要不换镜头就万事大吉。
正解外参会随时间漂移。汽车颠簸、机械臂长期运动、热胀冷缩都会让相机位置发生微小变化,0.5° 的旋转偏差在 5 米处就能带来 4 厘米的投影误差。工程上必须设计定期重标定机制,条件允许时要做在线自标定,用现场的静止特征持续修正外参。就像全家福拍完过几年,家庭成员变了,必须重新组织拍摄。
为何常见:单相机标定只要内参不变就长期有效,人们把单目经验直接照搬到多目,忽略了外参对机械环境的敏感性。
误区拍标定照片时,总习惯让标定板正正地对着镜头中心,觉得这样最清晰、最标准,歪着拍就心虚。
正解恰恰相反,标定需要全视场覆盖。如果标定板永远只出现在画面中央,镜头边缘的畸变和主点位置就无法被约束,拼接画面的边缘会明显弯曲。正确做法是让标定板在画面中心、边缘、四角、远近不同位置都出现,像摄影师换着角度举着校准牌一样。
为何常见:人眼觉得“正对才清楚”,但标定的目标是让整幅画面的投影都准确,而不是只让中心区域准确。
误区相邻相机视野重叠的那一小条区域没什么用,随便有点内容就行,反正主体画面不在这。
正解重叠区域是连接两个相机的唯一证据。如果没有共视点,两个相机的外参在理论上根本无法唯一确定(属于退化配置)。重叠区域里特征点的数量和质量,直接决定外参标定的精度上限。就像全家福里二舅正好站在两张照片的接缝处,他这块拍虚了,整条接缝都会裂开。
为何常见:从单相机视角看,重叠区域是“多余的重复画面”,很容易忽视它承担坐标系桥梁的角色。
误区看到 RMS 重投影误差优化到 0.05 像素,非常兴奋,觉得这个标定结果简直是完美的。
正解误差小到异常可能是过拟合——算法把观测噪声也一并“拟合”进去了,换一组新图像误差立刻反弹。正确做法是做交叉验证:留出一部分不参与优化的图像,用它们评估泛化误差。如果训练集误差 0.05 像素、验证集误差 2 像素,说明标定板不平整或图像质量有问题。
为何常见:优化指标带来的“数字越低越开心”的心理暗示,让人忘记了机器学习里过拟合这个老教训。
误区相邻相机一对一对标定,每对外参都挺准,合起来自然就准了,何必再做复杂的全局 Bundle Adjustment。
正解两两标定的误差会沿相机链累积。环形系统中,第一对误差 0.3 像素、第二对 0.3 像素……传到最后一对时,首尾相机可能错开几十像素。全局 BA 把误差均匀分摊到所有相机的内外参上,让整个环闭合。六位摄影师两两对齐接力传话,最后首尾对不上,必须所有人一起微调才行。
为何常见:双目等小系统两两标定效果看起来很好,放大到环视或多目阵列后,累积漂移问题才暴露出来。
面试题
Q1. 多相机标定中,内参矩阵主要描述什么?
- A.相机在世界中的位置
- B.镜头的内参固有属性← 正确答案
- C.相机朝向的旋转角度
- D.标定板的格数规格
答案:B。内参矩阵 K 描述焦距、主点等镜头固有属性,相当于摄影师的“镜头体质”。位置和朝向属于外参,标定板规格与内参无关。
Q2. 相邻相机必须有重叠视场的主要目的是?
- A.节省相机成本
- B.提供共视特征点← 正确答案
- C.提升图像分辨率
- D.减少标定板数量
答案:B。重叠区域提供同名特征点,是估计两个相机之间外参的唯一依据。没有共视点,外参在几何上不可观测,就像拼图少了连接块。
Q3. 下面哪个算法常用来剔除误匹配?
- A.RANSAC 算法← 正确答案
- B.K-Means 聚类
- C.SVM 分类器
- D.LSTM 模型
答案:A。RANSAC 通过随机采样拟合几何模型(如基础矩阵),把不符合模型的特征对判为外点剔除。K-Means 是聚类,SVM 是分类器,LSTM 是时序网络,都不做几何一致性校验。
Q4. Bundle Adjustment 优化过程的核心目标是什么?
- A.最小化图像像素亮度差
- B.最小化重投影误差← 正确答案
- C.最大化特征点数量
- D.最大化相机重叠面积
答案:B。BA 把所有相机内外参和三维点作为变量,最小化三维点在每张图像上的重投影误差,让光线束精确交会。亮度差是光流或直接法的目标,特征点数量和重叠面积不是优化目标。
Q5. LM(Levenberg-Marquardt)算法是哪两种方法的结合?
- A.梯度下降与牛顿法← 正确答案
- B.遗传算法与模拟退火
- C.最近邻与决策树
- D.贝叶斯与蒙特卡洛
答案:A。LM 在梯度下降(保证收敛)和牛顿法(快速局部收敛)之间自适应切换,是 BA 最常用的求解器。遗传算法、模拟退火属于随机搜索,贝叶斯属于概率推理,都不是 LM 的成分。
Q6. 鲁棒核函数在 BA 中的作用是什么?
- A.加快迭代收敛
- B.削弱误匹配影响← 正确答案
- C.增加约束数量
- D.降低相机分辨率
答案:B。鲁棒核(如 Huber 核)对大误差项做饱和处理,防止误匹配把优化结果“拽飞”。它不改变收敛速度、约束数量或图像分辨率,只改变误差对参数更新的贡献权重。
Q7. 多相机环视场景中,仅做两两标定而不做全局BA会导致?
- A.内参互相矛盾
- B.首尾相机累积错位← 正确答案
- C.标定板无法检测
- D.图像帧率下降
答案:B。两两标定的误差沿相机链传递累积,环形结构里最后一对相机与第一对相机会出现明显错位。内参矛盾、标定板检测、帧率都与两两标定无直接关系。
Q8. 下面哪项不是多相机标定常用的标定板?
- A.棋盘格标定板
- B.圆点阵列标定板
- C.二维码标记标定板
- D.纯色白板标记物← 正确答案
答案:D。棋盘格、圆点阵列、二维码板都有精确可检测的角点或标记点。纯色白板没有任何可提取的特征,无法提供约束,就像一张没有锚点的拼图。
Q9. 影响多相机标定精度的因素有哪些?
- A.标定板的刚度← 正确答案
- B.多角度覆盖程度← 正确答案
- C.光照均匀稳定← 正确答案
- D.相机外壳颜色
答案:ABC。标定板刚性不足会引入几何误差;多角度覆盖不全会让边缘畸变无法约束;光照不均匀会让角点检测偏移。相机外壳颜色不影响成像几何,对标定精度没有影响。
Q10. 多相机标定成果可以服务于哪些应用?
- A.环视全景拼接← 正确答案
- B.双目立体深度← 正确答案
- C.SLAM 初始化← 正确答案
- D.图像滤镜美化
答案:ABC。全景拼接依赖多相机外参对齐;双目深度估计依赖双目光束标定后的极线校正;SLAM 初始化需要多视角三角化可靠地图点。滤镜美化是单张图像处理,不需要多相机几何关系。