手眼标定与相机内外参标定 报告(理论模型、主流算法)

手眼标定与相机内外参标定 报告(理论模型、主流算法)

机器人视觉 · 标定专题研究

手眼标定与相机内外参标定

理论模型、主流算法、OpenCV 实现与工程验证

INTRINSIC  ×  EXTRINSIC  ×  HAND–EYE

项目

说明

报告类型

技术研究报告 / 工程实施指南

研究对象

单目工业相机、机器人末端与工作站坐标系

算法范围

Zhang、PnP、Tsai–Lenz、Park–Martin、Horaud、Andreff、Daniilidis、Shah

实现基线

Python + OpenCV calib3d(以 4.13.0 文档为参照)

编制日期

2026 年 8 月 4 日

适用场景:机器人抓取、装配、视觉引导、三维测量、视觉伺服与数字孪生坐标对齐。

 

摘要与核心结论

机器人视觉系统要把图像中的观测转成机器人可执行的空间坐标,至少要完成三层标定:相机内参用于描述成像几何和镜头畸变;相机外参用于描述目标坐标系与相机坐标系之间的刚体变换;手眼标定用于建立相机与机器人末端或机器人基座之间的固定变换。三者不是互相替代的关系,而是一条串联的数据链。任何一个环节的坐标方向、单位或时间戳出错,都可能造成厘米级甚至完全发散的抓取误差。

结论 01  工程上不应只比较某个算法输出的矩阵数值,而应比较独立验证集上的闭环误差、旋转测地误差、平移误差和最终任务空间误差。

结论 02  数据几何通常比算法名称更重要。手眼数据必须包含绕至少两个不平行轴的显著旋转,并同时覆盖不同平移与景深;相机内参数据要覆盖画面中心、四角、不同距离和倾角。

结论 03  建议将 Park 方法作为稳定基线,同时运行 Tsai、Horaud、Andreff、Daniilidis;以留出位姿的闭环一致性与真实抓取/触碰实验选型。Eye-to-Hand 若同时未知“相机到基座”和“标定板到末端”,优先按 AX=ZB(Robot–World / Hand–Eye)联合求解。

图 1  从图像与机器人位姿到可验证手眼结果的完整数据链

报告结构

  1. 第 1 章:问题定义、坐标系和齐次变换记号
  2. 第 2 章:相机内参标定——模型、张正友法、采集与质量评价
  3. 第 3 章:相机外参标定——PnP、变换方向与固定工作站外参
  4. 第 4 章:Eye-in-Hand / Eye-to-Hand 方程推导
  5. 第 5 章:五类 OpenCV 手眼算法与联合标定方法比较
  6. 第 6–8 章:工程流程、实验设计、代码模板与故障排查
  7. 附录:数据格式、验收清单、核心推导与参考文献。

问题定义与统一坐标记号

1.1  三类标定分别解决什么问题

标定类型

关系对象

典型输出

作用

失效条件

相机内参标定

相机内部

K、畸变系数 d

像素射线、去畸变、度量成像

焦距/焦点/分辨率改变后通常要重标

相机外参标定

目标/世界 ↔ 相机

R、t 或 4×4 齐次矩阵

已知三维点与二维观测之间的位姿

相机或参考物相对位置改变后重标

手眼标定

相机 ↔ 末端/基座

^gT_c 或 ^bT_c

把视觉结果映射到机器人坐标系

相机安装、法兰、支架发生变化后重标

内参标定输出的每幅图 rvec/tvec 是“标定板到相机”的逐帧外参,它不是手眼矩阵;手眼矩阵在相机与末端刚性连接不变时应当是唯一常量。

1.2  齐次变换的方向约定

本文统一采用 ^aT_b 表示“把 B 坐标系中的点变换到 A 坐标系”。列向量约定下:

^a p = ^aT_b · ^b p,     ^aT_c = ^aT_b · ^bT_c,     (^aT_b)⁻¹ = ^bT_a

T = [ R  t ; 0  1 ],     T⁻¹ = [ Rᵀ  −Rᵀt ; 0  1 ]

旋转矩阵不能只取负号;平移的逆必须同时乘以 Rᵀ。

最常见的致命错误  机器人 SDK 可能返回“基座中的末端位姿” ^bT_g,也可能返回其逆;OpenCV solvePnP 返回“物体/标定板到相机” ᶜTt。两者方向不能凭变量名猜测,必须用一个已知点做正向变换验证。

1.3  坐标系定义

符号

英文

含义

典型状态

{b}

robot base

机器人基座坐标系

固定

{g}

gripper / tool

末端法兰或工具坐标系

随机器人运动

{c}

camera

相机光心坐标系

随安装方式而定

{t}

target

棋盘格、圆点板或 ChArUco 标定板坐标系

Eye-in-Hand 固定;Eye-to-Hand 常装在末端

{w}

world

工作站/测量世界坐标系

可与 {b} 或 {t} 重合,也可独立

