点击下方卡片,关注“自动驾驶之心”公众号
ADAS巨卷干货,即可获取
前言
在当今技术飞速发展的时代,相机已经成为自动驾驶领域不可或缺的一部分,扮演着极其重要的角色。自动驾驶技术的核心在于精确地感知和理解周围环境,其中,相机作为感知系统的眼睛,为车辆提供了丰富的环境信息。通过捕捉周围的图像,相机帮助自动驾驶系统实现了对道路状况、行人、车辆以及其他障碍物的识别和定位。特别是在同时定位与地图构建(SLAM)技术中,相机不仅能够实时地提供环境图像,还能够通过分析这些图像来帮助车辆理解其在环境中的位置,这对于无人驾驶汽车的导航和路径规划至关重要。
为了让相机能够准确地提供这些关键信息,了解和校准相机的内参变得尤为重要。相机内参包括了影响图像成像的各种因素,如焦距、主点坐标和镜头畸变参数等,这些参数决定了相机如何将三维世界映射到二维图像上。通过对这些内参进行精确的校准,我们可以校正由于镜头畸变等因素导致的图像扭曲,从而提高图像的准确性,这对于提高自动驾驶系统的识别和定位准确性至关重要。内参标定不仅确保了数据的可靠性,也是实现高级视觉算法,如深度估计、物体识别和三维重建等,的基础。因此,相机内参标定是自动驾驶系统开发中的一个重要步骤,它直接影响到自动驾驶汽车的性能和安全性。在自动驾驶技术不断进步的今天,深入理解相机模型和精确校准相机内参,是推动这一领域发展的关键。
本文总结了SLAM领域常见的“相机内参”形式,所谓的“相机内参”将从以下几个方面展开:
分别介绍“相机模型”和“畸变模型”
“投影模型”是指在实际使用过程中,以上两者的组合形式、一些实用的去畸变技巧
本文仅做学术讨论,如有问题欢迎留言讨论和指正,希望能对图像数据操作、感知模型训练、SLAM前端处理等不同任务带来启发,下面正式开始!
相机模型
Pinhole
intrinsic vector: [ , , , ]
, : focal length (mm/pixel)
, : principal point
先将世界坐标系下的点根据外参矩阵变换到相机坐标系下,根据相似三角形可得:
其中和是物理成像平面上的点,单位是mm
相机真正的成像元件是由离散的像素组成,所以两轴还差缩放和平移:
由两式可得:

其中是两轴倾斜系数,从模型中可以看出针孔相机的极限就是180度,但是实际操作中即使加上畸变模型,超过120度的相机标定结果就不是很好
Omnidirectional (omni)
intrinsic vector: [ , , , , ]
: mirror parameter (光心与单位球心的距离)
全向模型也叫做统一相机模型 (Unified Camera Model), 由五个参数来描述,就是平时见到的Cata-fisheye-model (MEI)的相机模型,但是如果要完美的表达鱼眼相机,需要配合畸变模型。
所谓的CataCamera实际指的是catadioptric,意思就是在鱼眼相机及镜头的外侧,再加上一个反向正对的折反射镜,对应屈光度相机(dioptric camera,视野小于180):
为什么要加一个外部透镜?大大增加视野范围
主要解决的问题:
外部透镜与相机光心未对齐
不同透镜模型(双曲线、抛物线、椭圆、平面、鱼眼镜头)
相机镜头的畸变
过度参数化导致的难以解决的最小化问题
投影过程(简化模型,把折反镜、镜头、相机看作一个东西):
将mirror坐标系的世界坐标点投影到归一化的球面上(球心为)
将投影点的坐标转换到以为中心的坐标系中,在原坐标系下表达为
然后把新坐标系下的投影点表达,转换到归一化平面上,可以看到如果,则模型退化为pinhole
去畸变(MEI用的是下文描述的rantan畸变模型)
根据虚拟的pinhole内参矩阵K得到像素坐标系下的
标定过程:
人工点选mirror的中心和镜子边界上的一点,或默认使用图片中心,估计主点
人工在鱼眼图中选取棋盘一条直线上的至少3个点,估计focal length
人工在每个图片上框选棋盘格ROI,估计外参
重投影图片,提取亚像素角点
全局优化
Extended Unified Camera Model
intrinsic vector: [ , , , , , ]
: mirror parameter (光心与单位球心的距离)
: 非球面度
为什么要提出这个模型?只需要比pinhole多2个参数,就可以表达径向畸变
UCM原本是将世界点投影在单位球面上,EUCM在UCM模型的基础上再添加一个系数,用来控制投影的曲面,使其变成一个椭球面
可以将UCM重新参数化从:
变成:
则EUCM在此基础上多加了一个系数:
由此可见当时,EUCM退化成了UCM
标定精度实验:不同镜头,使用UCM和EUCM的标定精度对比,使用更少的时间获得了和采用畸变系数UCM类似的精度
Double Sphere
intrinsic vector: [ , , , , , ]
: 两个单位球心的距离
: 第二个单位球心到光心的距离的表达参数(距离为)
双球模型能够很好的拟合大视场的镜头参数、不需要大量的三角计算、有封闭形式的逆
投影公式为:
从各个模型的精度对比实验中可以发现双球模型的价值:
在精度表现中,双球模型基本排名第二(橘色),和第一名的KB 8参数模型(绿色)几乎达到了相同的精度,但是在计算时间上DS玩爆KB模型,甚至KB模型还需要估计畸变模型,导致需要估计的参数比DS多,综上得在重投影误差几乎类似的情况下,运行时间最快,是高阶多项式模型较好的替代。
但是内参标定在意的是精度,时间效率不是那么重要,从精度表现上可以很容易明白为什么OpenCV的cv::fisheye采用的是KB模型。
Scaramuzza (OCam)
intrinsic vector: [ , , , , , , ]
: 多项式系数(2D pixel to 3D point),通常数量为5个
: 逆多项式系数(3D point to 2D pixel),通常数量为7-12个,由求逆而得
, , : elements of stretch matrix
只要是中央全向相机(光线最终汇聚于一点)都可以利用一个泰勒多项式来将世界点投影到像素平面上,无需额外的畸变参数,投影过程为


