镜头畸变:径向和切向在改什么
OpenCV 用 k1–k6、p1、p2 参数化径向与切向畸变;未校正就做多视图几何时,RANSAC 会在错误模型上给出高 inlier 的错误位姿。

1. 中心 inlier 高,边缘 match 全崩
广角 VO:画面中心 essential matrix inlier 很好,一到边缘 epipolar 全歪、match 假阳性暴增。十有八九 dist 没进 pipeline,或标定板只拍中心—— 与 强相关,全局 RMS 低但边缘外推畸变大。广角上忽略畸变,几乎等于换了一台相机。这种「中心好边缘坏」的指纹,应优先查 dist 与 undistort,而不是先换 ORB 为 SIFT。
2. OpenCV 畸变模型
Brown–Conrady(OpenCV 默认):
在归一化平面。径向 把直线拉弯,广角主导;切向 多来自 sensor 与光轴不垂直,幅度通常更小但忽略会让去畸变后直线仍微弯。视场 >120° 直接 cv2.fisheye 模块——别用 pinhole dist 硬拟 fisheye,边缘 RMS 「假好」最误导人。
3. 运行时:map 而非每帧求逆
map1, map2 = cv2.initUndistortRectifyMap(K, dist, None, K, (w, h), cv2.CV_16SC2)
undist = cv2.remap(raw, map1, map2, cv2.INTER_LINEAR)undistort() 每帧解析求逆,1080p CPU 吃不消。map 与 绑定,换分辨率或换镜头必须重建。getOptimalNewCameraMatrix(K,dist,(w,h),alpha) 的 alpha 控制 valid ROI;newK 与 map 一起 version 进 yaml。stereo 里 alpha 与有效重叠区联动,改 alpha 要重跑 rectification 验收。
4. 标定覆盖与 fix 策略
板子角点必须进 视场四角;只有中心数据时边缘外推畸变大。至少 30% 图像板子覆盖四角。CALIB_RATIONAL_MODEL 启用 ;数据少时高阶 radial overfit 中心。CALIB_FIX_K3 防 overfit;fix 太多外推差。calibrateCamera 与 fisheye.calibrate 的 dist 向量长度不同,YAML 混用 silent wrong。张法采集要求 azimuth/elevation 网格,不是桌面平拍十张就上线。
5. undistortPoints 与 PnP 契约
PnP 输入若已 undistort,dist 应 None 或零向量,否则 double-undistort。任何 F/E/H/PnP 输入点,要么 undistort 后 pinhole 像素,要么算法显式带 dist——不能混层。undistortPoints(..., P=K) 返回仍带 K 的像素;P=None 才是归一化平面。文档里写清「本节点输入点是否已 undistort」比注释一行 dist=None 更防回归。
6. 与 feature / epipolar 的衔接
未 undistort 就在畸变像素域做 epipolar,Sampson threshold 无物理意义——中心 inlier 高、边缘崩是典型指纹。feature 检测可在 raw 或 undistort 上做,但 match 坐标层 必须统一。undistort 图上跑 ORB + E,threshold 按 undistort 像素设。换镜头后若只更新 K 不更新 dist 文件,边缘 match 会先坏——比 center reproj 更早报警。
7. fisheye 分支选型
fisheye.calibrate, fisheye.initUndistortRectifyMap 用不同多项式;迁移镜头类型时 dist 必须重标。去畸变后有效 FOV 变小,feature ROI 要调整。验收时 undistort 拍横平竖直建筑线肉眼看弯折;hold-out 角点 projectPoints reproj,边缘不应系统性大于中心。
8. 失败与验收
| 现象 | 查什么 |
|---|---|
| 去畸变后直线仍弯 | dist 阶数不够 / K 与 remap 不一致 |
| 边缘 feature 全假 | 未 undistort 做 epipolar |
| fisheye 用 pinhole | 换 fisheye API |
reprojection 仍大,先查 object point 单位(mm vs m)和 board 尺寸,再查 dist 阶数。四边 HoughLinesP 看曲率是现场快速自检。dist 与 map 版本写进 launch,启动 assert (w,h) 与标定一致。
10. 案例:中心标定 VO 边缘崩
广角 VO 只标定板子扫中心 60% 视场,全局 reproj 0.15 px,边缘 epipolar 全歪。补采四角后 k1 变化 20%,边缘 inlier 率升 25 pt。上线 checklist 增加「标定图四角覆盖」人工抽检,而不是只看 RMS 数字。dist 与 map 必须同版本发布,换镜头 serial 即触发重标流程。
11. 与 stereo rectification 的联动
双目标定 dist 错时,rectify 后 y-disparity 仍大,工程师去调匹配参数——根因仍是 dist。rectification 不是美化,是把极线变成水平线;dist 与 K 必须同标定文件。换镜头后即使 baseline 不变,也要 dist+map 全套重生成,不能只换左目 K。鱼眼与 pinhole 的 yaml 字段名应区分,部署脚本 load 前 assert model_type 与 API 一致,避免 projectPoints 用错系数长度。标定间温漂大时 schedule 定期 re-cal,dist 漂移会在边缘 match 上先于 center reproj 报警。fisheye 与 pinhole 混用 API 的 code review 红线:看到 calibrateCamera 用于超广角镜头直接 question。Release checklist 含 undistort 四边直线目视项。Wide FOV 换 narrow 镜头时 dist 文件必须废弃重建,不能 scale 旧系数凑合。上线前抽检 undistort 四边直线,弯则拒收标定包。
畸变校正不是「画面好看」的滤镜,是多视图几何成立的前提。
相关
也可以看看
johan's blog