图 2  针孔模型中的三维点、像平面和相机内外参

相机内参标定

2.1  成像模型与参数

s [u v 1]ᵀ = K [R | t] [X Y Z 1]ᵀ

K = [ fₓ  γ  cₓ ; 0  fᵧ  cᵧ ; 0  0  1 ]

其中 fₓ、fᵧ 是以像素为单位的焦距,(cₓ,cᵧ) 是主点,γ 是像素轴倾斜量(现代相机通常近似为 0)。K 只描述理想针孔投影;真实镜头还要用畸变模型修正归一化坐标。

x′ = x(1+k₁r²+k₂r⁴+k₃r⁶)+2p₁xy+p₂(r²+2x²)

y′ = y(1+k₁r²+k₂r⁴+k₃r⁶)+p₁(r²+2y²)+2p₂xy

OpenCV 常用 Brown–Conrady 模型,基本参数为 k₁、k₂、p₁、p₂、k₃;高阶 rational 模型可再加入 k₄–k₆,薄棱镜模型可加入 s₁–s₄,倾斜传感器模型可加入 τₓ、τᵧ。鱼眼镜头应优先使用 cv.fisheye 模块,不要强行用普通透视模型吸收超广角畸变。

2.2  张正友平面标定法

张正友法使用一个几何尺寸已知的平面模板,从多个未知姿态拍摄。每个姿态建立平面到图像的单应矩阵 H;利用旋转矩阵列向量正交且等长的约束,线性求出与 K 相关的对称矩阵,再恢复内参。随后恢复每一幅图的 R、t,并用最大似然意义下的非线性优化联合最小化重投影误差。原论文指出理论上少量姿态即可求解,但实际建议使用更多、几何分布更好的姿态。

  1. 建立标定板平面点 Pᵢ=(Xᵢ,Yᵢ,0),检测对应像素点 pᵢ。
  2. 每个视角估计单应矩阵 H,使 p ~ H·P。
  3. 由 H 的列向量约束构造线性方程,求取 K 的初值。
  4. 由 K⁻¹H 恢复各视角外参 R、t,并把近似旋转投影到 SO(3)。
  5. 联合优化 K、畸变参数和所有外参,使总重投影误差最小。

2.3  标定板选择

类型

优点

主要风险

适用

棋盘格

结构简单、成本低、资料多

局部遮挡会导致整板检测失败;黑白边界反光敏感

普通实验室与教学

圆点阵列

圆心亚像素定位稳定,适合工业打印/加工板

必须确认对称/非对称阵列定义与点序

高重复性工业标定

ChArUco

ArUco 身份编码 + 棋盘亚像素精度,可部分可见

板字典、尺寸和边界定义必须严格一致

手眼标定和大姿态变化

AprilGrid

标签身份明确,遮挡鲁棒,工具链成熟

与 OpenCV 原生流程的接口需额外实现

多传感器与科研系统

尺寸原则  算法中填入的是相邻角点或标记的实际几何尺寸,而不是外框尺寸。只要全流程单位一致,结果单位可用 m 或 mm;但手眼计算中相机 tvec 与机器人平移必须统一。

2.4  图像采集设计

图 3  内参和手眼数据都需要丰富的空间几何覆盖

  1. 固定焦距、焦点、分辨率、裁剪、缩放、binning 和 ISP 几何设置;自动对焦与电子防抖应关闭。
  2. 建议采集 15–30 张有效图像;数量只是起点,必须覆盖中心、四角、近距、远距和正负倾角。
  3. 让标定板占据画面较大比例,同时保留一部分边缘视角以约束径向畸变。
  4. 避免所有图都近似正对相机;至少包含绕水平轴和竖直轴的明显倾斜。
  5. 避免运动模糊、过曝、欠曝、打印纸翘曲和反光;高精度任务使用刚性加工板。
  6. 若后续工作温度、对焦距离变化显著,应按工作状态分组标定或建模温漂。

2.5  内参质量评价

eᵢ = ‖pᵢ − π(K,d,R,t,Pᵢ)‖₂,     RMSE = √(Σeᵢ² / N)

总 RMS 只能说明训练数据上的平均像素拟合,不能单独证明几何精度。应同时查看每幅图误差、误差在图像平面的空间分布、参数不确定度、去畸变后直线度以及留出图像的重投影误差。若某张图误差明显偏大,应检查角点错误、模糊、板面弯曲或错误尺寸,而不是立刻加入更多畸变参数。

指标

作用

建议做法

全局 RMS

快速比较同一数据集和同一模型

不作为唯一验收依据

per-view error

定位坏图和姿态弱约束

报告中保留每张图结果

留出重投影误差

检查泛化而非训练拟合

预留 20% 姿态不参与求解

直线度/边缘残差

检查畸变模型失配

观察画面边缘的直线与残差向量

参数稳定性

判断数据是否充分

重采样/Bootstrap,比较 K 与 d 的离散度