对于每个鱼眼相机都有透镜和成像平面,上式(3)的系数就是所需标定的 ,上式(4)中矩阵称为stretch matrix,内参中的, , 实际是一个矩阵的元素,完整写法应该是
其中黑色的是镜头,plane指的是图中粉红的数字传感器平面,pixel指的是第4个图片中最终看到的图片。
第3个表达的是:真实的数字传感器平面的“像素”不是理论上的“正方形且线性“的排列,但是在数字转换的时候会强行按照正方形且线性地排列,导致本来透镜看到的正圆,被数字转换强行转成了一个椭圆。笔者理解,这个弯曲的过程其实也可以包含镜头和成像平面没有对齐的情况,总而言之,这个拉伸矩阵的本质是仿射变换,矫正由于镜头和成像平面由于物理位置未对齐、信号转换过程等原因引起的畸变
对于每一个世界点投影到全向相机的镜头上时,都是投影到一个单位球上,这时候其实存在一个向量(不一定是单位的)是和 线性相关的,而这个又可以投影到传感器平面上,投影点为,所以说和世界点是线性相关的。
向量一共由2个东西决定:
sensor plane上的投影点:这个投影点来决定三维向量在sensor plane上的夹角
多项式曲线:所在的多项式曲面决定了自身第二个方向的夹角(垂直于sensor plane方向的夹角)
那么为什么在sensor plane的投影点会是直接平行于光轴投下来呢?
实际情况为右上图,因为和世界点是线性相关的,所以可以写成,实际就是向量第一个表达式中函数,所以真实的投影点可简写成,也就是图中真实的投影点和垂直的投影点相差了一个关于的函数,这个函数和函数一样取决于不同的折反射镜(抛物线形、双曲线形、椭圆形等等)或者镜头(等固体的、等角的等等),左上图是鱼眼镜头,右上图是双曲镜,对于所有鱼眼镜头和抛物线面镜的函数都等于1,所以左上图是垂直投影下来。
Scaramuzza大神在论文中也解释了为什么的第二个参数通常为0?
根据适用于双曲镜和抛物面镜或鱼眼相机的 的所有定义始终满足以下条件,对式(3)求导并取0,当取0时,必为0:

