摘要:在自动驾驶和机器人SLAM系统中,鱼眼相机因其超大视场角(FOV > 180°)而被广泛应用。但不同的鱼眼相机模型(UCM、Kannala-Brandt、Double Sphere等)该如何选择?本文深入解析主流鱼眼投影模型的数学原理、计算公式及代码实现,助你轻松应对智驾标注工具和可视化开发。
前言
在开发自动驾驶标注工具和机器人可视化系统时,你是否遇到过这样的困惑:
- 为什么同一个鱼眼相机,在不同系统中使用的标定参数格式不一样?
- OpenCV的
fisheye模型和ORB-SLAM的相机模型有什么区别? - 如何选择合适的鱼眼投影模型来保证标注精度?
作为一名专注智驾、机器人标注工具和可视化的开发者,今天我就带大家深入理解鱼眼相机投影模型的本质,并提供完整的TypeScript/Rust实现代码。
一、为什么需要鱼眼相机模型?
传统的**针孔相机模型(Pinhole Model)**假设光线直线传播,适用于视场角小于120°的普通相机。但鱼眼镜头的视场角通常达到180°甚至220°以上,会产生严重的径向畸变,针孔模型已无法准确描述。
图:鱼眼图像畸变与校正对比
为了解决这个问题,研究者提出了多种鱼眼相机投影模型,主要包括:
- UCM(Unified Camera Model) - 统一相机模型
- Kannala-Brandt(KB) - 基于入射角的多项式模型
- Double Sphere(DS) - 双球面模型
- FOV模型 - 视场角模型
下面我们逐一解析。
二、UCM(统一相机模型)详解
2.1 模型原理
UCM(Unified Camera Model),也称为Mei氏全向相机模型,是目前SLAM和VIO系统中最常用的鱼眼模型之一。它的核心思想是:
将3D点先投影到单位球面,再通过参数ξ将球面点投影到归一化平面。
图:UCM模型的球面投影原理
2.2 数学公式
给定3D点 ,UCM模型的投影过程如下:
步骤1:计算到原点的距离
步骤2:球面到平面投影(核心公式)
其中 (xi)是关键参数:
- :退化为标准针孔模型
- :适用于抛物面反射镜系统
- :适用于鱼眼镜头
步骤3:径向畸变多项式
步骤4:内参变换到像素坐标
2.3 TypeScript代码实现
export const getFisheyeUV = (
point: { x: number; y: number; z: number },
K: [number, number, number, number], // [fx, fy, cx, cy]
D: [number, number, number, number], // [k1, k2, k3, k4]
xi: number = 1
) => {
const [fx, fy, cx, cy] = K
const [k1, k2, k3, k4] = D
const { x, y, z } = point
// 步骤1:计算距离
const r = Math.sqrt(x * x + y * y + z * z)
if (r === 0) return null
// 步骤2:球面投影
const denom = z + xi * r
if (Math.abs(denom) < 1e-9) return null
const xu = x / denom
const yu = y / denom
// 步骤3:径向畸变
const rho2 = xu * xu + yu * yu
const rho4 = rho2 * rho2
const rho6 = rho4 * rho2
const rho8 = rho4 * rho4
const radial = 1 + k1 * rho2 + k2 * rho4 + k3 * rho6 + k4 * rho8
const xd = xu * radial
const yd = yu * radial
// 步骤4:像素坐标
const u = fx * xd + cx
const v = fy * yd + cy
return { x: u, y: v }
}
2.4 为什么SLAM系统偏爱UCM?
- 通用性强:一套公式可描述针孔、鱼眼、折反射相机
- 计算高效:仅涉及代数运算,无三角函数,适合实时系统
- 精度足够:在120°~220°视场角范围内拟合精度高
主流支持UCM的系统:
- ORB-SLAM3
- VINS-Mono
- OpenVINS
三、Kannala-Brandt(KB)模型详解
3.1 模型原理
Kannala-Brandt模型是OpenCV fisheye模块的默认模型,它基于入射角θ的多项式拟合。
图:KB模型基于入射角θ进行多项式拟合
3.2 数学公式
步骤1:计算入射角θ
步骤2:径向距离的多项式拟合
步骤3:归一化坐标 如果 :
步骤4:像素坐标
3.3 代码实现(TypeScript)
export const getKBProjection = (
point: { x: number; y: number; z: number },
K: [number, number, number, number],
D: [number, number, number, number]
) => {
const [fx, fy, cx, cy] = K
const [k1, k2, k3, k4] = D
const { x, y, z } = point
// 计算入射角θ
const r = Math.sqrt(x * x + y * y)
const theta = Math.atan2(r, z)
const theta2 = theta * theta
const theta3 = theta2 * theta
const theta5 = theta3 * theta2
const theta7 = theta5 * theta2
// 径向距离多项式
let rd = theta * (k1 + k2 * theta2 + k3 * theta4 + k4 * theta6)
// 处理θ接近0的情况
if (theta < 1e-8) {
rd = k1 * theta
}
// 归一化坐标
const scale = rd / theta
const xu = scale * x / z
const yu = scale * y / z
// 像素坐标
const u = fx * xu + cx
const v = fy * yu + cy
return { x: u, y: v }
}
3.4 KB模型特点
优点:
- 精度高:对普通鱼眼镜头(FOV < 195°)拟合效果极佳
- OpenCV原生支持:
cv::fisheye模块直接使用 - 标定工具丰富:Kalibr等工具默认输出KB模型参数
缺点:
- 涉及
atan三角函数,计算开销略高于UCM - 在超大视场角(>200°)下精度下降
四、Double Sphere(DS)双球面模型
4.1 模型原理
Double Sphere模型是UCM的改进版,使用两个球面参数来更好地拟合超大视场角鱼眼镜头。
4.2 数学公式
步骤1:第一次球面投影
步骤2:第二次球面投影
步骤3:应用畸变并转换到像素坐标 (与UCM类似,应用径向畸变多项式)
4.3 DS模型优势
- 超高精度:在FOV > 180°或超大畸变下,重投影误差最低
- 适用于超广角:适合220°+的极端视场角
- 新兴SLAM系统支持:OpenVINS、DSO等
五、FOV(Field-of-View)模型
5.1 模型原理
FOV模型由Scaramuzza提出,基于以下公式:
其中是唯一的畸变参数。
5.2 特点
- 参数少:仅需1个畸变参数
- 适合超广角:早期全景相机常用
- 计算简单:但精度不如KB和DS模型
六、模型对比总结
图:不同投影模型的畸变曲线对比
| 特性 | UCM | Kannala-Brandt | Double Sphere | Pinhole |
|---|---|---|---|---|
| 数学核心 | 球面投影+代数畸变 | 入射角θ+多项式 | 双球面投影 | 平面投影 |
| 计算开销 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 适用FOV | 120°~220°+ | 120°~195° | 150°~220°+ | <120° |
| 拟合精度 | 高 | 极高 | 最高 | 低(鱼眼不适用) |
| OpenCV支持 | omnidir模块 | fisheye原生 | omnidir新版本的 | calibrateCamera |
| 行业应用 | VIO/SLAM主流 | 自动驾驶标定主流 | 新兴SLAM系统 | 普通相机 |
七、实战建议
7.1 标注工具开发
如果你正在开发自动驾驶标注工具,建议:
-
同时支持UCM和KB模型
- ROS Bag / Kalibr标定常输出KB4参数
- VINS / ORB-SLAM常关联UCM参数
- 只支持一种模型会导致像素级误差
-
实现反投影(Undistortion)
- 从2D像素点反推3D射线是标注的核心功能
- UCM的反投影无解析解,需用牛顿迭代法求解
7.2 WebGL可视化优化
在Three.js中做鱼眼可视化时:
// 在Fragment Shader中实现投影,而非CPU
vec3 getFisheyeUV(vec3 point, float xi) {
float r = length(point);
float denom = point.z + xi * r;
return point.xy / denom;
}
void main() {
vec3 uv = getFisheyeUV(worldPos, 0.8);
// ... 纹理采样
}
性能提升技巧:
- 使用GPU并行计算代替CPU计算
- 高频场景考虑Rust + WASM,性能可提升10-50倍
7.3 Rust高性能实现
#[inline]
pub fn project_fisheye_ucm(
point: [f64; 3],
k: [f64; 4],
d: [f64; 4],
xi: f64,
) -> Option<[f64; 2]> {
let [x, y, z] = point;
let [fx, fy, cx, cy] = k;
let [k1, k2, k3, k4] = d;
let r = (x * x + y * y + z * z).sqrt();
if r < 1e-9 {
return None;
}
let denom = z + xi * r;
if denom.abs() < 1e-9 {
return None;
}
let xu = x / denom;
let yu = y / denom;
let rho2 = xu * xu + yu * yu;
let rho4 = rho2 * rho2;
let rho6 = rho4 * rho2;
let rho8 = rho4 * rho4;
let radial = 1.0 + k1 * rho2 + k2 * rho4 + k3 * rho6 + k4 * rho8;
let xd = xu * radial;
let yd = yu * radial;
let u = fx * xd + cx;
let v = fy * yd + cy;
Some([u, v])
}
八、总结
- UCM模型:SLAM/VIO系统的首选,计算高效、通用性强
- KB模型:自动驾驶标定的标准,OpenCV原生支持,精度极高
- DS模型:超广角(>200°)场景的最优解
- 模型选择:根据视场角和系统需求选择,标注工具建议同时支持多种模型
参考资料
- Mei, C. & Rives, P. (2007). Single View Point Omnidirectional Camera Calibration from Planar Grids.
- Kannala, J. & Brandt, S. (2006). A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses.
- Usenko, V. et al. (2017). The Double Sphere Camera Model.
- OpenCV Documentation: Fisheye Camera Model
作者介绍:红波,专注于智驾、机器人标注工具和可视化开发,技术栈:TypeScript/Vue/WebGL/Three.js/Go/Rust。欢迎交流讨论!
相关项目:
希望这篇文章能帮助你深入理解鱼眼相机模型!如有疑问,欢迎在评论区交流👇