手眼标定与机器人视觉实战:从图像到抓取坐标的完整链路

发布时间:2026/9/17 15:32:03
手眼标定与机器人视觉实战:从图像到抓取坐标的完整链路 我最初看到TASK02这个标题的时候第一反应是手眼标定嘛不就是一个相机外参标定把calibrateHandEye跑通就能交差。真到做实验才发现计算机视觉一旦要和机器人联动问题清单完全变了——你要纠结的不再是mAP高不高、模型过不过拟合而是像素坐标能不能变成机械臂能走的路径相机坐标系和机器人基座坐标系之间的误差能不能控制在毫米级。这个任务把视觉感知与手眼协调放在一起其实是逼你从“会看”走向“能做”。下面这份笔记是我完成Datawhale组队学习TASK02之后整理的一份上手复盘覆盖手眼标定的原理与代码实现、深度估计的选型逻辑、3D重建在机器人任务里的作用以及一条从图像到抓取坐标的完整链路。无论你是刚入门的计算机视觉学习者还是已经会跑YOLO但没碰过机械臂的工程师跟着这条思路走一遍至少能少走我踩过的那几段弯路。1. 先把“为什么机器人需要视觉”这件事想透1.1 感知、决策、执行计算机视觉在机器人里的真实位置很多做纯计算机视觉的人第一次接触机器人项目会习惯性地把“视觉系统”当成一个独立模块输入图像输出检测框或者分割掩码然后任务就结束了。但机器人不是这样的它接收视觉信息之后还要做一系列决策最后通过运动控制去执行动作。视觉只是整个闭环里的“感知”环节它的输出必须能被“决策”和“执行”这两个下游模块消费。举个例子你用目标检测算法从画面里找到了一个马克杯检测框的坐标是(x_min, y_min, x_max, y_max)这对一个纯视觉任务来说已经算完成了。但机械臂要抓杯子它需要的是一个三维空间点比如“在机器人基座坐标系下杯子把手右侧两厘米处高度离桌面5厘米”。从二维检测框到这个三维抓取点之间需要完成相机内参建模、深度获取、坐标变换、手眼关系解算等一系列工作。这是机器人视觉和普通视觉最大的区别它最终的度量单位是米是毫米而不是像素。你在图片上识别得再准如果换算到机器人空间里差了几毫米照样抓不中。1.2 为什么视觉感知和手眼协调会被放进同一个任务TASK02把视觉感知与手眼协调放在一起我理解不是随便拼凑的。视觉感知解决的是“看到了什么、在哪里”手眼协调解决的是“看到了之后手怎么过去、怎么对准”。这两者本质上是一条链中间断裂任何一环任务都会失败。你可以这样理解视觉感知是在“人眼”层面建立一个对环境的理解而手眼协调则是在“小脑和脊椎”层面把视觉信息转换成肌肉运动的指令。人之所以能轻松抓到水杯是因为大脑在漫长的进化里已经建立了眼睛坐标系与手部运动坐标系之间的映射。机器人没有这种天生的映射就需要通过手眼标定这一类算法人为地建立“眼睛看到的位置”和“手能到达的位置”之间的数学关系。所以真正做这个任务时你至少会接触四块内容目标检测或者分割感知、深度估计感知几何、手眼标定几何运动、3D重建环境建模。这四个模块单独拿出来都能讲很久但合在一起才构成一个可用的机器人视觉系统。TASK02的聪明之处就是让你先在一个相对简化的任务里把这条链路打通。2. 手眼标定前先分清“眼在手上”与“眼在手外”2.1 两种构型的基本差异手眼标定里的“手”一般指机械臂末端执行器“眼”指相机。按照相机安装位置系统分为两种眼在手上eye-in-hand和眼在手外eye-to-hand。眼在手上相机固定在机械臂末端跟着机械臂一起运动。这种构型灵活相机可以凑近目标很多移动抓取场景都这么干。眼在手外相机固定在工作空间外面只负责盯着机械臂和目标区域。这种构型视场稳定不需要考虑相机线缆随机械臂运动带来的干扰工业工作站里很常见。两者在手眼标定里的求解目标不一样眼在手上要求的是相机坐标系到机械臂末端坐标系的变换眼在手外要求的是相机坐标系到机械臂基座坐标系的变换。写代码之前如果没先弄清楚自己属于哪种构型后面整个标定流程都会是错的。2.2 AXXB到底在解什么手眼标定的核心数学形式是AXXB很多教程直接把这个公式丢出来新手很容易懵。我用大白话解释一遍。假设机械臂从位姿A1运动到位姿A2同时相机观测同一个固定标定板得到了两次标定板在相机坐标系下的位姿B1和B2。机械臂的位姿可以通过运动学正解得到标定板的位姿可以通过PnP解得所以A1、A2、B1、B2都是已知量。未知量是那个固定不变的手眼变换矩阵X。由于X在整个运动过程中是不变的前后两次观测可以列出一个约束关系相邻两次运动中从机械臂基座到目标点的变换相等。整理之后等式就能化成AXXB。A由前后两次末端位姿计算得到B由前后两次相机观测计算得到X就是我们要解的未知矩阵。解这个方程需要机械臂和相机至少发生三次以上非共面的旋转运动。如果只是在同一平面内平移方程会是病态的解出来也不可信。所以我建议实际采集数据时把机械臂的姿态变化做得丰富一点抬高、偏转、俯仰、旋转交替来让旋转轴的分布在空间里足够分散。只想用两三组数据碰运气的话标定结果大概率会漂。2.3 数据采集的质量决定了标定上限花了一周时间调手眼标定算法最后发现是数据没采好这是我见过最多的情况。数据采集的几点经验值得写在最前面标定板要足够平整打印后贴在玻璃板或者刚性底板上别用软纸随便贴表面不平会直接带坏角点检测。光照要稳定太强的反光会让角点检测抖动太暗又提不亮特征点。标定板在图像里的尺寸不能太小太小会导致PnP位姿估计的噪声变大最终解出的手眼矩阵自然不准。机械臂末端位姿和标定板位姿必须一一对应。不要出现某张图片的机械臂角度记录错误这一步错了后面全错。数据量方面我通常采集10到20组不同姿态姿态覆盖度比绝对数量更重要。宁可采集15组姿态差异明显的也不要采集30组机械臂几乎没动的“伪数据”。对比维度眼在手上eye-in-hand眼在手外eye-to-hand相机位置固定在机械臂末端固定在工作空间外部标定板位置固定在工作空间内固定在机械臂末端待求变换相机到末端的变换相机到基座的变换视觉特点可灵活移动近距离观察目标视场固定适合全局监控常见场景移动抓取、自动巡检固定工位上下料、装配3. 手眼标定从公式到代码我建议的实现路径3.1 一次标定实验的完整数据流手眼标定不是一个孤立的算法它需要上游提供两块数据机械臂自身的位姿以及相机观测到的外部目标位姿。我建议按下面的顺序准备数据流先用棋盘格或者ChArUco标定板标定相机内参得到焦距、主点、畸变系数。把相机安装好眼在手上或眼在手外将标定板放到视野内。控制机械臂运动到预设姿态记录当前机械臂末端在基座坐标系下的位姿。同步拍一张标定板图像检测角点用solvePnP或者aruco.estimatePoseSingleMarkers解出标定板在相机坐标系下的位姿。重复步骤3和4采集10到20组数据。把所有位姿序列送入手眼标定求解器得到手眼矩阵。这里有一个容易忽略的细节机械臂位姿的记录要和相机图像的时间戳对齐。如果机械臂还在运动时就拍了照图像里的标定板位姿和记录下来的机械臂末端位姿根本不是同一时刻的状态标定结果一定会偏。条件允许的话最好在机械臂完全停稳之后再触发拍照。3.2 用OpenCV把问题变成几行调用OpenCV的calibrateHandEye已经把核心求解封装好了你不用自己写迭代优化。我给出一个眼在手上场景的调用示例方便理解数据组织方式import cv2 import numpy as np # 假设已经收集了两个列表 # R_gripper2base_list / t_gripper2base_list机械臂末端在基座坐标系下的位姿 # R_target2cam_list / t_target2cam_list标定板在相机坐标系下的位姿 R_gripper2base np.stack(R_gripper2base_list) t_gripper2base np.stack(t_gripper2base_list) R_target2cam np.stack(R_target2cam_list) t_target2cam np.stack(t_target2cam_list) R_cam2gripper, t_cam2gripper cv2.calibrateHandEye( R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, methodcv2.CALIB_HAND_EYE_TSAI ) print(R_cam2gripper:\n, R_cam2gripper) print(t_cam2gripper:\n, t_cam2gripper)这里的method除了CALIB_HAND_EYE_TSAI还有CALIB_HAND_EYE_PARK和CALIB_HAND_EYE_HORAUD等选项。我实测下来Tsai方法在数据质量一般时相对容易出稳定结果Park方法在姿态变化丰富时精度更好。如果只是做学习验证直接用Tsai就够了。注意calibrateHandEye的输入约定是“gripper to base”和“target to cam”。眼在手外的情况不能照抄这个参数顺序需要根据你的构型重新整理数据。强烈建议你在运行前先打印几个矩阵确认数据维度和语义不然解出来的X会在错误的方向上。3.3 标定结果应该如何验证跑通代码之后真正区分“会用API”和“真的会标定”的地方在于怎么验证结果。我常用的验证方法有三个看解的物理合理性。相机和末端之间的平移量应该和你实际安装的尺寸在同一个数量级。如果眼在手上标定出来的平移是几十厘米那肯定有问题。旋转矩阵正交性检查。手眼矩阵的旋转部分理论上应该满足R^T R I行列式为1。如果偏离明显说明数值解不稳定。实机验证。让机械臂带着相机运动到某个位置从相机图像里找到标定板上某个角点再通过手眼矩阵把它的坐标换到机械臂基座系最后让机械臂末端指向那个点观察偏移量。实机验证这一步最花时间但也是唯一能证明标定结果“可用”的手段。很多项目标定完只看重投影误差一到实际抓取就偏原因就是没有做这个端到端验证。4. 深度估计让机器人从“看见”升级到“会量距离”4.1 四种主流深度获取方案的对比深度估计在机器人视觉里的作用是把二维图像升级为三维空间信息。目前主流的方案无非是双目视觉、结构光、ToF和单目深度估计。方案基本原理优点主要的坑双目视觉两个相机视差三角测量室内外都能用成本相对低纹理缺乏区域失效计算量大结构光投射编码光斑按形变解深度低纹理物体也能重建受强环境光影响户外阳光下基本废ToF测量光信号飞行时间速度快实时性好边缘深度不准多台设备会互相干扰单目深度估计深度学习从单张图回归深度成本最低部署简单尺度不确定泛化差难以用于精确操作我自己的经验是在室内机器人平台上目前性价比最高的是RGB-D相机典型代表是Intel RealSense系列和微软Kinect系列。它们本质上是结构光或者ToF与普通RGB相机的组合能同时输出彩色图和深度图省去很多前期标定工作。如果要在室外或者阳光直射环境工作双目相机更稳一些但需要花不少时间做极线校正和立体匹配调优。4.2 单目深度估计看着很香为什么机器人不敢直接用这两年单目深度估计的学术进展很快模型可以端到端地从一张RGB图预测出看起来不错的深度图。但到了机器人场景一个致命问题就暴露了单目深度估计只能输出相对深度无法稳定还原绝对尺度。同样一张图像模型可能预测杯子在1米处也可能预测在1.2米处看起来相差不大但对机械臂来说20厘米的误差足以导致抓空。有人会问能不能用已知物体大小来约束尺度理论上可以比如检测到是一张A4纸就知道它的物理尺寸是210毫米乘297毫米从而反推距离。但这个方法在目标种类多、姿态变化大的真实场景里很脆弱。一旦物体被遮挡或者不是已知尺寸的刚体约束就失效了。所以我的结论是单目深度估计目前在机器人领域更适合做感知层面的粗估比如判断前方是否有障碍物、大致距离是多少用于避障和导航的粗规划。涉及抓取、装配这类需要毫米级定位的任务还是要靠RGB-D相机、双目视觉或者激光雷达来提供带尺度的深度信息。4.3 实际项目里的深度选型建议给准备做机器人视觉项目的同学一个相对省心的选型思路室内桌面级抓取直接上RealSense D435这类相机。它自带深度和RGB对齐官方SDK成熟社区资料也多。如果你的项目在强光环境或者需要远距离感知优先考虑双目激光雷达融合而不是硬着头皮用结构光相机在太阳底下硬扛。另外别忘了深度图本身也是有噪声的。尤其是物体边缘、反光表面、透明物体和黑色吸光材料深度值经常会出现空洞或者跳变。后续环节最好加一层中值滤波或者深度填充否则点云里会冒出很多“飞点”影响目标定位精度。5. 3D重建把零散深度信息拼成机器人能操作的世界5.1 深度图到点云第一步坐标投影拿到深度图之后第一步往往是把像素坐标投影成三维点云。这一步用到的核心公式很简单z depth(u, v) / scale x (u - cx) * z / fx y (v - cy) * z / fy其中fx、fy、cx、cy是相机内参scale是深度图的缩放系数。很多深度相机保存的深度值是16位整数需要除以一个系数比如1000才能得到以米为单位的真实深度。我见过有人在代码里忘了除scale结果整个场景被放大了1000倍机械臂直接朝远处乱抓。5.2 从多帧点云到完整模型单帧点云只有相机当前视角下的局部几何没法看到物体背面也没法得到完整的桌面场景。实际应用里通常会让机械臂带动相机或者旋转工作台从多个视角采集深度数据然后做点云配准。点云配准最常用的算法是ICP迭代最近点。它会不断寻找两片点云之间的最近点对迭代求解旋转和平移直到误差收敛。用ICP之前需要先给定一个初始位姿估计否则容易掉进局部最优。如果你有机械臂的运动学信息可以直接用当前机械臂末端位姿来估计两帧点云之间的相对关系这会大幅提升配准成功率。配准完成后再把所有帧融合到一个统一的体积模型里。常见的做法是TSDF截断符号距离函数融合把空间体素化每个体素存一个到最近表面的带符号距离值。TSDF的好处是能平滑噪声处理多帧数据时的冗余信息最后再用Marching Cubes算法抽取等值面得到一个网格模型。Open3D库对这些流程都有现成实现不必自己造轮子。5.3 重建质量如何影响下游抓取与导航3D重建不是“看着像”就完事它直接影响机器人能不能安全操作。如果点云有明显的空洞规划出来的路径可能直接穿过真实物体如果重建出来的模型表面有严重膨胀机械臂又可能永远无法接近目标。对于抓取来说目标物体的点云精度比网格表面平滑度更重要因为抓取点通常是从点云计算出来的而导航避障更关心的是占据信息是否完整有没有漏掉障碍物和悬空物体。我在项目里养成了一个习惯重建完之后先在点云可视化工具里从不同方向旋转检查一遍看有没有明显的飘浮噪点、空洞、偏差然后再让机械臂运动。宁可多花两分钟人工检查也不要让机械臂带着错误模型去执行任务。另外3D重建在移动机器人导航里还有一个重要应用把深度数据转成占据栅格地图或者八叉树地图比如OctoMap。这样路径规划模块才能知道哪里可以走、哪里不能走。一个常见坑是透明玻璃和镜面物体在深度相机里经常表现为空洞导致机器人以为前方没有障碍物直接撞上去。处理方法是多做几组视角融合或者结合激光雷达数据把玻璃区域补上。6. 手眼协调全链路一个抓取任务的完整拆解6.1 从像素坐标到机械臂基座坐标把前面的知识串起来看一个具体场景桌面放着一个马克杯机械臂要把它抓起来。第一步彩色图输入目标检测模型得到杯子在图像里的中心像素坐标(u, v)。第二步在深度图里读取该像素对应的深度值z。第三步利用相机内参把(u, v, z)投影成相机坐标系下的三维点。第四步利用手眼标定得到的变换矩阵把相机坐标系下的点变换到机械臂基座坐标系。第五步通过逆运动学求解机械臂各关节角控制机械臂末端移动到抓取位置。在眼在手上构型下坐标变换链是相机坐标系 - 机械臂末端坐标系 - 机械臂基座坐标系表达式是P_base T_gripper2base * T_cam2gripper * P_cam其中T_cam2gripper就是手眼标定求出来的结果T_gripper2base是机器人当前关节角下的运动学正解。两个量都是4x4齐次变换矩阵。这条链里任何一环出错最终抓取位置都会偏。这个流程在代码里实现并不难难的是如何保证每一步的精度都在可控范围。我通常会做一次“闭环验证”先用视觉算出目标点让机械臂移动到目标点上方然后人工观察机械臂末端与真实目标的偏差再反过来判断是检测的问题、深度的问题还是手眼矩阵的问题。6.2 视觉伺服标定误差的最后一道补偿手眼标定总会有残余误差单纯靠一次视觉定位然后开环执行精度通常有限。要进一步提高精度可以用视觉伺服。视觉伺服用相机的实时反馈来调整机械臂运动形成一个闭环。比如眼在手上的系统当机械臂接近目标时相机不断检测目标在图像中的位置计算它与期望位置之间的偏差然后实时调整机械臂的速度直到偏差收敛。这种方式的鲁棒性比纯开环好因为即使手眼标定有一点误差视觉反馈也能把机械臂“拉”回正确位置。不过视觉伺服也不是万能药。图像特征丢失、相机视野遮挡、运动过快导致图像模糊这些问题在实机上都可能触发。我的经验是开环定位负责把机械臂快速送到目标附近视觉伺服负责最后几厘米的精细对准两者配合既保证效率又保证精度。6.3 这条链路里我实际踩过的坑第一次做这个全链路项目时我犯过一个特别低级的错误目标检测给出的像素坐标是图像中心点但杯子中心在深度图上恰好落在杯口内部深度值跳变很厉害导致投影出来的三维点忽远忽近。后来我改成取目标框中心附近一个矩形区域的中值深度问题立刻缓解。深度图分析是典型的“一票否决”环节像素选错后面所有计算都是白费。另一个坑是深度图的时间对齐。RGB图像和深度图像来自不同传感器时间戳如果没对齐运动过程中拍摄的深度图会带重影。我后来在采集数据时强制机械臂停止运动后再拍照彻底规避了这个麻烦。如果你用ROS2尽量用message_filters做时间同步把彩色图和深度图按时间戳配对后再进入后续管线。7. 没有实体机械臂时如何用仿真把流程跑通7.1 仿真平台的选型思路很多人看到机器人视觉项目第一反应就是“我没有机械臂怎么办”。其实没有必要被硬件卡住现在仿真环境已经足够完成TASK02这类任务的核心验证。GazeboROS2是常见的开源方案CoppeliaSim以前叫V-REP适合快速搭机械臂场景Isaac Sim的渲染质量高但硬件门槛也高。仿真环境最大的好处是“真值随手可得”。你可以精确知道机械臂末端在哪个位置也可以精确知道相机外参拿这些数据去验证你的手眼标定算法到底解出了多少误差。我建议新手先在仿真里跑通全链路理解坐标变换的逻辑再上实体机这样排查问题会快很多。如果你预算有限但想动手Piper这类桌面机械臂搭配一个RealSense相机也足够复现整套流程了。7.2 用真值数据验证手眼标定算法在仿真里做手眼标定思路和实机一样只是数据来源更干净机械臂末端位姿直接从仿真器读取标定板在相机坐标系下的位姿可以通过仿真相机的外参直接换算。拿到这些数据之后故意加一些高斯噪声观察手眼标定结果如何随着噪声增大而变差是一个非常有效的学习方法。我在仿真里做过一次实验不加入噪声时标定出来的手眼矩阵和真值几乎一致加入0.5厘米的位姿噪声后平移误差涨到几毫米继续加大噪声标定结果直接发散。这个实验让我深刻意识到实机场景里的手眼标定精度很大程度取决于机械臂末端位姿的精度和相机位姿估计的精度而不是求解器本身。7.3 TASK02真正想训练的能力把视觉感知、手眼标定、深度估计、3D重建全部串起来之后我最大的感受是这个任务真正值钱的地方不在于你记住了多少公式也不在于你能调通多少API而在于你亲手把整条链路跑通了一遍。之后回到真实项目里你看到“抓取失败”的第一反应不再是盲目调网络、换模型而是先怀疑手眼矩阵、深度值、机械臂误差这些基础环节。这种“系统排查”的直觉才是TASK02最想训练的东西。我个人的体会是做机器人视觉不要一开始就追求“高级模型”坐标变换链、标定精度、数据质量这三样基本功比任何花哨的网络结构都重要。稳扎稳打把一条最简单的抓取链路跑通再往里面加功能你会发现后面的一切都顺很多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询