3. 针孔相机模型:成像原理、畸变模型、去畸变实战、OpenCV实现
3.1 从物理世界到像素平面
做BEV感知,第一关就是搞懂相机是怎么「看」世界的。说白了,针孔相机模型就是最基础的几何抽象——把三维空间里的点,映射到二维图像上。
我记得刚入行时,总觉得这玩意儿太简单,不就是小孔成像嘛。直到有一次在实车测试中,发现车道线投影到BEV视角下全是弯的,排查了半天才发现是相机内参标定出了问题。嗯,从那以后我再也不敢小看这个模型了。
针孔模型的数学表达其实很直观:
// 世界坐标系 -> 相机坐标系 -> 图像坐标系 -> 像素坐标系
// 核心公式:s * [u, v, 1]^T = K * [R|t] * [X, Y, Z, 1]^T
其中 K 是内参矩阵,[R|t] 是外参。内参决定了焦距、光心偏移这些相机本身的属性,外参决定了相机在世界中的位置和朝向。
内参矩阵 K 长这样:
[ fx 0 cx ]
[ 0 fy cy ]
[ 0 0 1 ]
fx, fy 是焦距(像素单位),cx, cy 是光心坐标。这些值一旦标定好,只要不换镜头、不调焦,基本不变。
3.2 畸变模型:为什么直线会变弯?
理想很丰满,现实很骨感。针孔模型假设光线直线传播,但实际镜头是透镜组,光线会折射。这就导致了畸变。
畸变主要分两类:
- 径向畸变:光线经过透镜边缘时弯曲更厉害,产生「桶形」或「枕形」效果。用
k1, k2, k3三个参数描述。 - 切向畸变:透镜和成像平面不平行,产生「倾斜」效果。用
p1, p2两个参数描述。
我做过一个项目,用广角相机做环视拼接。一开始没做去畸变,结果拼接出来的俯视图,车旁边的行人都是扭曲的——你想想看,这要是用于泊车辅助,谁敢信?
注意:畸变参数和相机内参是绑定的。换镜头、调焦距后必须重新标定。我曾经见过有人把不同相机的参数混用,结果去畸变后图像反而更扭曲了。
3.3 去畸变实战:OpenCV 实现
去畸变的流程其实就三步:
- 从相机标定得到内参和畸变系数
- 用
cv::initUndistortRectifyMap生成映射表 - 用
cv::remap重映射图像
我个人习惯把映射表提前算好存下来,因为实车上每帧都算一遍太浪费算力。你想想看,嵌入式平台本来就资源紧张,能省则省。
#include <opencv2/opencv.hpp>
// 假设已经标定得到以下参数
cv::Mat cameraMatrix = (cv::Mat_<double>(3,3) <<
fx, 0, cx,
0, fy, cy,
0, 0, 1);
cv::Mat distCoeffs = (cv::Mat_<double>(1,5) <<
k1, k2, p1, p2, k3);
// 生成映射表(只做一次)
cv::Mat map1, map2;
cv::Size imageSize(1280, 720);
cv::initUndistortRectifyMap(
cameraMatrix, distCoeffs, cv::Mat(),
cameraMatrix, imageSize,
CV_32FC1, map1, map2);
// 每帧去畸变
cv::Mat distortedImg, undistortedImg;
// ... 读取图像到 distortedImg ...
cv::remap(distortedImg, undistortedImg, map1, map2, cv::INTER_LINEAR);
小技巧:如果去畸变后图像边缘出现黑边,可以调整 cv::getOptimalNewCameraMatrix 的 alpha 参数。alpha=0 会裁剪掉所有黑边但损失视野,alpha=1 保留全部视野但会有黑边。我一般设 0.5 左右,平衡一下。
3.4 知识体系总览
下面这张图是我自己梳理的针孔相机模型知识结构,方便你快速把握全局:
3.5 避坑指南与个人经验
做去畸变这几年,我踩过不少坑。挑几个典型的说说:
- 映射表的数据类型:
initUndistortRectifyMap的 map 类型建议用CV_32FC1,别用CV_16SC2。后者虽然省内存,但精度不够,去畸变后的图像边缘会有锯齿。我在一个量产项目上吃过这个亏,后来全部改成了 float 类型。 - 畸变参数顺序:OpenCV 的畸变系数向量是
[k1, k2, p1, p2, k3],但有些标定工具输出的是[k1, k2, p1, p2, k3, k4, k5, k6]。搞混了的话,去畸变结果会完全不对。我建议每次标定完都先拿一张棋盘格验证一下。 - 性能优化:如果每帧图像分辨率很大(比如 1920x1080),remap 会吃掉不少 CPU。我一般用
cv::INTER_NEAREST代替cv::INTER_LINEAR,速度能快 30% 左右,效果差别不大。
一句话总结:针孔相机模型是 BEV 感知的基石。内参外参标定准了,去畸变做好了,后面的 IPM 变换、多相机融合才能靠谱。这一步省事,后面全是坑。
可可精品资料库