相机外参标定

3.1  外参的准确含义

外参描述参考物体或世界坐标系到相机坐标系的刚体变换。OpenCV solvePnP 的 rvec、tvec 使三维 objectPoints 从物体坐标系变换到相机坐标系,即 ᶜTₒ。它不是“相机在世界中的位姿” ^wT_c;后者需要求逆。

ᶜp = ^cT_w · 𝒘p,     ^wT_c = (^cT_w)⁻¹,     相机中心 𝒘C = −Rᵀt

方向验证  把标定板原点 [0,0,0,1]ᵀ 乘以 solvePnP 输出的 ^cT_t,结果应位于相机前方且 Z>0;再把结果投影回图像检查像素位置。这比仅看 tvec 的正负号可靠。

3.2  PnP 方法选择

方法

点数/结构

特点

建议

SOLVEPNP_ITERATIVE

≥4(一般)

LM 迭代最小化重投影误差

默认稳健基线;可由初值继续优化

SOLVEPNP_EPNP

≥4

非迭代高效估计

点较多或需快速初值

SOLVEPNP_IPPE

平面点

输出平面位姿的两个候选

标定板/平面目标,需消除二义性

SOLVEPNP_IPPE_SQUARE

4 个方形点

专用方形标记顺序

AprilTag/ArUco 单标记,必须遵守点序

solvePnPRansac

带外点

RANSAC + PnP

存在误匹配时先剔除外点,再 refine

对于平面标定板,正视、距离很远或图像占比很小时,深度和平面法向更容易不稳定。应增加倾角与板面占比,并使用 reprojection、cheirality(点在相机前方)和相邻帧连续性选择正确解。

3.3  工作站固定外参

如果目标是求固定相机到机器人基座的变换 ^bT_c,单次 PnP 只有在标定板到基座 ^bT_t 已知时才能直接组成:

^bT_c = ^bT_t · (^cT_t)⁻¹

如果 ^bT_t 未知但标定板固定在末端、末端位姿可读取,则属于 Eye-to-Hand / Robot–World–Hand–Eye 问题,应使用多姿态联合求解,而不是把某一帧 PnP 结果当成基座外参。

手眼标定模型与方程

图 4  Eye-in-Hand 与 Eye-to-Hand 的安装方式、固定量和待求量

4.1  Eye-in-Hand:相机安装在末端

输入:每个姿态的机器人末端到基座 ^bT_g(i),以及标定板到相机 ^cT_t(i)。未知固定量为相机到末端 X=^gT_c;标定板到基座 W=^bT_t 在采集中保持不变。每帧满足:

^bT_g(i) · ^gT_c · ^cT_t(i) = ^bT_t

取两个姿态 i、j 并消去固定的 ^bT_t,可得到经典方程:

Aᵢⱼ X = X Bᵢⱼ,     Aᵢⱼ = [^bT_g(j)]⁻¹^bT_g(i),     Bᵢⱼ = ^cT_t(j)[^cT_t(i)]⁻¹

OpenCV calibrateHandEye 直接接收所有绝对位姿序列并在内部构造相对运动。参数名 R_gripper2base / t_gripper2base 表示 ^bT_g;R_target2cam / t_target2cam 表示 ^cT_t;输出 R_cam2gripper / t_cam2gripper 表示 ^gT_c。

4.2  Eye-to-Hand:相机固定在机器人外部

相机固定在工作站,标定板刚性安装在末端。未知固定量通常有两个:X=^bT_c(相机到基座)和 Z=^gT_t(标定板到末端)。每帧满足:

^bT_g(i) · ^gT_t = ^bT_c · ^cT_t(i)

这类问题可写成 AX=ZB 或等价的 Robot–World / Hand–Eye 联合标定。联合求解的优点是不用预先精确知道标定板相对法兰的安装位姿。若使用 calibrateHandEye 的“角色替换”技巧,可把每个 ^bT_g 求逆为 ^gT_b 并作为第一组输入,输出解释为 ^bT_c;但这一做法依赖严格的方向约定,必须用闭环验证。对需要正式交付的系统,更推荐显式使用联合方程或 cv.calibrateRobotWorldHandEye。

4.3  可观测性与退化

  1. 所有运动都是纯平移:无法充分约束手眼旋转。
  2. 所有旋转轴互相平行或运动近似共轴:某些自由度不可辨识或病态。
  3. 旋转角度过小:相对运动接近单位阵,噪声被放大。
  4. 平移变化极小:旋转与平移耦合方法中的平移估计不稳定。
  5. 标定板在图像中总是很小或近似正视:PnP 的法向与深度误差传递到手眼结果。
  6. 机器人位姿和图像不同步:算法会把时延误差错误地解释为手眼外参。

运动设计建议  采集 15–30 个高质量姿态,覆盖绕至少两个不平行轴的正负旋转;相邻姿态角度不宜全都过小。对高精度系统,应从更多候选姿态中选择条件数更好的子集,并做时间同步或静止触发。

 

