binocular_calibration 双目标定数学原理 -Bouguet思想

该算子是Halcon 双目相机标定核心算子 ,本质是联合优化求解左右相机内参、畸变、相对位姿、全局位姿 ,基于针孔相机模型 + 透镜畸变 + 光束平差法 (Bundle Adjustment, BA) 实现全局最小二乘优化。

一、binocular_calibration算子

cpp 复制代码
binocular_calibration (
X, Y, Z,          // 世界坐标系 3D 标定点 (Xw,Yw,Zw)
RowsL, ColsL,     // 左图观测像素坐标 (v_L, u_L)
RowsR, ColsR,     // 右图观测像素坐标 (v_R, u_R)
StartCamParL,     // 左相机初始内参+畸变 [f,k1,k2,k3,p1,p2,cx,cy,sx,sy]
StartCamParR,     // 右相机初始内参+畸变
StartPosesL,      // 左相机所有姿态初始 (R,t)
StartPosesR,      // 右相机所有姿态初始 (R,t)
'all',            // 优化模式:'all' = 同时优化 内参+畸变+所有位姿+双目外参
CamParamL,        // 输出:优化后左相机完整参数
CamParamR,        // 输出:优化后右相机完整参数
NFinalPoseL,      // 输出:所有左相机最终位姿 (R,t)
NFinalPoseR,      // 输出:所有右相机最终位姿
cLPcR,            // 输出:右相机相对左相机的外参 (R_LR, t_LR)
Errors            // 输出:整体平均重投影误差(像素)
)

二、Bouguet思想

1、为什么要做立体矫正

原始双目现状

普通双目相机安装后,很难做到严格平行

  • 左右相机光轴不平行、成像平面不共面;
  • 极线是倾斜斜线;
  • 找匹配点需要在整张图 / 斜线上搜索,速度慢、误匹配多

校正目标(统一目标)

把任意姿态的双目,变换成理想平行双目

  1. 两相机光轴平行、成像面共面;
  2. 所有极线变为水平线 (匹配点一定在同一行);
  3. 匹配只需要一维同行搜索。

Bouguet 是已标定双目 的经典校正算法,也是 OpenCV 默认实现,最大特点:让两张图的旋转畸变最小

2、Bouguet 核心思想

核心总思想

已知右相机相对左相机的旋转R平移 t(基线)

  1. 先构造一个全局旋转,把基线方向强行转到水平 X 轴,让极线变水平;
  2. 再把左右相机之间的相对旋转 **** 平均拆分:左转一半、右转一半;
  3. 最终两相机相对旋转完全抵消、光轴平行,同时单张图像旋转角度最小,画面变形最少

分层拆解 3 个关键思路

a、对齐基线-极线水平
  • 双目极线倾斜的根源是基线(两相机光心连线)不是水平的 。 Bouguet 第一步:构造旋转矩阵,将基线向量旋转到标准坐标系的 X 轴,极点被推到无穷远,极线自然全部变成水平线。
b、平分相对旋转 → 最小图像畸变

假设左右相机原本有一个整体相对旋转 R。

  • 若只让右相机单独旋转抵消 R:右图旋转角度大,画面扭曲、边缘裁剪严重;
  • 若只让左相机旋转抵消 R:左图扭曲严重;
  • Bouguet 方案:把总旋转R拆成两半 R^1/2,左相机反向转半角,右相机正向转半角。 两图旋转幅度一致且最小,这是该算法最核心的优势
c、组合两次旋转 → 得到最终校正姿态

将「基线对齐旋转」和「半旋转补偿」结合,分别得到左、右相机的最终校正旋转,再结合相机内参完成像素重映射

分步原理(几何 + 数学)

约定:

  • 左相机坐标系为基准;
  • R:右相机相对左相机的旋转矩阵;
  • t:右相机相对左相机的平移向量(基线向量)

步骤 1:构造基线对齐旋转矩阵 R_rect

目的:让基线沿 X 轴,极线水平。 构建一组右手正交坐标系 r1,r2,r3

1、r1:新X轴=单位化基线

把两相机光心连线作为新X轴

2、r2;新Y轴(垂直于基线,抑制竖直畸变)

垂直于 r_1,且落在原相机成像平面法向平面内:

几何意义:垂直于基线 t,保证新 Y 轴在原始成像平面法平面内,抑制图像竖直方向畸变。

3、r3:新z 轴(右手系正交)

最终,整体校正旋转矩阵(将原始坐标系转到基线对齐坐标系):

R_rect的作用:把极点推到无穷远,让极线变为水平线。

