☰
多相机SLAM中的鱼眼相机模型:原理、标定与工程避坑指南
2026/10/14 14:01:04 网站建设 项目流程

多相机视觉SLAM确实是个容易让人上头的话题,尤其当你的系统里装的是鱼眼镜头时。MultiCol-SLAM名声在外,一批做多相机定位的人都拿它当过起步参考,但很多人卡住的第一关,恰恰不是SLAM本身的图优化或回环检测,而是底层的鱼眼相机模型。我见过不少同学用针孔模型硬套鱼眼,结果前端特征跟踪一路狂掉、重投影误差爆表,却死活查不出原因。这篇文章就把鱼眼相机的相机模型这件事彻底聊透:它到底是什么、有哪些门派、在MultiCol-SLAM这类系统里怎么落地、标定和避坑时要注意什么。适合正在研究多相机SLAM、准备从单目转到全景视觉,以及被鱼眼畸变折磨过的读者。

1. 多相机SLAM为什么绕不开鱼眼相机模型

1.1 多相机SLAM用鱼眼镜头图什么:视场、时长、鲁棒性

单目相机做SLAM时最痛的场景就是快速旋转和贴近遮挡物,画面一花,特征点全丢。鱼眼镜头接近半球的视场(常见190度左右)让这个问题缓解了一大截。在多相机系统里,鱼眼的价值还不只是单个镜头看得广,而是多个鱼眼组合起来能实现近似全向覆盖,车辆转弯、机器人原地掉头时,至少有几个相机还看得见特征。MultiCol-SLAM正是一套围绕多相机设计的前端里程计方案,它之所以要处理鱼眼相机模型,根本原因是这类镜头的成像几何和针孔完全不是一回事。

鱼眼带来的另一个实际好处是特征跟踪持续性变强。同样一个角点,在窄视场镜头里可能只跟踪几十帧,在鱼眼镜头里可以跟踪上百帧,因为特征的移动路径更长、留在大视场里的时间更久。长跟踪意味着三角化更稳、位姿估计的约束更连续,这在退化场景(走廊、白墙、隧道)里尤其救命。

1.2 相机模型在多相机系统里的“翻译官”角色

相机模型解决的是一个看似简单、实际工程味很重的问题:三维空间中的某个点,到底投影到图像平面的哪个像素上?反过来,图像里的某个像素,对应空间中的哪个方向?在单目系统里,这个“翻译”错了,顶多是自己跟自己的轨迹出问题。而在MultiCol-SLAM这种多相机系统里,所有相机要共享同一个世界坐标系,各相机之间的位姿关系(外参)需要把多组观测统一到同一个优化框架下。如果每个相机的内参模型都不准,外参标定和在线优化就会互相打架,你甚至分不清误差到底来自内参还是外参。所以鱼眼相机模型看似是内参的事,实则牵一发而动全身。

1.3 鱼眼模型要满足的3个硬指标

结合MultiCol-SLAM的实际使用,我总结出鱼眼相机模型必须满足三个硬指标。

第一是能覆盖超宽视场。针孔模型加上大畸变参数也能勉强拟合鱼眼,但超过90度之后误差急剧膨胀,到了140度以上基本失效。完整的鱼眼模型必须能把接近半球面的光线投射关系表达出来。

第二是数学形式可逆。SLAM的后端优化要反复做投影、算残差,前端又要通过像素反投影出方向来三角化。一个模型如果只有正投影、没有稳定高效的反投影,工程上几乎是废的。

第三是标定参数必须稳定。多相机系统标定一次很麻烦,如果模型参数对噪声敏感、容易陷入局部最优,出来的内参会带着很大偏差,后患无穷。这也是我在选型时最看重的一点。

2. 鱼眼相机模型的门派与选型思路

2.1 四种经典鱼眼投影:从公式看它们怎么压缩半球

鱼眼镜头想用有限的传感器面积装下超宽视场,就必须“压缩”图像。压缩方式不同,就产生了不同的投影模型。工程中最常见的有四种:等距投影、等立体角投影、体视投影、正交投影。

等距投影的公式是r = f * θ,r是成像点到图像中心的距离,f是焦距,θ是入射角。这个模型的特点是角度和半径成正比,看起来“均匀”,很多市售鱼眼镜头出厂就接近这种设计。等立体角投影是r = 2f * sin(θ/2),它让单位立体角对应相等的像面面积,画面边缘压缩比等距更狠。体视投影是r = 2f * tan(θ/2),它在角度较小时趋近针孔模型,边缘畸变介于中间。正交投影是r = f * sinθ,超过90度后半径反而减小,实际中单独使用的很少,多用于理论推导。