主流手眼算法研究与选型

5.1  分离求解与同时求解

将 A、B、X 拆成旋转和平移后,AX=XB 产生 RₐRₓ=RₓRᵦ 和 (Rₐ−I)tₓ=Rₓtᵦ−tₐ。分离法先求 Rₓ,再线性求 tₓ;实现简单、易分析,但旋转误差会传播到平移。同时求解法用双四元数或扩展线性系统把旋转和平移共同表示,能保留刚体运动耦合,但对尺度归一化、噪声模型和退化运动也更敏感。

算法

类别

数学工具

优势

风险

OpenCV

Tsai–Lenz

分离

最小旋转参数/几何线性化

经典、快速、解释直观

大噪声或旋转分布差时平移受旋转误差影响

CALIB_HAND_EYE_TSAI

Park–Martin

分离

SO(3)/SE(3) 李群对数

闭式最小二乘、工程基线稳健

接近退化运动仍会病态

CALIB_HAND_EYE_PARK

Horaud

分离

单位四元数

旋转表示紧凑、传统替代方案

四元数符号与线性系统需一致处理

CALIB_HAND_EYE_HORAUD

Andreff

同时/在线

Kronecker/线性系统

可扩展在线标定,旋转平移联合

需要有信息量的平移;噪声与尺度会影响线性解

CALIB_HAND_EYE_ANDREFF

Daniilidis

同时

单位双四元数/螺旋运动

统一表达旋转和平移,SVD 求解

归一化、符号和数据几何不佳时可能不稳定

CALIB_HAND_EYE_DANIILIDIS

Shah / AX=ZB

联合

Kronecker + SVD

同时求 Robot–World 与 Hand–Eye 两个未知变换

输入方向更复杂,需要更严格闭环验证

calibrateRobotWorldHandEye

5.2  各方法要点

Tsai–Lenz:通过运动轴关系先计算旋转,再由线性方程计算平移。论文特别强调需要绕不同轴旋转才能唯一恢复三维关系。适合作为经典基线和教学推导。

Park–Martin:在欧氏群上利用矩阵对数把旋转共轭关系转成向量配准,再闭式求解。对多姿态最小二乘实现自然,建议作为第一工程基线。

Horaud:使用单位四元数建立旋转约束,并提供先旋转后平移与非线性联合优化框架。原研究的稳定性分析指出,同时优化在噪声下可更稳健。

Andreff:从 Kronecker 形式推导线性系统,并面向在线场景递增处理运动。适合持续标定研究,但静态工业部署仍应与离线方法交叉验证。

Daniilidis:用双四元数把刚体运动视为螺旋运动,同时估计旋转和平移。理论表达优雅,但并不意味着对任何采集数据都必然优于分离法。

Shah:面向 AX=YB / AX=ZB 联合问题,采用 Kronecker 积和 SVD 构造闭式解,适合 Eye-to-Hand 中两个固定变换均未知的场景。

5.3  工程选型策略

  1. 同一批清洗后的数据同时运行五种 calibrateHandEye 方法,所有方法使用完全相同的输入方向和单位。
  2. 先检查结果是否为合法 SE(3):RᵀR≈I、det(R)≈+1、平移量级合理。
  3. 在训练集上计算 pairwise AX−XB 残差和恒定链 ^bT_g·X·^cT_t 的离散度。
  4. 在未参与求解的留出姿态上计算同样指标,避免选择过拟合结果。
  5. 用独立空间基准做任务验证,例如机器人触碰已知球心、针尖对孔或抓取标定块。
  6. 若多方法差异远大于重复采集噪声,优先回查数据方向、同步与姿态几何,而不是“投票平均矩阵”。

标准工程实施流程

阶段

关键动作

阶段 A:定义坐标与接口

画出 {b},{g},{c},{t},记录每个 API 返回的变换方向、旋转表示、长度单位和时间戳含义。

阶段 B:冻结相机配置

固定分辨率、ROI、焦距、对焦、曝光策略和畸变模型;确认部署配置与标定配置完全一致。

阶段 C:内参标定

采集覆盖充分的图像,检测亚像素角点,求 K 与 d,剔除坏图并用留出集验证。

阶段 D:同步采集手眼数据

每个机器人姿态稳定后同时保存图像、机器人绝对位姿、时间戳、关节角和质量标志。

阶段 E:逐帧 PnP

对每张图求 ^cT_t,检查 Z>0、重投影误差、标记数量和候选解。

阶段 F:手眼求解

按安装形式组装输入,运行多个求解器;保存全部输出和参数版本。

阶段 G:闭环与独立验证

计算 SE(3) 闭环残差、留出姿态误差、重复采集稳定性和真实任务空间误差。

阶段 H:部署与漂移监控

固化矩阵方向、单位、序列化格式与版本;支架碰撞、对焦变化或维护后重新验证。