B-spline
intrinsic vector: [ , , ]
为B-spline曲面的控制点
如图所示,利用B-spline建立曲面来精准标定所有像素的方向:
优点:理论上可以准确标定出任何畸变、无畸变参数、没有相机模型的强假设(e.g. 畸变径向对称)
缺点:参数数量多(具体曲面控制点)、标定观测多
投影过程为:
标定精度实验1, 对比2个相机同时垂直于玻璃、水平于玻璃放置,分别使用普通模型和B-spline模型,可以看到在垂直于玻璃时,玻璃带来的影响类似,故误差分布相似;另一种情况,B-spline更能标定出玻璃带来的影响。
标定精度实验2,对比不同相机,分别使用普通模型和B-spline模型,可以看到B-spline的误差分布更小
畸变模型
Radial-Tangential (radtan)
distortion vector: [ , , , , ]
大家最熟悉、最常用、配合pinhole的畸变模型,分成径向畸变和切向畸变
一般k3可以不用估计,切向畸变一般也很小,根据需要可以估计
径向畸变
分为枕形畸变(长焦镜头)和桶形畸变(广角镜头)
光学镜头在生产制造过程中,很难保证厚度均匀,离中心越远,光线弯曲程度越高
![]() | ![]() |
切向畸变
相机感光成像平面没有完全和透镜平行
两者结合的公式:
Equidistant (equi)
distortion vector: [ , , , ]
用作鱼眼相机的畸变模型,和Pinhole使用就是Kannala-Brandt模型,能够很好的通过多项式来拟合普通、广角、鱼眼的镜头参数。
KB模型假设从图像的光心到投影点的距离与该点和主轴之间的角度多项式成比例(所以计算速度会比较慢,因为会大量进行三角计算)
对于相机系下的点可以通过公式转换到像素坐标系(这边采用的相机模型还是pinhole):
由投影公式和图片可以看到,实际上就是光心到归一化3D点的距离,所以竖直方向距离是1,由此可得该3D点和光轴的夹角的表达式。而上述成比例即可表达为的表达式。
其实一共有4种投影模型,但是都是奇函数,所以都可以用泰勒展开来表达,等距模型是为了简化采用的最简单的一种
当然畸变参数是可以增加的,阶数越高,精度越高,计算越慢。
Field-of-View (fov)
distortion vector: [ ]
由Kalibr提出的,根据鱼眼镜头的成像原理设计,一般也是和pinhole一起组合使用。
投影去畸变的时候主要有2个因素(畸变参数只有1个):
相机系下的3D点本身距离光心的距离
3D点到光心的距离和该点与光轴的夹角成比例比例因子
这个模型只是理想模型,这个角度是理论的视场角,但是真实的光学器件可能不完全遵循这个模型,比如制造偏差、硬件误差等
投影模型
模型组合
相机模型 + 畸变模型;一些应用举例
pinhole + radtan: cv::pinhole (OpenCV [4] ), VINS, ORB-SLAM
pinhole + equi (Kannala-Brandt [8] ): cv::fisheye (OpenCV), DSO
pinhole + FOV: atan (SVO, DSO, Kalibr)
omni + rantan: MEI (VINS Cata), cv::omnidir (OpenCV)
Scaramuzza: SVO, NASA, Matlab
去畸变方式
Pinhole
最常见的投影方式,一般都是把高畸变的鱼眼图片中的像素根据内参转换到相机系下的归一化3D点,然后再自己假设一个无畸变的Pinhole模型投影成针孔的样子。在这个过程中,实际上就可以DIY自己需要的结果,可以根据以下公式实现(横向)FOV角度与focal length的转换:
画面内容自适应:按照原图的比例大小去畸变(不会有黑边),这样会损失广角或鱼眼的一部分视野:
全视野模式:将会把所有原图的像素保留下来(图片内容不会有黑边,图示黑色为图例空白区域),但是会改变图片的长宽:
指定FOV:根据输入的指定角度去畸变,并且计算相应的focal length,如100度相机给定FOV为80度:
指定focal length:根据输入的指定focal length去畸变,并且计算相应的FOV,如100度相机给定fx,fy为500:
那为什么去完畸变之后边界的图像会被拉扯得特别严重?
鱼眼镜头会把光线进行折射(粉色),使得可以看到更广泛的视野,对于世界下的同一条直线(绿色),针孔按照相似三角形原理在图像上的投影更长(蓝色),所以在鱼眼原图越靠近边缘的地方,去完畸变拉扯现象越严重
Panoramic
全景图片可以在保留原始大FOV的前提下,尽量减小畸变。但是图像内容也会变得比较奇怪,e.g. 相机在道路中间,道路会变成两半。
Cubemap
由于鱼眼图片直接投影成pinhole边缘区域会出现拉伸现象,为了有效缓解这个问题,可以将整个原图的像素投影在一个立方体的5个面上(后面是看不到东西的),除了前面和投影到pinhole没什么区别,其他面就是把外参多转90度。
这样做会在不同面的接缝处产生突然弯折的现象。
Cylindrical
圆柱面的投影会在有效降低拉伸现象的同时,最大保留原始FOV。可以想像这个相机坐标系下的单位球就是地球,这个圆柱投影就是“墨卡托投影”,会生成一张“世界地图”。
![]() | ![]() |
以下为畸变示意图,请主要关注左侧车辆的形状变化,从左至右分别为广角原图(形变)、pinhole投影(拉伸现象)、cylindrical投影(较为自然)
![]() | ![]() | ![]() |
参考资料
[1] ETH Kalibr: https://github.com/ethz-asl/kalibr
[2] ETH CamOdoCal: http://github.com/hengli/camodocal
[3] ROS camera_calibration: http://wiki.ros.org/camera_calibration
[4] OpenCV: http://opencv.org
[5] Matlab Ocam calibration toolbox: http://sites.google.com/site/scarabotix/ocamcalib-toolbox
[6] Pinhole calibration: "A Flexible New Technique for Camera Calibration"
[7] Iterative calibration: "Accurate Camera Calibration using Iterative Refinement of Control Points"
[8] Kannala-Brandt model: "A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses"
[9] Mei model: "Single View Point Omnidirectional Camera Calibration from Planar Grids"
[10] Extended Unified camera model: "An Enhanced Unified Camera Model"
[11] Double sphere model: "The Double Sphere Camera Model"
[12] Scaramuzza: "A Toolbox for Easily Calibrating Omnidirectional Cameras"
[13] Figure explanation of Ocam: "Structure from Motion with Wide Circular Field of View Cameras"
[14] Figure explanation of Cubemap: "CubemapSLAM: A Piecewise-Pinhole Monocular Fisheye SLAM System"
[15] Figure explanation of Panoramic: "Review on Panoramic Imaging and Its Applications in Scene Understanding"
[16] B-spline model: "Generalized B-spline Camera Model"
投稿作者为『自动驾驶之心知识星球』特邀嘉宾,欢迎加入交流!
① 全网独家视频课程
BEV感知、毫米波雷达视觉融合、多传感器标定、多传感器融合、多模态3D目标检测、车道线检测、轨迹预测、在线高精地图、世界模型、点云3D目标检测、目标跟踪、Occupancy、cuda与TensorRT模型部署、大模型与自动驾驶、Nerf、语义分割、自动驾驶仿真、传感器部署、决策规划、轨迹预测等多个方向学习视频(扫码即可学习)

