本文适合初学者系统掌握鱼眼镜头的标定与矫正原理,图文结合,带你从 0 到 1 理解
K
,D
,u,v
等参数的真实含义。
📌 一句话总结
鱼眼相机由于镜头视角宽、畸变大,拍出来的画面会“鼓起来”或者变形。通过标定得到的参数,可以让计算机“理解”这种变形是怎么发生的,并据此把图像“拉回正形”。
📐 一、什么是内参矩阵 K
?
🔹 定义
在 OpenCV 中,内参矩阵(Camera Intrinsic Matrix)通常是一个 3x3
的矩阵:
cfg.K = cv::Matx33d(
fx, 0, cx,
0, fy, cy,
0, 0, 1
);
你可能会看到这样的数值:
cfg.K = cv::Matx33d(
436.38, 0, 966.97,
0, 436.01, 556.57,
0, 0, 1
);
矩阵元素 | 含义 |
---|---|
fx |
X 方向焦距(单位:像素) |
fy |
Y 方向焦距(单位:像素) |
cx |
主点横坐标(图像中心 X) |
cy |
主点纵坐标(图像中心 Y) |
✅ 这个矩阵定义了相机如何将三维空间的点
(X, Y, Z)
投影到图像上的像素点(u, v)
。
🌀 二、什么是畸变系数 D
?
鱼眼镜头会让图像产生严重的边缘弯曲,OpenCV 提供了畸变系数来描述这种变形。
cfg.D = cv::Vec4d(k1, k2, k3, k4);
示例:
cfg.D = cv::Vec4d(
0.0130, 0.0029, -0.0016, 0.000017
);
k1
,k2
,k3
,k4
是四个畸变参数- 适用于 OpenCV 的
fisheye
模块(与普通畸变模型不同)
🔍 三、如何进行图像矫正?
OpenCV 使用以下 API:
cv::Mat map1, map2;
cv::fisheye::initUndistortRectifyMap(
cfg.K, cfg.D, cv::Mat::eye(3, 3, CV_64F), // 内参、畸变、旋转矩阵
cfg.K, image.size(), // 新的投影矩阵、图像尺寸
CV_16SC2, map1, map2
);
cv::Mat undistorted;
cv::remap(inputImage, undistorted, map1, map2, cv::INTER_LINEAR);
✅ 步骤解释:
initUndistortRectifyMap()
生成像素映射规则(map)remap()
按照 map 把每个像素“搬”回它该在的位置
🧠 四、图像坐标系 (u, v)
是啥?
坐标 | 含义 |
---|---|
u |
水平方向像素坐标(从左到右) |
v |
垂直方向像素坐标(从上到下) |
图像坐标从左上角 (0,0)
开始,右下角是 (width-1, height-1)
。
🧮 五、像素点是如何计算出来的?
相机模型里有这样一组公式:
u = fx * (X/Z) + cx
v = fy * (Y/Z) + cy
📌 表示一个 3D 世界点
(X,Y,Z)
被投影成 2D 图像坐标(u,v)
。
变量 | 含义 |
---|---|
(X,Y,Z) |
世界坐标系中的 3D 点 |
(u,v) |
相应的图像坐标(像素) |
fx, fy |
焦距乘以像素密度,缩放比例 |
cx, cy |
图像中心(主点),像素偏移量 |
🎥 六、实际标定流程
拍摄棋盘格图像后,OpenCV 提供了函数可直接求出 K
, D
:
cv::fisheye::calibrate(
objectPoints, imagePoints, imageSize,
K, D, rvecs, tvecs,
cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC,
cv::TermCriteria(3, 20, 1e-6)
);
objectPoints
: 棋盘格上每个点在 3D 空间的坐标imagePoints
: 图像中检测到的角点像素坐标K
,D
: 得到的内参和畸变参数
🧾 七、总结表格
项目 | 含义 |
---|---|
K |
相机内参,描述镜头成像方式 |
D |
鱼眼畸变系数,描述弯曲程度 |
u, v |
图像上的像素坐标 |
fx, fy |
像素缩放系数(与镜头焦距有关) |
cx, cy |
主点位置,决定图像中心偏移 |
矫正流程 | 利用 initUndistortRectifyMap + remap 实现 |
如果这篇文章帮你理清了思路,欢迎 👍点赞 / ⭐收藏 / 💬留言交流!