6.1  数据记录规范

字段

示例

说明

sample_id

0001

图像与机器人记录的唯一键

timestamp_cam / robot

ns 或 μs

同一时钟域优先;记录触发与采样时刻

image_path

images/0001.png

保存原始、无二次缩放图像

T_base_gripper

4×4, row-major

明确是 ^bT_g;单位 m

T_cam_target

4×4

由 PnP 得到 ^cT_t;单位 m

corner_count / reproj

48 / 0.21 px

逐帧视觉质量

robot_status

steady=true

是否停止、是否到位、是否报警

calib_version

camA_20260804_v1

内参、板尺寸、机器人 TCP 和代码版本

6.2  时间同步

动态采集时,图像与机器人位姿的时间偏差会形成与速度成比例的空间误差:位置误差约为 ‖v‖·Δt,姿态误差约为 ‖ω‖·Δt。最稳妥的离线方案是“机器人完全静止—等待机械振动衰减—触发相机—读取同一时刻位姿”;连续运动场景则要使用硬件触发、统一时钟或时间偏移联合估计。

δp ≈ v·Δt,     δθ ≈ ω·Δt

实验设计与误差评价

7.1  数据集划分

建议至少进行三次独立采集,每次重新随机摆放姿态但不改变相机安装。每次数据按姿态分成 80% 求解集和 20% 留出集;不能把同一小范围连续帧随机拆到两边,否则留出集与训练集几何高度相似,会高估泛化能力。

数据子集

用途

最低内容

训练集

求 K/d 或手眼 X

丰富视角、覆盖完整工作空间

留出集

比较算法与超参数

包含新的姿态与距离

独立基准集

最终验收

不依赖同一标定板检测链的空间基准

重复采集集

稳定性/漂移

不同时间、相同硬件配置

7.2  手眼残差指标

Eᵢⱼ = (Aᵢⱼ X) · (X Bᵢⱼ)⁻¹

e_R = acos((tr(R_E)−1)/2),     e_t = ‖t_E‖₂

另一个直观指标是计算每帧的闭环常量 Wᵢ=^bT_g(i)·X·^cT_t(i)。理想情况下所有 Wᵢ 相同。可用 SO(3) 旋转均值与平移均值作为中心,报告旋转 RMS/95 分位数和平移 RMS/95 分位数。Eye-to-Hand 则检查 GᵢZ 与 XCᵢ 两条链是否一致。

7.3  验收指标体系

层级

指标

说明

验收原则

像素层

重投影 RMS / P95

角点预测与观测差

与像素尺寸、成像噪声和任务要求绑定

几何层

闭环旋转/平移残差

AX=XB 或链式常量误差

训练与留出结果接近

稳定层

Bootstrap/重复标定离散度

参数对采样变化的敏感度

输出置信区间而非单个矩阵

任务层

抓取/触碰/测量误差

最终系统误差

作为最终放行依据

参考而非硬门槛  普通清晰工业图像的内参重投影 RMS 常希望低于约 0.3–0.5 px;高质量机器人系统的手眼重复误差可能希望达到 0.1–0.3°、0.5–2 mm 量级。但这些数字不能跨设备直接套用,最终阈值应从焦距、工作距离、机器人重复定位、标定板精度和任务公差反推。

7.4  不确定度与误差预算

误差源

典型机制

控制措施

相机检测

角点噪声、模糊、畸变模型误差

亚像素检测、提高板面占比、留出验证

标定板

尺寸误差、非平面、热胀冷缩

刚性加工板、尺寸溯源、平面度检查

机器人

绝对精度、重复定位、TCP/基座误差

区分重复精度与绝对精度;必要时机器人本体标定

安装结构

支架柔性、重力变形、碰撞漂移

刚性安装、姿态载荷评估、周期复核

同步

图像与位姿时间偏差

静止采集、硬件触发、统一时钟

算法

线性化、局部最优、离群值

多方法、鲁棒筛选、联合非线性优化

8  OpenCV / Python 实现模板

以下模板展示关键接口和变换方向。实际项目应补充相机驱动、机器人 CSV/JSON 解析、异常处理、时间同步和结果序列化。OpenCV 版本升级后应重新运行单元测试与已知数据回归测试。

代码 1  棋盘格内参标定骨架

import cv2 as cv

import glob, numpy as np

 

pattern = (9, 6)          # 内角点列数、行数

square = 0.020            # 相邻角点距离,单位 m

objp = np.zeros((pattern[0] * pattern[1], 3), np.float32)

objp[:, :2] = np.mgrid[0:pattern[0], 0:pattern[1]].T.reshape(-1, 2)

objp *= square

 

object_points, image_points = [], []

image_size = None

for path in sorted(glob.glob('intrinsic/*.png')):

    gray = cv.imread(path, cv.IMREAD_GRAYSCALE)

    if gray is None:

        continue

    image_size = gray.shape[::-1]

    ok, corners = cv.findChessboardCornersSB(gray, pattern)

    if not ok:

        continue

    object_points.append(objp.copy())

    image_points.append(corners.astype(np.float32))

 