步骤 2:拆分相对旋转(核心:平分旋转)

两相机原本存在相对旋转R,会导致光轴不平行。

旋转矩阵可以分解为旋转轴 + 旋转角 ,对总旋转求半旋转 R^1/2:

  • R^1/2:旋转角度变为原来 1/2,旋转轴不变;
  • R^-1/2:反向半旋转。

步骤 3:计算左右相机最终校正旋转

  • 左相机校正旋转:R_L = R_rect * R^-1/2
  • 右相机校正旋转:R_R = R_rect * R}^1/2
几何解释
  1. 先统一做R_rect:基线拉平,极线水平;
  2. 左相机反向转半角 ,右相机正向转半角
  3. 两者叠加后,原始相对旋转完全消失,光轴严格平行;
  4. 每一张图只转了「总旋转的一半」,畸变、拉伸、黑边最小。

步骤 4:图像重映射(工程落地)

有了校正旋转 +相机内参 K+ 畸变系数,对每个像素做:

原图像素 → 相机归一化坐标 → 乘校正旋转 → 重投影到校正图像 → 插值填充。 最终输出极线同行的校正图

总结:Bouguet 立体校正 = 基线拉平让极线水平 + 旋转平分让图像形变最小

工程实现对应(OpenCV 接口对照)

OpenCV 中 stereoCalibrate + stereoRectify 即为 Bouguet 方法

cpp 复制代码
// 输入:内外参、畸变系数、图像尺寸
stereoRectify(K1, D1, K2, D2, imgSize, R, t, R1, R2, P1, P2, Q);

三、基础数学模型

1. 针孔相机 + 径向畸变模型(Halcon 标准模型)

Halcon 相机内参 CamPar = [f, k1, k2, k3, p1, p2, cx, cy, sx, sy]

世界坐标系 → 相机坐标系

相机坐标系 → 归一化图像坐标

透镜畸变矫正(径向 + 切向畸变)

归一化坐标 → 像素坐标(最终投影)

2、重投影误差(优化目标函数)

3、双目外参cLPcR的数学意义

四、映射gen_binocular_rectification_map

参数 含义 说明
Image1/Image2 左右原始双目图像(输入) 仅用于获取图像尺寸,不参与像素计算
CameraParam1 左相机内参 + 畸变参数 Halcon 标准相机参数 CamPar 格式:fx​,fy​,cx​,cy​,k1​,k2​,k3​,p1​,p2​
CameraParam2 右相机内参 + 畸变参数 同左相机
RelPose 右相机相对左相机的位姿(姿态) Halcon Pose 类型:描述右相机在左相机坐标系下的 6 自由度位姿 (tx​,ty​,tz​,α,β,γ)
RectifMap1/RectifMap2 输出:左右校正映射图 核心输出,存储「校正后坐标 → 原图坐标」的映射关系,给 map_image 使用
RectifCameraParam1/RectifCameraParam2 输出:校正后相机内参 校正后平行双目模型的新内参
RectifPose 输出:校正后双目相对位姿 校正后理想平行双目姿态(光轴平行、基线水平)
Method 校正算法选择 常用:'bouguet'(默认、推荐)、'hartley'
Width/Height 校正后图像分辨率 自定义输出图像尺寸,可和原图一致或缩放

重点:Method='bouguet' 时,完全沿用前文讲的 Bouguet 立体校正数学框架

1、畸变逆矫正(去除原始镜头畸变)

根据输入畸变系数 D,对 p做逆畸变映射,得到无畸变归一化坐标。

2、投影到原始图像像素坐标

3、存储映射表

  1. 将每一组 \u',v')到(u,v) 存入 RectifMap1 / RectifMap2,支持后续插值。

总结:映射图 = 全像素反向投影 + 旋转 + 畸变矫正 的预计算结果

4、输出校正后参数

  • RectifCameraParam1/2:校正后平行双目统一内参;
  • RectifPose:校正后理想双目位姿(相对旋转为 0,仅保留水平基线)。

运行结果现象

  1. 校正前:同一物理点在左右图纵坐标不一致,极线倾斜;
  2. 校正后:同一物理点纵坐标完全相等,极线水平;
  3. 左右图像旋转幅度均等(各 \(3^\circ\)),图像形变、黑边最小。

关键特性、差异与常见问题

1. 'bouguet' vs 'hartley' 区别

  • bouguet基于标定参数,均分旋转,图像畸变最小,工业双目首选;
  • hartley基于基础矩阵,无需精确标定,无内参 / 位姿也可校正,但图像扭曲大。