你别记这些公式背得头大,用生活化的方式理解:把鱼眼镜头看成要把一个半球面“压平”到一张底片上,等距像是均匀按压,等立体角像是从球心向外压,体视像是从球面某个点向外压。方式不同,边缘区域的拉伸和变形程度自然不同。

2.2 多项式畸变模型凭什么成为主流

问题是,真实镜头不会严格符合某一种理想投影,而是各种变形的混合。如果硬套某个理想模型,边缘区域就会残留系统性畸变。所以工程上更通用的做法是:用一个多项式来表达入射角θ和实际成像半径之间的映射关系。这就是业界常说的KB模型思路:真实畸变半径是入射角的奇次多项式函数,典型形式为:

θd = θ * (1 + k1 * θ² + k2 * θ⁴ + k3 * θ⁶ + k4 * θ⁸)

然后最终成像点坐标为:

x = fx * θd * cos(φ) + cxy = fy * θd * sin(φ) + cy

其中φ是入射光线在相机坐标系下的方位角。这个多项式的好处是抓住了鱼眼畸变的本质:畸变是入射角的函数,而不是简单在像素坐标上乘个系数。多项式阶数可以随镜头复杂度调节,标定程序能灵活拟合。它的代价是需要求逆运算,因为从像素反求入射角时,要解一个高次多项式方程。这个问题在下一节详细展开。

2.3 MultiCol-SLAM实际采用的鱼眼模型

基于公开的论文描述和开源实现,MultiCol-SLAM的每个鱼眼相机都是按通用多项式鱼眼模型来建模的,也就是将每个相机的投影映射建模为入射角到像素坐标的多项式函数,各个相机作为独立的传感器节点参与联合估计。这是非常合理的做法,因为一个多相机系统里,相机的制造工艺可能有细微差异,逐个建模能最大化适应度。而相机之间的外参(旋转和平移)作为系统的整体状态估计出来,链路非常清晰。

很多人误以为MultiCol-SLAM用了某种“特殊”的鱼眼模型,其实没有,真正特殊的是它对多相机的组织方式和对鱼眼模型的工程化处理。把多项式鱼眼模型吃透,再看它的代码就会轻松许多。

3. 一条投影链路走完:坐标变换到像素坐标

3.1 刚体变换:把世界坐标搬到相机坐标系

任何相机投影的第一步,都是把世界坐标系下的点变换到相机坐标系。这一步用的是外参,包含旋转矩阵R和平移向量t:

Pc = R * Pw + t

拍脑袋想一下,这一步无非是回答“这个三维点在我相机看来的前后左右上下是多少”。多相机系统里,每个相机都有自己相对于系统基准(通常是第一个相机或车辆坐标系)的外参,MultiCol-SLAM的联合优化里,这些外参也是一起在线的变量。

3.2 从入射角到畸变半径:核心公式拆解

当点落到相机坐标系Pc = (X, Y, Z)后,定义两个关键角度:方位角φ = atan2(Y, X),入射角θ = atan2(√(X²+Y²), Z)。如果把X、Y、Z归一化到Z=1的平面上,就是针孔模型里的归一化坐标;但在鱼眼模型里,我们不直接除以Z,而是保留角度信息,因为大视场下Z可能很小甚至趋近0,直接用归一化坐标会导致数值爆炸。

多项式模型登场:θd = θ * (1 + k1 * θ² + k2 * θ⁴ + k3 * θ⁶ + k4 * θ⁸)。这里θ是入射角(弧度),k1到k4是畸变系数。如果k全是0,那这个式子退化成了等距投影模型,所以可以想象多项式模型是对理想鱼眼模型的一种“修正”。在实际系统里,我见过k1和k2就可以修正大部分镜头,k3和k4更多是为了拟合边缘极端畸变。

3.3 内参矩阵:物理尺度到像素的最后一跳

有了θd和方位角φ,就得到了成像平面上距主点的“鱼眼距离”方向。这一步需要把物理尺度换算成像素尺度,并加上光心偏移:

u = fx * θd * cos(φ) + cxv = fy * θd * sin(φ) + cy

fx、fy是两轴焦距,cx、cy是主点坐标。注意这里用的不是针孔模型的fxX/Z形式,而是fxθd*cos(φ)形式,区别是:针孔里距离和Z成反比,视场越宽点越向中心收;鱼眼里距离只由入射角决定,所以即使画面边缘的物体离相机很近,它仍然能出现在视场里。这是鱼眼“看得宽”的数学本质。

3.4 反投影模型:SLAM优化里反复用的那条路

在SLAM里,正投影(3D到2D)用得不算最多,用得更多的是反投影:给定一个像素点,求它对应空间中的方向射线。因为前端三角化和后端残差计算都要靠方向而不是像素坐标。