assert len(object_points) >= 12, '有效姿态过少或覆盖不足'

rms, K, dist, rvecs, tvecs = cv.calibrateCamera(

    object_points, image_points, image_size, None, None)

print('RMS(px)=', rms)

print('K=\n', K)

print('dist=', dist.ravel())

代码 2  PnP 与齐次变换方向

def T_from_rvec_tvec(rvec, tvec):

    R, _ = cv.Rodrigues(np.asarray(rvec, np.float64).reshape(3, 1))

    T = np.eye(4)

    T[:3, :3] = R

    T[:3, 3] = np.asarray(tvec, np.float64).reshape(3)

    return T

 

def invert_T(T):

    R, t = T[:3, :3], T[:3, 3]

    Ti = np.eye(4)

    Ti[:3, :3] = R.T

    Ti[:3, 3] = -R.T @ t

    return Ti

 

# object_points 是标定板坐标,corners 是像素坐标

ok, rvec, tvec = cv.solvePnP(

    object_points, corners, K, dist,

    flags=cv.SOLVEPNP_ITERATIVE)

assert ok

T_cam_target = T_from_rvec_tvec(rvec, tvec)  # ^cT_t

assert T_cam_target[2, 3] > 0                 # 粗略 cheirality 检查

代码 3  Eye-in-Hand 多算法求解

METHODS = {

    'TSAI': cv.CALIB_HAND_EYE_TSAI,

    'PARK': cv.CALIB_HAND_EYE_PARK,

    'HORAUD': cv.CALIB_HAND_EYE_HORAUD,

    'ANDREFF': cv.CALIB_HAND_EYE_ANDREFF,

    'DANIILIDIS': cv.CALIB_HAND_EYE_DANIILIDIS,

}

 

# T_base_gripper[i]:机器人 SDK 读取并确认方向为 ^bT_g

# T_cam_target[i]:PnP 输出并确认方向为 ^cT_t

R_g2b = [T[:3, :3] for T in T_base_gripper]

t_g2b = [T[:3, 3].reshape(3, 1) for T in T_base_gripper]

R_t2c = [T[:3, :3] for T in T_cam_target]

t_t2c = [T[:3, 3].reshape(3, 1) for T in T_cam_target]

 

solutions = {}

for name, method in METHODS.items():

    R_c2g, t_c2g = cv.calibrateHandEye(

        R_g2b, t_g2b, R_t2c, t_t2c, method=method)

    X = np.eye(4)                 # X = ^gT_c

    X[:3, :3] = R_c2g

    X[:3, 3] = t_c2g.reshape(3)

    solutions[name] = X

代码 4  闭环常量验证(示意)

def rotation_angle(R):

    x = np.clip((np.trace(R) - 1.0) / 2.0, -1.0, 1.0)

    return np.degrees(np.arccos(x))

 

def closure_stats(T_base_gripper, T_cam_target, X):

    # 每帧 W_i = ^bT_g(i) · ^gT_c · ^cT_t(i),理想情况下 W_i 恒定

    W = [G @ X @ C for G, C in zip(T_base_gripper, T_cam_target)]

    t = np.stack([w[:3, 3] for w in W])

    t_center = np.median(t, axis=0)

    t_err = np.linalg.norm(t - t_center, axis=1)

 

    # 简化旋转离散度:以第一帧为参考;正式项目可计算 SO(3) 均值

    R0 = W[0][:3, :3]

    r_err = np.array([rotation_angle(R0.T @ w[:3, :3]) for w in W])

    return {

        'translation_rms': np.sqrt(np.mean(t_err ** 2)),

        'translation_p95': np.percentile(t_err, 95),

        'rotation_rms_deg': np.sqrt(np.mean(r_err ** 2)),

        'rotation_p95_deg': np.percentile(r_err, 95),

    }

 

for name, X in solutions.items():

    print(name, closure_stats(T_base_gripper, T_cam_target, X))

8.1  Eye-to-Hand 角色替换示例

代码 5  Eye-to-Hand 的方向变换与解释

# 目标固定在末端、相机固定在外部:

# P_i = (^bT_g(i))⁻¹ = ^gT_b;仍使用 C_i = ^cT_t(i)

T_gripper_base = [invert_T(T) for T in T_base_gripper]

R1 = [T[:3, :3] for T in T_gripper_base]

t1 = [T[:3, 3].reshape(3, 1) for T in T_gripper_base]

 

R_cam2base, t_cam2base = cv.calibrateHandEye(

    R1, t1, R_t2c, t_t2c, method=cv.CALIB_HAND_EYE_PARK)

 

T_base_cam = np.eye(4)           # 输出在此解释为 ^bT_c

T_base_cam[:3, :3] = R_cam2base

