- 自动驾驶
- 计算机视觉
【免费下载链接】SensorsCalibration
OpenCalib: A Multi-sensor Calibration Toolbox for Autonomous Driving
导读
本文围绕开源多传感器标定工具箱 SensorsCalibration 中的 surround-camera 模块,系统讲解自动驾驶环视(Surround View / AVM)相机外参标定的四套工具:面向普通环视相机的 target-less 自动标定(auto_calib)、面向环视鱼眼相机的 target-less 自动标定(auto_calib_fisheye)、基于标定板的产线级自动标定(auto_calib_target),以及支持 pinhole / Ocam / fisheye 三种模型的交互式手动标定(manual_calib)。读完本文,你将掌握每套工具的适用场景、编译运行方式、命令行参数、相机模型选择依据,以及从 BEV 投影、纹理提取到随机搜索优化(coarse-to-fine)的完整算法链路,并能在真实部署中根据传感器类型(普通相机或鱼眼)与场景(道路 or 产线)正确选择工具。
一、模块总览:一套 AVM 工具箱,四种标定路线
surround-camera/README.md 将本模块定位为 "a calibration toolbox for surround view cameras or surround view fisheye cameras",即同时覆盖普通环视相机与环视鱼眼相机。四套工具的选型关系可用下表概括(来源于该 README 的工具矩阵):
| calibration param | calibration type | calibration method | mannual calibration | auto calibration | usage documentation |
|---|---|---|---|---|---|
| surround_cameras (fisheye) | extrinsic | target-less | ✔ | manual_calib | |
| surround_cameras (fisheye) | extrinsic | target-less | ✔ | auto_calib_fisheye | |
| surround_cameras | extrinsic | target-less | ✔ | auto_calib | |
| surround_cameras | extrinsic | target | ✔ | auto_calib_target |
几点关键结论:
- 四套工具全部解决**外参(extrinsic)**标定问题,即各环视相机相对车体(或 BEV 地面坐标系)的旋转和平移。
- 前三套标定路线均为target-less(无标定板),依靠场景自然纹理完成自动优化;只有 auto_calib_target 属于target(标定板)路线,且 README 明确指出它可用于环视相机生产线的标定("This tool can be used for production line calibration of surround view cameras")。
- 手动标定(manual_calib)同时支持普通环视相机与鱼眼环视相机,是唯一同时覆盖两种传感器的手动方案。
从仓库目录结构看,四个子模块的实现高度同构:auto_calib 与 auto_calib_fisheye 均包含include/{optimizer.h, texture_extractor.h, transform_util.h}与src/{calibration.cpp, optimizer.cpp, texture_extractor.cpp},二者的核心区别在于主程序入口(main)中选择的camera_model与data_set;manual_calib 依赖 include/extrinsic_param.hpp 与 include/intrinsic_param.hpp 从 JSON 加载内参/外参;auto_calib_target 则包含独立的 src/calibration.cpp(solvePnP 求解外参)与 src/stitching.cpp(环视拼接验证)。
二、编译与运行:统一构建流程与可执行文件约定
四套工具都采用标准 CMake 构建流程,各子模块 README 中给出的编译步骤完全一致:
mkdir -p build && cd build cmake .. && make构建产物统一输出到模块根目录下的bin/目录(由各 CMakeLists.txt 的set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)决定,见 auto_calib/CMakeLists.txt)。
各工具的可执行文件与运行方式如下:
| 工具 | 可执行文件 | 运行方式(在模块根目录执行) |
|---|---|---|
| auto_calib | run_AVM_Calibration | cd ~./auto_calib/后./bin/run_AVM_Calibration |
| auto_calib_fisheye | run_AVM_Calibration | cd ~./auto_calib_fisheye/后./bin/run_AVM_Calibration |
| auto_calib_target | run_AVM_Calibration/run_stitching | ./bin/run_AVM_Calibration或./bin/run_stitching |
| manual_calib | run_avm | 见下节命令行参数 |
其中 auto_calib 与 auto_calib_fisheye 的 CMakeLists 均为project(online_Calibration)、add_executable(run_AVM_Calibration src/calibration.cpp)(fisheye 版 与 普通版 完全一致),因此可执行文件名相同,需要放在各自目录下运行。
2.1 依赖与构建前提
从 CMakeLists 可归纳出构建依赖:
- auto_calib / auto_calib_fisheye:C++17(
-std=c++17 -pthread,用于多线程随机搜索)、Eigen3(/usr/include/eigen3)、OpenCV(find_package(OpenCV REQUIRED),代码中用到fisheye::distortPoints、remap、findContours等接口)。 - auto_calib_target:C++11、Eigen3、OpenCV;CMake 默认在
/usr/local/opencv-2.4.13/share/OpenCV/下查找 OpenCV 2.4.13(NO_DEFAULT_PATH),若使用其他版本需自行调整该路径。 - manual_calib:C++11、Pangolin(GUI 显示)、Boost(filesystem、system)、OpenCV、jsoncpp(
libjsoncpp.a),链接关系见 manual_calib/CMakeLists.txt。
2.2 运行示例与输出
无标定板自动标定(auto_calib / auto_calib_fisheye)为无参数交互程序:入口 main 直接读取./imgs/下的Front/Left/Back/Right四张图像(普通版为 png、鱼眼版为 jpg),标定过程中会依次打印左/右/后相机各阶段(1st 粗搜、2nd 精调、3rd 微调)的 luminosity loss、最优搜索参数(roll/pitch/yaw/tx/ty/tz)与优化后的外参矩阵,最终在模块根目录输出拼接结果图after_all_calib.png,并将各阶段对比图写入after_*_calib*.png(详见 auto_calib/src/calibration.cpp)。
auto_calib_target 的run_stitching直接读取imgs/front_125.png等四张图像,投影到地面后用addWeighted叠加生成并保存surround_view.png(stitching.cpp)。
三、无标定板自动标定:auto_calib 与 auto_calib_fisheye
这两套工具共享同一套算法框架(optimizer + texture_extractor),仅通过 main 中的三个配置项区分:
// camera_model: 0-fisheye; 1-Ocam; 2-pinhole int camera_model = 2; // auto_calib 用 pinhole int camera_model = 0; // auto_calib_fisheye 用 fisheye string data_set = "common"; // auto_calib string data_set = "fisheye"; // auto_calib_fisheyecamera_model控制投影时使用的畸变模型(见Optimizer::project_on_ground中fisheye::distortPoints/distortPointsOcam/distortPoints三分支),data_set则决定内参、畸变、外参初值、BEV 高度与裁剪尺寸等初始化参数(见 optimizer.cpp 的initializeK/initializeD/initializePose/initializeKG/initializeHeight/initializetailsize)。
3.1 算法主链路:BEV 投影 → 公共视野纹理提取 → 光度一致性优化
整个标定流程(以fixed = "front"固定前相机为例)可分为四步:
- 生成初始 BEV 鸟瞰图:利用四台相机初始外参
T_CG(ground→camera)、内参K_C、畸变D_C与地面相机内参K_G,对地面网格像素逐个反投影、畸变、remap采样,得到四张 BEV 图(project_on_ground,代码见 optimizer.cpp)。 - 裁剪公共视野区域:
Optimizer::tail按sizef/sizel/sizeb/sizer保留前/左/后/右相机各自靠近车身一侧的条带区域,其余区域补黑(optimizer.cpp),使相邻相机之间形成可比较的公共视野。 - 纹理提取:
extractor对相邻 BEV 对(fl/fr/bl/br)做二值化(Binarization,两图同位置均非黑则置 255)、膨胀腐蚀与findContours提取最大轮廓,再按梯度幅值筛选纹理点并随机下采样 500 个点,同时计算曝光补偿系数ncoef(两图公共视野平均灰度的比值)与各相机灰度gamma校正(见 texture_extractor.cpp)。 - 光度一致性随机搜索优化:以待标定相机外参微扰
deltaT将 BEV 纹理点重投影到相邻相机图像上,计算灰度差平方和作为 loss,用多线程随机采样最小化。
标定顺序上,前相机固定,先标 right,再标 left,最后标 behind(main 中的调用顺序),每次标定完会用最优外参重新生成该相机 BEV 并更新公共视野纹理。
3.2 粗到精(coarse-to-fine)三阶段搜索策略
CameraOptimization(见 auto_calib/src/calibration.cpp)对每个相机依次执行三阶段搜索,各阶段参数如下:
| 阶段 | 线程数 | 迭代次数 | roll/pitch/yaw 搜索范围 | tx/ty/tz 搜索范围 |
|---|---|---|---|---|
| 1st 粗搜(coarse) | 7 | 100000/线程 | [-3°, 3°] 按 x/y/z 轴拆分区间 | [-0.01, 0.01] m |
| 2nd 精调(fine) | 6 | 15000/线程 | [-1°, 1°] 为主 | [-0.005, 0.005] m 为主 |
| 3rd 微调(fine) | 3 | 8000/线程 | [-0.01°, 0.01°] | [-0.002, 0.002] m |
第一阶段的 7 个线程将三维姿态空间(每个轴 [-3,3] 度)拆分成若干子区间并行搜索(例如Calibrate_right(iter_nums, -3, 3, -3, 3, -3, 3, ...)),随后用fine_random_search_params在更小邻域继续细化。搜索过程中使用独立 mutex 保护各相机的最优解更新(mutexleft/mutexright/mutexbehind),并且只有 loss 严格下降才接受新外参(random_search_params与fine_random_search_params中的loss_new < cur_*_loss判断,见 optimizer.cpp)。
对畸变模型的适配细节:优化过程中back_camera_and_compute_loss重投影纹理点时同样按camera_model选择fisheye::distortPoints、distortPointsOcam或简化 pinhole 投影(optimizer.cpp)。
3.3 两种数据集的关键初始化参数对比
data_set为 "common"(auto_calib)与 "fisheye"(auto_calib_fisheye)时,初始化参数差异如下(均取自initialize*系列函数):
| 参数 | common(pinhole) | fisheye |
|---|---|---|
| 相机内参 K(示例 Front) | fx=fy=390.425287, cx=cy=750 | fx≈422.13, cx≈612.83, cy≈545.06(四相机各异) |
| 畸变 D(示例 Front) | [0,0,0,0] | [-0.07031853, 0.00387505, -0.00333139, 0.00056406] |
| 地面 BEV 内参 K_G | fx=fy=390.425287, cx=cy=750 | fx=1/0.15, fy=-1/0.15, cx=bcols/2, cy=brows/2 |
| 相机高度 h | 5.1 m(四相机) | 1.0 m(四相机) |
| tail 裁剪尺寸 | sizef=sizel=sizer=450, sizeb=350 | sizef=340, sizel=sizer=390, sizeb=380 |
| BEV 尺寸 | 1500×1500 | 1000×1000 |
需要说明的是,common 数据集的初始外参T_CG中还叠加了人为施加的姿态扰动(left/right/behind 的扰动欧拉角与平移见 optimizer.cpp),用于模拟真实安装误差并验证优化算法的收敛能力;fisheye 数据集则直接使用 ROCES 标定结果作为初值。
3.4 曝光一致性处理
由于四台相机曝光参数未必一致,公共视野两侧灰度可能存在系统性偏差。纹理提取阶段通过exposure_flag开关控制:开启时ncoef = mean(gray1) / mean(gray2)(公共视野平均灰度比),优化 loss 计算中将参照侧灰度除以该系数后再做差,从而把曝光差异从几何误差中解耦。auto_calib 中 fl/fr 对exposure_flag=0、bl/br 对exposure_flag=0,而 auto_calib_fisheye 全部置 1,且对 bl/br 还启用了公共视野边缘过滤(edge_flag=1,按与相机中心的距离剔除贴近 BEV 边缘的弱纹理点)。这些开关均为 main 中的可调参数(auto_calib_fisheye/src/calibration.cpp)。
3.5 结果可视化对比
auto_calib 与 auto_calib_fisheye 在优化前会先用初始外参生成before_all_calib.png,优化结束后用SaveOptResult基于最终外参生成after_all_calib.png。两个版本仓库内均附带示例结果图:
- 普通环视相机版本:标定前 before_all_calib.png 与标定后 after_all_calib.png;
- 鱼眼环视版本:标定前 before_all_calib.png 与标定后 after_all_calib.png。
注意:标定板在无标定板自动标定中仅起到提供纹理信息的作用(README 原文 "the calibration board here only provides some texture information"),并不参与几何约束求解。
四、基于标定板的产线级自动标定:auto_calib_target
auto_calib_target 面向生产场景,思路与无标定板路线完全不同:它利用已知车体系 3D 点与图像 2D 点的一一对应,通过solvePnP直接求解各相机外参。
4.1 求解流程:已知 3D 点 + 2D 点 → solvePnP
src/calibration.cpp 的 main 中:
InitializeK为四台相机设置相同的针孔内参(fx=fy=390.425287, cx=cy=750),InitializeD将畸变置零(5 维向量全 0)。Initialize3dPoints定义标定板特征点在车体坐标系下的 3D 坐标,例如前相机前方x=3.5 m平面上的 12 个点((3.5, ±0.12, ±0.36)等),左/后/右相机分别对应y=2.0 / x=-3.0 / y=-2.0平面上的对称点组(见 calibration.cpp)。Initialize2dPoints给出同一组特征点在四张图像中的像素坐标(2D 匹配点,calibration.cpp)。- 对每台相机依次调用
solvePnP(pts_3d, pts_2d, K, D, rvecs, translation)求解旋转向量与平移,再经Rodrigues转为旋转矩阵,hconcat拼成 4×4 外参矩阵T_F/T_L/T_B/T_R并打印(calibration.cpp)。
因此,要移植到自己的产线,核心工作量在于替换上述 3D 点(由标定板相对车体的精确安装位置决定)与 2D 点(标定板角点/特征在图像中的检测结果,当前仓库为手工预设样本)。
4.2 拼接验证工具 run_stitching
src/stitching.cpp 提供独立的环视拼接验证程序:读取imgs/front_125.png等四张图,用初始化函数中的内参/外参投影到 1500×1500 的 BEV(dX=dY=0.005,即 5 mm/像素),将各相机 BEV 裁剪掉互相遮挡的区域后以 0.5 权重addWeighted叠加生成surround_view.png(stitching.cpp)。该工具可快速检验 auto_calib_target 求出的外参是否能让环视画面无缝拼接。
仓库内附带四张带标定板图像的 BEV 投影验证结果:前 img_GF.png、左 img_GL.png、后 img_GB.png、右 img_GR.png,以及最终 surround_view.png。
五、交互式手动标定:manual_calib
manual_calib 提供基于 Pangolin 的实时可视化手动微调工具,支持 pinhole、Ocam(全方位相机)、fisheye 三种相机模型,仓库内附 pinhole_samples 与 ocam_samples 两套示例数据。
5.1 命令行参数与运行示例
程序要求 5 个参数(run_avm.cpp):
./bin/run_avm <image_path> <intrinsic_path> <extrinsic_path> <camera_model>其中<camera_model>取值:0表示 OpenCV fisheye 模型,1表示 Ocam(Omnidirectional)模型,2表示 pinhole 模型。README 给出的三种运行方式:
# 直接运行(使用默认参数) cd ~./manual_calib/ ./bin/run_avm # pinhole 示例数据 ./bin/run_avm pinhole_samples/imgs pinhole_samples/intrinsic pinhole_samples/extrinsic 2 # Ocam 示例数据 ./bin/run_avm ocam_samples/imgs ocam_samples/intrinsic ocam_samples/extrinsic 1注意两套示例数据对应的相机安装高度不同:代码中默认bev2ground=5.1(pinhole 样本),当camera_model==1时切换为 Ocam 样本的四个高度值(Front/Left/Back/Right 分别约 6.078/6.252/6.310/6.281 m,见 run_avm.cpp),更换数据时务必核对安装高度。
5.2 数据格式:JSON 内参与外参
程序通过 include/intrinsic_param.hpp 的LoadIntrinsic与 include/extrinsic_param.hpp 的LoadExtrinsic读取 JSON。内参文件要求形如 pinhole_samples/intrinsic/Front.json:顶层键为<sensor>-intrinsic,其param.cam_K.data为 3×3 矩阵、param.cam_dist.data为畸变系数行向量。外参文件形如 pinhole_samples/extrinsic/Front.json:顶层键为<sensor>-to-<target>-extrinsic,param.sensor_calib.data为 4×4 变换矩阵(此处为 ground/BEV 系到相机系的T_CG)。四台相机固定命名为Front/Left/Back/Right.json。
5.3 交互操作与参数微调
程序启动后以 Pangolin 窗口显示 BEV 投影结果,并提供控制面板与键盘两种微调方式:
- 键盘微调:字符表
{'q','a','w','s','e','d','r','f','t','g','y','h'}分别对应 roll/pitch/yaw/tx/ty/tz 六个自由度的正向与负向调整(ManualCalibration,见 run_avm.cpp),每按一键即对当前相机外参乘以对应的微调增量矩阵。 - 面板微调:Pangolin 面板提供步长调节(
deg step默认 0.3°,t step(cm)默认 6 cm,对应代码中cali_scale_degree_=0.3、cali_scale_trans_=0.06)、相机选择(frame0-3)、单相机微调按钮(± x/y/z degree、± x/y/z trans)、Reset(恢复初始外参)与 Save Image 按钮。 - 拼接模式:
stiching开关开启后,窗口显示四相机联合环视图,保存时会将四台相机结果一次性写入calibration_0.txt~calibration_3.txt(JSON 格式 4×4 矩阵,见saveResult)。
每次调整后程序都用当前外参重新执行project_on_ground并刷新画面,实现所见即所得的微调体验。完整操作流程可参照仓库 lidar2camera/README.md 中描述的手动标定交互规范。
六、核心原理小结与选型建议
从源码可以归纳出两套并行的技术路线:
无标定板自动标定(auto_calib / auto_calib_fisheye)
- 依赖场景纹理而非标定板,适合道路场景快速部署;
- 算法本质是基于公共视野光度一致性的外参优化:BEV 投影建立"地面像素 ↔ 相机像素"映射,纹理提取圈定可比较区域,随机搜索在 6 维外参空间最小化灰度差平方和;
- 粗(±3° 分区间并行搜索)→ 精(±1°)→ 微调(±0.01°)三阶段搜索有效扩大收敛域;
- 通过
camera_model与data_set两个开关即可切换 pinhole/fisheye 与对应初始化参数。
标定板路线(auto_calib_target)+ 手动微调(manual_calib)
- auto_calib_target 用 solvePnP 从 3D-2D 对应直接求解外参,流程确定、可重复,适合产线;
- manual_calib 适合在自动结果基础上做人工精修,或在自动标定不可用的场景兜底;
- 两者共用 pinhole/Ocam/fisheye 三种投影模型的选择逻辑,保证模型一致性。
选择建议:普通环视相机优先用 auto_calib,鱼眼环视相机用 auto_calib_fisheye(注意其内部已内置 fisheye 畸变初值与 1000×1000 BEV 配置);产线场景用 auto_calib_target 并自行替换 3D/2D 标定点;需要在自动结果上精修或无法自动标定时,用 manual_calib 按传感器模型选择对应示例数据作为模板。
引用
本文内容基于 surround-camera/README.md 及其四个子模块文档整理,算法细节与参数均取自对应源码。该模块对应的学术工作为论文Automatic Surround Camera Calibration Method in Road Scene for Self-driving Car(arXiv:2305.16840),若在研究中使用了本项目,可按仓库 README 中给出的 BibTeX 条目引用:
@misc{2305.16840, Author = {Jixiang Li and Jiahao Pi and Guohang Yan and Yikang Li}, Title = {Automatic Surround Camera Calibration Method in Road Scene for Self-driving Car}, Year = {2023}, Eprint = {arXiv:2305.16840}, }- 自动驾驶
- 计算机视觉
【免费下载链接】SensorsCalibration
OpenCalib: A Multi-sensor Calibration Toolbox for Autonomous Driving
相关推荐
免费解锁 Wand 专业版:Wand-Enhancer 本地补丁与手机远程面板完整指南
免费解锁 Wand 专业版:Wand Enhancer 本地补丁与手机远程面板完整指南 免费时长用完的那次弹窗 单机打到存档点,打开 Wand 准备调数值,弹窗
自动驾驶计算机视觉SensorsCalibration环绕相机标定:鱼眼相机与普通相机标定差异详解
SensorsCalibration环绕相机标定:鱼眼相机与普通相机标定差异详解 在自动驾驶和智能交通系统中,环绕相机标定是确保车辆环境感知准确性的关键技术。S
自动驾驶计算机视觉SensorsCalibration 环绕相机标定板方案 auto_calib_target:产线 AVM 外参标定与俯视拼接实战指南
SensorsCalibration 环绕相机标定板方案 auto_calib_target:产线 AVM 外参标定与俯视拼接实战指南 环绕视图(Around
自动驾驶计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考