反投影先由像素坐标计算θd和φ:

θd = sqrt((u-cx)²/fx² + (v-cy)²/fy²)φ = atan2((v-cy)/fy, (u-cx)/fx)

然后需要从θd反解θ。多项式函数是单调递增的,可以使用牛顿迭代,初值可以直接取θd,迭代几步就收敛。如果追求极致性能,可以离线生成角度查询表,运行时线性插值。在MultiCol-SLAM的工程化实现里,这种查表或迭代策略都是可落地的方案。

4. 鱼眼镜头标定:别拿针孔那套糊弄

4.1 鱼眼标定与针孔标定的关键差异

很多人标定普通相机习惯了,拿起棋盘格对着鱼眼拍几张就丢给OpenCV标定,结果边缘角点大量漏检,标定出来的内参画满绿叉。鱼眼标定和针孔标定有本质区别:针孔图像的棋盘格基本是直线结构,角点好提取;鱼眼图像的棋盘格在边缘区域弯得像哈哈镜,角点检测器很容易失败。

另外,鱼眼镜头的视场往往超过180度,图像周边会有圆形黑色区域(镜筒遮挡),角点检测器很容易在黑色边界附近产生虚检。标定板也不可能完全覆盖视场,所以标定时需要不断变换标定板姿态,让角点尽量分布到图像中心到边缘的各个半径范围里。只拍中心区域,边缘畸变参数完全没有观测约束,标定出来的k系数当然不准。

4.2 六步走完一套能用的标定

我把一套比较稳的流程总结成六步:

第一步,固定相机和镜头,终于不要再动对焦环。鱼眼镜头对焦环松动的后果是内参漂移,标定完等于白标。

第二步,准备标定板。普通棋盘格可以,但更推荐AprilTag或圆心阵列(如非对称圆格),因为它们在极端畸变下角点/圆心提取更鲁棒。如果一定要用棋盘格,尽量用棋盘格数量多(比如12x9)的板子,不要用6x4那种小格子。

第三步,采集图像。数量建议不少于30张,让标定板覆盖视场的中心、上下左右边缘、四个角落,同时让板子朝向相机倾斜多个角度。关键要求:图像中板子必须有清晰纹理,曝光不要过曝,否则角点亚像素精度全丢。

第四步,把标定图片交给标定工具。用OpenCV fisheye模块的话,记得先做角点提取,将提取失败的图像直接剔除,不要硬凑。用Kalibr这类工具则要按它的输入格式组织好图像和时间戳。

第五步,查看重投影误差和参数合理性。正常标定后平均重投影误差应该控制在0.5个像素以内。如果明显偏大,先怀疑角点检测错误,再怀疑标定板不平整,最后怀疑模型不匹配。多项式阶数可以尝试从4项降到2项,有时参数少反而更稳定。

第六步,固定标定结果,找一张白墙或均匀场景拍一张图,肉眼检查去畸变后的图像边缘直线是否变直。这个方法很土但极有效,只要边缘的直线仍然弯,标定一定有问题。

4.3 标定结果与多相机参数组织

标定完单个相机,得到的就是fx、fy、cx、cy和畸变系数组。MultiCol-SLAM这类多相机系统还需要各相机间的外参:相对位姿的旋转矩阵R和平移向量t。这些外参可以在系统内用联合标定的方式求,也可以先单独标定每个相机,再用立体标定方法求两两相对位姿。

实践中我建议参数文件不只记数字,还要记录相机型号、镜头焦距、标定时间、标定板类型和重投影误差,方便后续排障。参数导出时务必保留足够的小数位,内参文件里截断到个位数的光心偏差,在鱼眼大畸变下会产生好几个像素的误差,足以让SLAM后端的残差显着劣化。

5. 工程实战:我把MultiCol-SLAM接上鱼眼的几个坑

5.1 坑一:在未畸变图上做特征,却用畸变模型投影

我在实验中发现最隐蔽的bug之一:为了便于特征提取,有人对鱼眼图像做了去畸变处理(把鱼眼图重投影成针孔透视图),然后在去畸变图上提取角点、算描述子。这本问题不大,但后端投影残差却还是用原始鱼眼模型的参数。结果就是特征点位置和模型投影完全对不上,优化怎么调都发散。

正确的做法是做好坐标映射:要么全部在原始畸变域里提取特征,用畸变模型;要么在未畸变域里提取特征并把像素坐标反变换到原始畸变域。千万别混着用,一旦发现特征跟踪正常但后端残差飘忽,优先检查这个。

5.2 坑二:边缘特征点“虚胖”,优化被带偏

