
1. 模型概述
鱼眼相机通过特殊镜头获得超大视场角,水平或对角视场角可接近或超过 180 ∘ 180^\circ 180∘。普通针孔模型采用透视投影,当视角接近 180 ∘ 180^\circ 180∘ 时,像平面坐标会趋于无穷,因此不能直接准确描述鱼眼镜头。
鱼眼模型通常把入射光线与光轴之间的夹角映射为图像半径:
ρ = f g ( θ ) \rho=f\,g(\theta) ρ=fg(θ)
其中:
- θ \theta θ:空间光线与相机光轴之间的夹角;
- ρ \rho ρ:投影点到主点的图像半径;
- f f f:尺度或等效焦距;
- g ( θ ) g(\theta) g(θ):鱼眼投影函数。
2. 坐标系统
2.1 世界坐标系
空间点表示为:
P w = X w Y w Z w T \mathbf{P}_w= \begin{bmatrix} X_w & Y_w & Z_w \end{bmatrix}^{T} Pw=XwYwZwT
2.2 相机坐标系
通过外参将世界坐标转换到相机坐标:
P c = R P w + t \mathbf{P}_c=\mathbf{R}\mathbf{P}_w+\mathbf{t} Pc=RPw+t
其中:
- R ∈ S O ( 3 ) \mathbf{R}\in SO(3) R∈SO(3):旋转矩阵;
- t ∈ R 3 \mathbf{t}\in\mathbb{R}^{3} t∈R3:平移向量;
- P c = X c , Y c , Z c T \mathbf{P}_c=X_c,Y_c,Z_c^T Pc=Xc,Yc,ZcT。
2.3 像素坐标系
像素点表示为:
p = u v T \mathbf{p}= \begin{bmatrix} u & v \end{bmatrix}^{T} p=uvT
通常以图像左上角为原点, u u u 向右, v v v 向下。
3. OpenCV 鱼眼投影模型
3.1 归一化透视坐标
对于相机坐标系中的三维点:
a = X c Z c , b = Y c Z c a=\frac{X_c}{Z_c},\qquad b=\frac{Y_c}{Z_c} a=ZcXc,b=ZcYc
定义:
r = a 2 + b 2 r=\sqrt{a^2+b^2} r=a2+b2
光线夹角为:
θ = arctan ( r ) \theta=\arctan(r) θ=arctan(r)
3.2 Kannala--Brandt 角度多项式
OpenCV cv::fisheye 使用四个畸变系数描述角度映射:
θ d = θ ( 1 + k 1 θ 2 + k 2 θ 4 + k 3 θ 6 + k 4 θ 8 ) \theta_d= \theta \left( 1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8 \right) θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)
畸变后的归一化坐标为:
x d = θ d r a , y d = θ d r b x_d=\frac{\theta_d}{r}a,\qquad y_d=\frac{\theta_d}{r}b xd=rθda,yd=rθdb
当 r r r 接近 0 时,应使用极限值处理,避免除零。
3.3 映射到像素坐标
相机内参矩阵为:
K = f x α f x c x 0 f y c y 0 0 1 \mathbf{K}= \begin{bmatrix} f_x & \alpha f_x & c_x\\ 0 & f_y & c_y\\ 0 & 0 & 1 \end{bmatrix} K= fx00αfxfy0cxcy1
最终像素坐标:
u = f x ( x d + α y d ) + c x u=f_x(x_d+\alpha y_d)+c_x u=fx(xd+αyd)+cx
v = f y y d + c y v=f_y y_d+c_y v=fyyd+cy
其中:
- f x , f y f_x,f_y fx,fy:横向和纵向焦距,单位为像素;
- c x , c y c_x,c_y cx,cy:主点坐标;
- α \alpha α:倾斜系数,工程中通常固定为 0;
- k 1 , k 2 , k 3 , k 4 k_1,k_2,k_3,k_4 k1,k2,k3,k4:鱼眼畸变系数。
完整转换链路:
text
世界三维点 Pw
↓ 外参 R、t
相机三维点 Pc
↓ 归一化
透视坐标 a、b
↓ 计算入射角 θ
鱼眼角度映射 θd
↓ 半径缩放
畸变归一化坐标 xd、yd
↓ 内参 K
像素坐标 u、v
4. 常见鱼眼投影类型
| 投影模型 | 半径映射 | 特点 | 常见用途 |
|---|---|---|---|
| 等距投影 | ρ = f θ \rho=f\theta ρ=fθ | 角度与图像半径成正比 | 全景、机器人、运动相机 |
| 等立体角投影 | ρ = 2 f sin ( θ / 2 ) \rho=2f\sin(\theta/2) ρ=2fsin(θ/2) | 保持单位面积对应的立体角关系 | 测光、天空成像 |
| 体视投影 | ρ = 2 f tan ( θ / 2 ) \rho=2f\tan(\theta/2) ρ=2ftan(θ/2) | 保角性较好,边缘拉伸明显 | 视觉测量、特殊全景 |
| 正射投影 | ρ = f sin θ \rho=f\sin\theta ρ=fsinθ | 边缘压缩明显,投影范围有限 | 监控、半球视场 |
| 多项式模型 | ρ = f g ( θ ) \rho=f\,g(\theta) ρ=fg(θ) | 能拟合真实镜头,精度较高 | 工业标定、OpenCV 鱼眼模型 |
真实镜头通常不严格满足单一理想投影函数,因此工程中常用多项式模型或统一相机模型拟合。
5. 鱼眼模型与针孔模型对比
| 对比项 | 针孔相机 | 鱼眼相机 |
|---|---|---|
| 基本映射 | r = f tan θ r=f\tan\theta r=ftanθ | r = f g ( θ ) r=f\,g(\theta) r=fg(θ) |
| 典型视场角 | 通常小于 120 ∘ 120^\circ 120∘ | 可接近或超过 180 ∘ 180^\circ 180∘ |
| 图像边缘 | 透视拉伸 | 弯曲和径向压缩明显 |
| 直线性质 | 三维直线通常投影为二维直线 | 非过光心直线常投影为曲线 |
| 常用标定模型 | Brown--Conrady | Kannala--Brandt、统一相机模型 |
| 典型场景 | 测量、普通检测、双目 | 环视、全景、机器人导航、监控 |
6. 逆投影:像素到空间射线
逆投影用于把像素恢复为相机坐标系中的一条空间射线。
6.1 像素归一化
忽略倾斜系数时:
x d = u − c x f x , y d = v − c y f y x_d=\frac{u-c_x}{f_x},\qquad y_d=\frac{v-c_y}{f_y} xd=fxu−cx,yd=fyv−cy
r d = x d 2 + y d 2 r_d=\sqrt{x_d^2+y_d^2} rd=xd2+yd2
6.2 求解入射角
根据鱼眼模型求解:
r d = θ ( 1 + k 1 θ 2 + k 2 θ 4 + k 3 θ 6 + k 4 θ 8 ) r_d= \theta \left( 1+k_1\theta^2+k_2\theta^4+k_3\theta^6+k_4\theta^8 \right) rd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)
该非线性方程通常使用牛顿迭代求解 θ \theta θ。
6.3 恢复单位射线
令:
ϕ = atan2 ( y d , x d ) \phi=\operatorname{atan2}(y_d,x_d) ϕ=atan2(yd,xd)
则单位方向向量为:
d = sin θ cos ϕ sin θ sin ϕ cos θ \mathbf{d}= \begin{bmatrix} \sin\theta\cos\phi\\ \sin\theta\sin\phi\\ \cos\theta \end{bmatrix} d= sinθcosϕsinθsinϕcosθ
单个像素只能恢复一条空间射线。必须结合双目视差、深度网络、激光雷达、地面平面或已知尺寸,才能恢复唯一三维点。
7. 标定参数
鱼眼相机标定通常输出:
text
图像尺寸:
width, height
内参:
fx, fy, cx, cy, alpha
畸变:
k1, k2, k3, k4
每张标定图外参:
rvec, tvec
质量指标:
RMS 重投影误差
每幅图重投影误差
边缘区域误差
参数稳定性
推荐 YAML 格式:
yaml
camera_model: fisheye
image_width: 1920
image_height: 1080
camera_matrix:
rows: 3
cols: 3
data: [fx, 0.0, cx,
0.0, fy, cy,
0.0, 0.0, 1.0]
distortion_model: equidistant
distortion_coefficients:
rows: 1
cols: 4
data: [k1, k2, k3, k4]
8. 鱼眼标定流程
- 准备棋盘格、圆点阵列或 ChArUco 标定板;
- 从图像中心、边缘和四角采集不同姿态;
- 保证标定板覆盖尽可能大的视场;
- 检测角点并进行亚像素优化;
- 初始化内参矩阵和四个鱼眼畸变参数;
- 最小化所有图像的重投影误差;
- 剔除模糊、遮挡或误差过大的图像;
- 重新标定并检查参数稳定性;
- 生成去畸变或立体校正映射;
- 使用真实场景直线和边缘区域验证。
采集建议
- 标定板应覆盖图像中心、边缘和四角;
- 不要只采集正对相机的图像;
- 包含俯仰、偏航、滚转和不同距离;
- 固定焦距、分辨率、裁剪模式和 ISP 配置;
- 关闭动态防抖、数字变焦和动态裁剪;
- 避免运动模糊、强反光、过曝和角点遮挡;
- 标定板尺寸必须准确,并保持平整。
9. 去畸变与视场控制
去畸变不是简单地恢复"原始场景",而是将鱼眼图像重新投影到目标相机模型。
输出效果受新相机矩阵和输出尺寸影响:
- 新焦距变大:中心区域放大,保留视场减小;
- 新焦距变小:保留更多视场,但黑边增多;
- 输出透视图:适合检测和测量,但边缘拉伸明显;
- 输出柱面图:适合水平全景;
- 输出球面图:适合全景拼接和环视;
- 输出多个透视视图:适合机器人环视检测和 BEV 感知。
OpenCV 常用处理链:
cpp
cv::fisheye::estimateNewCameraMatrixForUndistortRectify(
K, D, image_size, R, K_new,
balance, new_size, fov_scale);
cv::fisheye::initUndistortRectifyMap(
K, D, R, K_new, new_size,
CV_16SC2, map1, map2);
cv::remap(
src, dst, map1, map2,
cv::INTER_LINEAR,
cv::BORDER_CONSTANT);
其中:
balance控制裁剪与视场保留的平衡;fov_scale调整输出视场;map1、map2可预计算,适合视频实时处理。
10. OpenCV C++ 标定接口
cpp
#include <opencv2/calib3d.hpp>
#include <opencv2/imgproc.hpp>
std::vector<std::vector<cv::Point3f>> object_points;
std::vector<std::vector<cv::Point2f>> image_points;
cv::Mat K = cv::Mat::eye(3, 3, CV_64F);
cv::Mat D = cv::Mat::zeros(4, 1, CV_64F);
std::vector<cv::Vec3d> rvecs;
std::vector<cv::Vec3d> tvecs;
int flags =
cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC |
cv::fisheye::CALIB_CHECK_COND |
cv::fisheye::CALIB_FIX_SKEW;
cv::TermCriteria criteria(
cv::TermCriteria::COUNT + cv::TermCriteria::EPS,
100,
1e-8);
double rms = cv::fisheye::calibrate(
object_points,
image_points,
image_size,
K,
D,
rvecs,
tvecs,
flags,
criteria);
11. 重投影误差
对于第 i i i 个标定点,观测像素为 p i \mathbf{p}_i pi,模型投影为 p ^ i \hat{\mathbf{p}}_i p^i:
e i = ∥ p i − p ^ i ∥ 2 e_i= \left\| \mathbf{p}_i-\hat{\mathbf{p}}_i \right\|_2 ei=∥pi−p^i∥2
均方根误差:
E R M S = 1 N ∑ i = 1 N e i 2 E_{\mathrm{RMS}}= \sqrt{ \frac{1}{N} \sum_{i=1}^{N}e_i^2 } ERMS=N1i=1∑Nei2
不能只检查全局 RMS,还应统计:
- 图像中心区域误差;
- 图像边缘和四角误差;
- 每张标定图平均误差;
- 最大误差和 P95 误差;
- 不同距离、姿态下的误差;
- 去畸变后直线的弯曲残差。
12. 工程注意事项
12.1 分辨率变化
纯缩放图像时,可按比例调整:
f x ′ = s x f x , f y ′ = s y f y , c x ′ = s x c x , c y ′ = s y c y f_x'=s_xf_x,\quad f_y'=s_yf_y,\quad c_x'=s_xc_x,\quad c_y'=s_yc_y fx′=sxfx,fy′=syfy,cx′=sxcx,cy′=sycy
鱼眼畸变系数通常保持不变。
若分辨率变化来自传感器裁剪、binning、数字防抖、不同读出区域或不同 ISP 模式,则主点和有效成像关系可能改变,应重新进行投影验证,必要时重新标定。
12.2 模型不要混用
- 普通相机模型使用
cv::calibrateCamera; - OpenCV 鱼眼模型使用
cv::fisheye::calibrate; - 两套模型的畸变参数定义不同;
- 不应把普通模型的 k 1 , k 2 , p 1 , p 2 , k 3 k_1,k_2,p_1,p_2,k_3 k1,k2,p1,p2,k3 直接传入鱼眼接口;
- ROS 中常把 OpenCV 鱼眼模型标记为
equidistant。
12.3 边缘误差
鱼眼图像边缘区域对参数更敏感。若标定板只出现在中心区域,即使全局 RMS 较小,边缘投影仍可能严重偏差。
12.4 检测与分割
将整幅鱼眼图强行展开为透视图,会改变边缘目标的尺寸和形状。常见方案包括:
- 直接使用原始鱼眼图训练模型;
- 将鱼眼图切分为多个透视视图;
- 使用柱面或球面特征;
- 在原始鱼眼坐标中检测,再反投影为空间射线;
- 为 BEV 感知预计算像素到射线查找表。
13. 机器人融合感知应用
13.1 环视感知
多颗鱼眼相机可覆盖机器人周围近 360 ∘ 360^\circ 360∘ 区域,用于:
- 近场障碍物检测;
- 环视拼接;
- 可行驶区域分割;
- 泊车和低速导航;
- 视觉里程计与定位;
- BEV 特征构建。
13.2 相机---激光雷达融合
text
激光雷达三维点
↓ 外参变换
鱼眼相机坐标系三维点
↓ 鱼眼投影模型
鱼眼像素坐标
↓ 图像边界与遮挡检查
语义、颜色或特征关联
不能使用普通针孔投影直接代替鱼眼投影,否则边缘区域会产生明显投影偏差。
13.3 鱼眼双目
鱼眼双目需要:
- 左右相机分别完成鱼眼内参标定;
- 求解左右相机外参;
- 使用鱼眼立体校正;
- 生成适合立体匹配的目标投影图;
- 在校正图上计算视差;
- 使用校正模型恢复三维点。
OpenCV 常用接口:
cpp
cv::fisheye::stereoCalibrate(...);
cv::fisheye::stereoRectify(...);
14. 推荐模块接口
输入结构
cpp
struct FisheyeCameraModelInput {
cv::Mat image;
cv::Mat K;
cv::Mat D;
cv::Mat R;
cv::Mat t;
cv::Size image_size;
};
输出结构
cpp
struct FisheyeProjectionResult {
cv::Point2f pixel;
cv::Vec3d camera_ray;
bool inside_image;
bool valid_depth;
};
软件模块划分
text
FisheyeCalibration
├── PatternDetector
├── CornerRefiner
├── CalibrationSolver
├── ReprojectionEvaluator
└── CalibrationSerializer
FisheyeCameraModel
├── ProjectPoint
├── UnprojectPixel
├── DistortPoint
├── UndistortPoint
├── BuildRemapTable
└── ValidateProjection
FisheyeFusion
├── LidarToCamera
├── CameraToPixel
├── OcclusionCheck
├── SemanticAssociation
└── ProjectionVisualizer
15. 总结
鱼眼相机模型的核心不是在针孔模型后简单增加普通径向畸变,而是建立:
空间光线角度 → 鱼眼图像半径 → 像素坐标 \text{空间光线角度} \rightarrow \text{鱼眼图像半径} \rightarrow \text{像素坐标} 空间光线角度→鱼眼图像半径→像素坐标
完整工程链路应包含:
- 准确的鱼眼投影和逆投影模型;
- 内参、畸变和外参标定;
- 像素到空间射线的转换;
- 可控视场的去畸变和重映射;
- 中心与边缘分区误差验证;
- 分辨率和传感器模式一致性检查;
- 与激光雷达、IMU、双目和 BEV 模块的坐标统一。
参考资料
-
OpenCV Documentation --- Fisheye camera model
https://docs.opencv.org/4.x/db/d58/group__calib3d__fisheye.html
-
Juho Kannala, Sami S. Brandt, A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses, IEEE TPAMI, 2006.