② 国内首个自动驾驶学习社区
国内最大最专业,近2700人的交流社区,已得到大多数自动驾驶公司的认可!涉及30+自动驾驶技术栈学习路线,从0到一带你入门自动驾驶感知(2D/3D检测、语义分割、车道线、BEV感知、Occupancy、多传感器融合、多传感器标定、目标跟踪)、自动驾驶定位建图(SLAM、高精地图、局部在线地图)、自动驾驶规划控制/轨迹预测等领域技术方案、大模型、端到端等,更有行业动态和岗位发布!欢迎扫描下方二维码,加入自动驾驶之心知识星球,这是一个真正有干货的地方,与领域大佬交流入门、学习、工作、跳槽上的各类难题,日常分享论文+代码+视频

③【自动驾驶之心】技术交流群
自动驾驶之心是首个自动驾驶开发者社区,聚焦2D/3D目标检测、语义分割、车道线检测、目标跟踪、BEV感知、多模态感知、Occupancy、多传感器融合、transformer、大模型、在线地图、点云处理、端到端自动驾驶、SLAM与高精地图、深度估计、轨迹预测、NeRF、Gaussian Splatting、规划控制、模型部署落地、cuda加速、自动驾驶仿真测试、产品经理、硬件配置、AI求职交流等方向。扫码添加汽车人助理微信邀请入群,备注:学校/公司+方向+昵称(快速入群方式)
④【自动驾驶之心】平台矩阵,欢迎联系我们!