返回专辑
·Johan·4 分钟阅读

双目校正:极线平行之后

stereoRectify 求 R1,R2,P1,P2 使极线水平对齐;alpha 和 valid ROI 设错时,SGBM 在错的 1D 搜索线上匹配。

双目校正:极线平行之后

1. 残余 vertical disparity 说明前面全错

SGBM 参数调到极致,depth 仍系统性偏、边缘 fat。画 rectified pair 的极线,对应点垂直差标准差一点八像素——匹配在错的 一维搜索线上跑。我花在校正上的时间经常不比匹配少;残余 vertical disparity 说明外参漂移、畸变模型不一致、或 imageSize 与 remap 尺寸不符。校正把二维搜索降成一维,是 SGBM 能跑的前提;这一步错,后面全是 confident wrong depth,调 blockSize 只是在错误搜索线上做 confident wrong matching。

2. 目标与 API

校正后两图共面且极线水平,对应点满足 ,匹配变沿 scanline 的一维搜索:

python
R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(
    K1, dist1, K2, dist2, imageSize, R, T,
    flags=cv2.CALIB_ZERO_DISPARITY, alpha=0)
map1x, map1y = cv2.initUndistortRectifyMap(
    K1, dist1, R1, P1, imageSize, cv2.CV_16SC2)
left_rect = cv2.remap(left, map1x, map1y, cv2.INTER_LINEAR)

R、T 来自 stereoCalibrate。Q 四乘四给 reprojectImageTo3D;视差须 SGBM 十六倍定点输出除以十六后的 float。CALIB_ZERO_DISPARITY 让主点在两 rectified 图对齐,视差符号直观。

3. alpha 与 valid ROI

alpha 等于零:裁剪到有效像素,无黑边,视场变小——产线固定几何常用。alpha 等于一:保留全视场,有 black border。alpha 负一自动。getValidDisparityROI 给出有效视差区——ROI 外 depth 无意义,别在 black border 上算 RMSE。Q 符号错一个,depth 整片变负;用 known 平面 sanity check 是第一步。我会把 alpha、imageSize、Q 写进配置,启动时打印 baseline 与 Q 摘要。

4. 残余 vertical disparity 诊断

理想垂直差绝对值等于零。工程上统计 rectified pair 的垂直差标准差,应小于零点五像素:

python
dy = pts2_rect[:, 1] - pts1_rect[:, 1]
print('dy std', np.std(dy))

最大值大于两像素说明标定或畸变有问题。baseline 编码在 P2 与 fx 关系(符号依 OpenCV 约定);T 单位毫米与米是 depth 系统性偏的常见根因。温振导致外参漂移时,schedule 复标 stereoCalibrate 比调 SGBM 有效。

5. 失败模式

现象
匹配全错Q 或 baseline 符号
边缘 blackalpha / ROI
depth 系统性偏T 单位(mm vs m)
dy std 大外参漂移 / dist 不一致

6. 验收

rectified 图 horizontal line 叠加肉眼验;垂直差直方图;已知距离平面 depth RMSE。我会画 epipolar line 叠加图做 sanity check——比只看 depth 彩色图可靠。校正这一步对,SGBM 参数才有意义。

7. 案例:T 单位 mm 当 m 用

某项目 depth 系统性偏一千倍,查 Q 与 baseline 发现 stereoCalibrate 的 T 是毫米,下游当米用。单位错是 silent failure 经典——rectify 后先用已知距离平面 sanity check,比跑全场景 depth 再猜快。标定输出要注明单位,配置里 assert 合理范围。

8. 与 Q 矩阵、重投影联动

reprojectImageTo3D 要求 disparity 格式与 Q 一致。SGBM 输出除以十六后的 float 视差,配合 stereoRectify 输出的 Q,满足 [X,Y,Z,W]^T = Q [x, y, disparity, 1]^T。Q 错一个符号,depth 整片变负——这是必做的 known 平面检查,不是可选项。

9. 手动 check rectification

python
dy = pts2_rect[:, 1] - pts1_rect[:, 1]
print('dy std', np.std(dy), 'dy max', np.max(np.abs(dy)))

P1、P2 的 baseline 编码在 P2 与 fx 关系(符号依 OpenCV 约定)。我会画 epipolar line 叠加图肉眼验,比只看 depth 彩色图可靠。温漂大时 schedule 复标 stereoCalibrate,比调 SGBM 有效。

10. 配置与验收

alpha、imageSize、CALIB_ZERO_DISPARITY 写进 yaml;启动打印 Q 摘要与 baseline。验收:dy std 小于零点五像素;dy max 小于两像素;known 平面 depth RMSE;ROI 外不算 RMSE。校正错,后面全是 confident wrong depth。

11. 失败模式速查

匹配全错查 Q 或 baseline 符号;边缘 black 查 alpha/ROI;depth 系统性偏查 T 单位;dy std 大查外参漂移或 dist 不一致。每一步都有可观察现象,别在 SGBM 上死磕。initUndistortRectifyMap 的 imageSize 必须与实际 remap 尺寸一致,否则 map 与 Q 语义错位,depth 整片偏。stereoCalibrate 的 R、T 与 rectify 用的是同一套;标定后改 dist 不 rerun rectify 是常见 silent failure。getValidDisparityROI 外 depth 无意义,别在 black border 上算 RMSE。CALIB_ZERO_DISPARITY 让主点对齐、视差符号直观;alpha 零裁剪黑边最多,产线固定几何常用。温漂大时 schedule 复标,比调 SGBM blockSize 有效。Q 与 baseline 符号错,depth 整片变负——known plane 检查是必做项。stereoRectify 输出 roi1、roi2 与 getValidDisparityROI 一起用,ROI 外不算 depth RMSE。我会把 R1、R2、P1、P2、Q 与标定 yaml 绑定版本;remap 节点 imageSize 与标定一致,否则 map 与 Q 语义错位。rectified pair 上 dy std 小于零点五像素是 SGBM 前提;max 大于两像素说明标定或畸变有问题。我会把 alpha、CALIB_ZERO_DISPARITY、Q 摘要写进启动日志,方便现场对照。

← 全部文章

johan's blog