T_base_cam[:3, 3] = t_cam2base.reshape(3)

 

# 必须验证:^bT_g(i)·^gT_t ≈ ^bT_c·^cT_t(i)

# 若两个固定变换均未知且需正式交付,优先使用 AX=ZB 联合求解。

8.2  必须加入的单元测试

  1. invert_T(T) @ T 与 T @ invert_T(T) 均接近单位阵。
  2. 每个旋转矩阵满足 RᵀR≈I 且 det(R)≈1。
  3. 把标定板点经 ^cT_t 变换后 Z>0,并能重投影到原角点。
  4. 用人工构造的真值 X 生成无噪声 A、B,所有求解器应恢复真值。
  5. 平移单位从 mm 统一到 m 前后,旋转结果不变,平移按比例变化。
  6. 打乱一帧机器人位姿与图像的对应关系后,闭环误差应显著上升。

常见失败模式与排查

症状

可能原因

优先处理

结果方向完全相反

把 ^bT_g、^gT_b、^cT_t、^tT_c 混用

用一个已知点验证每个 API;统一 ^aT_b 记号;按公式求逆

平移大 1000 倍或小 1000 倍

标定板用 m、机器人用 mm

数据入库时统一 SI 单位并保存 unit 字段

重投影很好但抓取很差

内参只拟合训练图;手眼/机器人绝对精度/同步错误

做留出闭环和独立触碰实验,拆分误差预算

不同算法差异巨大

运动退化、坏帧、时间错配或方向错误

检查旋转轴分布、逐帧 PnP、时间戳和链式常量

平移漂移明显,旋转较稳定

旋转误差向平移传播;平移激励不足;板尺寸错误

增加大角度与不同距离;复核尺寸;联合优化

某些姿态 PnP 翻转

平面二义性、正视、小目标

使用 IPPE 候选、Z>0、连续性和重投影共同判定

内参每次变化很大

自动对焦/变焦、视角覆盖差、板不平

冻结光学设置;重新设计姿态;使用刚性板

边缘去畸变仍弯曲

模型不足或边缘约束不足

增加边缘样本;再评估 rational/fisheye 模型,避免盲目过拟合

结果随机器人姿态变化

支架柔性、法兰/TCP 定义变化、线缆拉扯

机械加固;检查负载与 TCP;分姿态验证

静态数据正常,运动中失败

时间同步/滚动快门

静止触发验证;硬件同步;建模时间偏移与滚动快门

9.1  排查顺序

  1. 先查方向和单位:这是“完全错误”的最高概率来源。
  2. 再查每帧视觉质量:角点、PnP、Z>0、重投影与异常值。
  3. 再查机器人数据:位姿定义、TCP、基座、欧拉角顺序、时间同步。
  4. 再查数据几何:旋转轴、角度幅度、平移、景深与图像覆盖。
  5. 最后才比较算法和优化器,并在独立验证集上做选择。

10  推荐实施方案

推荐基线  ChArUco 或高质量棋盘格 + Zhang 内参 + solvePnP/IPPE + Park 手眼基线 + 五算法横向比较 + 留出闭环 + 独立任务空间验收。Eye-to-Hand 两个固定变换均未知时采用 Shah/Robot–World–Hand–Eye 联合求解。

阶段

推荐配置

交付物

内参

20±10 张覆盖充分图像;固定分辨率与焦点;基础 5 参数模型起步

K、d、图像尺寸、RMS、per-view error、留出误差

手眼采集

15–30 个静止姿态;两个以上非平行旋转轴;图像与机器人同键同步

原图、^bT_g、^cT_t、时间戳、质量字段

求解

Park 为基线,同时运行其他四法;Eye-to-Hand 联合求解

所有候选 X/Z、算法与版本记录

验证

训练闭环 + 留出闭环 + 重复采集 + 独立触碰/抓取

R/t RMS、P95、任务误差、置信区间

部署

矩阵方向、单位、坐标轴、序列化与校验和固化

版本化 YAML/JSON、验收记录、复核周期

10.1  分阶段验收门

验收门

通过条件

Gate 1:内参

留出重投影误差与训练接近;边缘直线度正常;参数在重采样中稳定。

Gate 2:逐帧外参

所有有效帧 Z>0、PnP 误差受控、候选解无跳变。

Gate 3:手眼数学闭环

训练与留出 SE(3) 残差都达标,多算法结果合理一致。

Gate 4:系统任务

独立空间基准上的抓取/触碰/测量误差满足业务公差。

Gate 5:耐久性

跨时间、温度和典型机器人姿态的漂移受控。

10.2  进一步研究方向

  1. 把内参、畸变、逐帧目标位姿、手眼和机器人基座/世界外参放入同一 bundle adjustment 联合优化。
  2. 在 SE(3) 上使用稳健核函数与离群值模型,避免少数错误 PnP 主导解。
  3. 联合估计相机—机器人时间偏移,适配连续运动采集。
  4. 用概率模型传播角点、机器人位姿和板尺寸不确定度,输出手眼协方差。
  5. 针对鱼眼、滚动快门、远心镜头或折射介质建立专用成像模型。
  6. 用主动姿态规划最大化 Fisher 信息或降低条件数,减少采集数量。
 

