该算子是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、为什么要做立体矫正
原始双目现状
普通双目相机安装后,很难做到严格平行:
- 左右相机光轴不平行、成像平面不共面;
- 极线是倾斜斜线;
- 找匹配点需要在整张图 / 斜线上搜索,速度慢、误匹配多
校正目标(统一目标)
把任意姿态的双目,变换成理想平行双目:
- 两相机光轴平行、成像面共面;
- 所有极线变为水平线 (匹配点一定在同一行);
- 匹配只需要一维同行搜索。
Bouguet 是已标定双目 的经典校正算法,也是 OpenCV 默认实现,最大特点:让两张图的旋转畸变最小。
2、Bouguet 核心思想
核心总思想
已知右相机相对左相机的旋转R 和平移 t(基线):
- 先构造一个全局旋转,把基线方向强行转到水平 X 轴,让极线变水平;
- 再把左右相机之间的相对旋转 **** 平均拆分:左转一半、右转一半;
- 最终两相机相对旋转完全抵消、光轴平行,同时单张图像旋转角度最小,画面变形最少。
分层拆解 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

几何解释
- 先统一做R_rect:基线拉平,极线水平;
- 左相机反向转半角 ,右相机正向转半角;
- 两者叠加后,原始相对旋转完全消失,光轴严格平行;
- 每一张图只转了「总旋转的一半」,畸变、拉伸、黑边最小。
步骤 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、存储映射表
- 将每一组 \u',v')到(u,v) 存入
RectifMap1/RectifMap2,支持后续插值。
总结:映射图 = 全像素反向投影 + 旋转 + 畸变矫正 的预计算结果。
4、输出校正后参数
RectifCameraParam1/2:校正后平行双目统一内参;RectifPose:校正后理想双目位姿(相对旋转为 0,仅保留水平基线)。

运行结果现象
- 校正前:同一物理点在左右图纵坐标不一致,极线倾斜;
- 校正后:同一物理点纵坐标完全相等,极线水平;
- 左右图像旋转幅度均等(各 \(3^\circ\)),图像形变、黑边最小。
关键特性、差异与常见问题
1. 'bouguet' vs 'hartley' 区别
bouguet:基于标定参数,均分旋转,图像畸变最小,工业双目首选;hartley:基于基础矩阵,无需精确标定,无内参 / 位姿也可校正,但图像扭曲大。