鱼眼镜头边缘的角点在图像上经常被拉长成一团,提取器给出的角点坐标实际上离真实角点可以偏差好几个像素。这种“虚胖”的特征一旦进入三角化和位姿优化,会以离群值的形式把结果带歪。

我的建议是,多相机系统里可以做一个简单的“半径掩码”:对距离主点超过一定半径(比如图像对角线半径的85%)的特征点直接剔除或降权重。因为边缘区域的畸变模型误差通常也更大,与其冒险,不如牺牲一点数量换取稳定性。MultiCol-SLAM前端的鲁棒性更多来自大视场带来的丰富特征,而不是硬啃边缘那几个残废点。

5.3 坑三:多相机外参基准不统一

多相机系统经常从两个相机开始联调,然后逐步加入更多路由相机。问题出在:不同批次的标定,相机0的参考坐标系可能因为初始化不同而偏了几毫米甚至几度。各相机内参虽然没变,但外参基准不统一,融合出来的轨迹会有明显的“跛脚感”,在某些角度下位姿抖动。

解决思路是统一基准:所有外参都相对于第一个相机或车辆坐标系,重新标定新相机时先固定已有相机的外参,只优化新相机的内参和相对位姿。MultiCol-SLAM的模块化设计很适合这种“逐步接入”策略,我调试时也是严格按照这个顺序。

5.4 坑四:参数精度与初始值问题

鱼眼模型的优化是非线性问题,标定和在线优化对初始值都很敏感。如果用一张中心区域的图像去估计初值,畸变系数的初值给0,光心给图像中心,通常能收敛;但如果光心初值给得离谱,优化很容易掉进局部最优,最终重投影误差看着还行,真实投影却完全对不上。

所以标定前,先用简单的棋盘格中心图像粗标定一次,得到光心和焦距的初步值,再带入全视场数据精标。在代码层面,我还会打印每轮迭代的参数增量,如果k1、k2变化幅度超过一个数量级,说明初值有问题。

5.5 排查速查表

现象优先排查项解决方向
重投影误差很大但参数正常角点提取错误、标定板弯曲剔除坏帧、换标定板
特征跟踪正常,后端残差发飘特征域与投影域不一致统一坐标映射
多相机融合轨迹有周期性抖动外参基准不统一固定基准、逐步接入
去畸变后边缘仍弯曲畸变模型阶数不足增加多项式阶数或重新标定
快速旋转时跟踪中断严重特征点集中分布使用半径掩码、均衡分布
标定结果每次都不一样对焦环松动、光照变化固定镜头、控制曝光

6. 工具选型与时间预算建议

6.1 常用标定工具横向对比

我做鱼眼标定这些年,OpenCV fisheye模块用得最多,优点是免费、离线、API简单,适合快速验证;缺点是它对标定板图像的管理比较手动,错误帧要自己过滤。Kalibr工具更适合多相机系统标定和IMU联合标定,它支持鱼眼模型,输出格式与不少SLAM系统的参数接口兼容度高。还有一些商业工具精度高、交互体验好,但价格不菲,对个人开发者不太友好。

工具适用场景优势短板
OpenCV fisheye单鱼眼验证、初学者免费、上手快交互弱、需手动清洗数据
Kalibr多相机与IMU联合模型齐全、多相机友好配置繁琐、对输入格式要求高
商业工具工业级精标自动化程度高、鲁棒成本高、闭源

6.2 我建议的最小可行流程与时间预算

如果你只是想跑通MultiCol-SLAM并用鱼眼数据做实验,我建议不要一上来就追求毫米级标定精度。先把流程跑通,再回头优化精度。最小可行流程是:固定相机,拍40张覆盖全视场的标定图像,用OpenCV fisheye模块标出内参,检查重投影误差和去畸变效果,然后以第一相机为基准做一次多相机外参估计。整个过程熟练的话半天内能完成。

我在实际使用中发现,多花30分钟仔细采集边缘区域的标定图像,比事后调试一周都管用。鱼眼标定这件事,数据质量对结果的支配性比算法本身强得多。别把时间都耗在调k系数上,多花时间端着标定板把视场边缘都喂一遍,效果立竿见影。

这几年调多相机SLAM,我最深的体会是:鱼眼相机的相机模型并不是一个需要“搞定”的数学难题,而是一个需要“伺候好”的工程环节。投影公式就那么几个,但真正决定系统稳不稳的,是你在标定数据采集、坐标映射、参数管理这些琐碎事情上的认真程度。如果你也被MultiCol-SLAM的鱼眼部分卡住,建议先从重投影误差曲线和一张去畸变测试图入手,把最基本的链路验证干净,再谈算法调优。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询