附录 A  结果文件建议格式

建议的 YAML 语义:字段名直接编码变换方向,不使用含糊的 extrinsic

calibration:

  version: camA_robot1_20260804_v1

  units: meter

  image_size: [1920, 1200]

  camera_model: pinhole_brown_conrady

  K: [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]

  distortion: [k1, k2, p1, p2, k3]

  handeye:

    configuration: eye_in_hand

    transform: T_gripper_camera       # ^gT_c:camera -> gripper

    matrix: [[...], [...], [...], [0, 0, 0, 1]]

    solver: PARK

  validation:

    reprojection_rms_px: ...

    closure_rotation_p95_deg: ...

    closure_translation_p95_m: ...

    task_error_p95_m: ...

附录 B  现场采集检查表

  1. □ 相机分辨率、ROI、焦距、对焦和图像方向已冻结。
  2. □ 标定板型号、字典、角点数、方格/标签尺寸和单位已复核。
  3. □ 机器人基座、法兰、工具/TCP 定义已冻结并记录。
  4. □ 已用已知点验证机器人 API 位姿方向。
  5. □ 图像与机器人位姿使用同一 sample_id 和时间戳。
  6. □ 每次曝光时机器人静止,或系统具备可靠同步。
  7. □ 姿态覆盖至少两个不平行旋转轴、不同平移和不同距离。
  8. □ 标定板在所有有效帧中清晰、无遮挡或满足标签检测要求。
  9. □ 已保存原始图像,不经过缩放、裁剪或二次压缩。
  10. □ 已预留独立验证姿态和最终任务空间基准。

附录 C  关键公式速查

项目

公式

点坐标变换

^a p = ^aT_b · ^b p

变换复合

^aT_c = ^aT_b · ^bT_c

刚体变换求逆

R⁻¹=Rᵀ,t_inv=−Rᵀt

相机投影

s·p = K[R|t]P

Eye-in-Hand 单帧链

^bT_g · ^gT_c · ^cT_t = ^bT_t

Eye-in-Hand 相对运动

A X = X B

Eye-to-Hand 单帧链

^bT_g · ^gT_t = ^bT_c · ^cT_t

闭环残差

E=(AX)(XB)⁻¹

旋转测地角

θ=acos((tr(R)−1)/2)

参考文献与权威资料

[1] Z. Zhang. “A Flexible New Technique for Camera Calibration.” IEEE TPAMI, 22(11), 2000. DOI: 10.1109/34.888718. 访问来源

[2] R. Y. Tsai, R. K. Lenz. “A New Technique for Fully Autonomous and Efficient 3D Robotics Hand/Eye Calibration.” IEEE TRA, 5(3), 1989. DOI: 10.1109/70.34770. 访问来源

[3] F. C. Park, B. J. Martin. “Robot Sensor Calibration: Solving AX=XB on the Euclidean Group.” IEEE TRA, 10(5), 1994. DOI: 10.1109/70.326576. 访问来源

[4] R. Horaud, F. Dornaika. “Hand-Eye Calibration.” The International Journal of Robotics Research, 14(3), 1995. DOI: 10.1177/027836499501400301. 访问来源

[5] N. Andreff, R. Horaud, B. Espiau. “On-line Hand-Eye Calibration.” 2nd International Conference on 3-D Digital Imaging and Modeling, 1999. DOI: 10.1109/IM.1999.805374. 访问来源

[6] K. Daniilidis. “Hand-Eye Calibration Using Dual Quaternions.” The International Journal of Robotics Research, 18(3), 1999. DOI: 10.1177/02783649922066213. 访问来源

[7] M. Shah. “Solving the Robot-World/Hand-Eye Calibration Problem Using the Kronecker Product.” Journal of Mechanisms and Robotics, 5(3), 2013. 访问来源

[8] OpenCV 4.13.0. “Camera Calibration and 3D Reconstruction / calibrateHandEye.” 官方 API 文档。 访问来源

[9] OpenCV 4.13.0. “Perspective-n-Point (PnP) pose computation.” 官方教程。 访问来源

[10] OpenCV 4.13.0. “Camera Calibration.” 官方 Python 教程。 访问来源

[11] K. H. Strobl, G. Hirzinger. “Optimal Hand-Eye Calibration.” IEEE/RSJ IROS, 2006. 访问来源

[12] I. Enebuse et al. “Accuracy Evaluation of Hand-Eye Calibration Techniques for Vision-Guided Robots.” PLOS ONE, 2022. 访问来源

资料检索与接口核对日期:2026 年 8 月 4 日。报告中的工程阈值为经验性参考,正式验收应由任务公差和完整误差预算确定。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