拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于Pytorch的视觉操作关系推理与多物体抓取系统实战

简介本资源是一个面向机器人视觉与工业自动化领域的PyTorch实战项目聚焦于视觉操作关系推理与多物体协同抓取任务适用于具备深度学习基础的算法工程师、高校研究者及智能机器人方向开发者。系统基于VMRD数据集训练验证融合Cascade R-CNN实现高精度目标检测与ROI提取并创新性引入旋转矩形锚框的FCN网络显著提升对倾斜/旋转物体的定位与关系建模能力可直接支撑服务机器人、仓储分拣等场景的抓取策略生成。压缩包共7个文件4个Python源码含main.py与test11.py核心模块、1份README.md说明、1个说明文件.txt及1个附赠资源.docx总大小仅45KB轻量但结构完整涵盖模型构建、训练流程、数据加载与推理接口等关键环节。目前已有55人学习下载资源提供即用型代码框架、清晰的模块划分与配套文档便于快速复现、二次开发或嵌入实际机器人视觉系统。1. 项目介绍从“看见物体”到“理解操作关系”做机器人抓取的朋友应该都有同感单纯把目标检测做到99%的mAP机械臂实际抓取时依然会翻车。为什么因为抓取不是“看见东西就伸手”它涉及两个层次的推理第一层是“那里有什么”第二层是“这些东西之间能做什么操作”。比如桌上有杯子和盘子它们之间是“放在上面”的关系有剪刀和纸是“剪裁”的关系。如果机器人不理解这层关系就只会傻乎乎地伸手去抓结果把杯子撞倒、把剪刀带翻。我在实际项目中做的这套“基于Pytorch的视觉操作关系推理与多物体抓取系统”核心就是解决这个问题。它基于VMRDVisual Manipulation Relationship Detection数据集思路是先用Cascade R-CNN做目标检测和ROI提取再通过带有旋转矩形锚框的FCN网络完成操作关系的推理最终把“物体在哪里”和“物体之间能做什么”两件事一起算出来喂给机械臂做抓取规划。这篇文章把我从数据准备、模型搭建、训练调试到最终部署的完整过程写下来。里面包含了不少踩过的坑比如旋转锚框的标签匹配怎么算IoU、Cascade R-CNN的多级阈值怎么和VMRD的类别分布适配、关系推理分支的loss权重怎么调才不崩。适合正在做抓取感知、操作关系理解或者想复现VMRD相关工作的人参考。2. 整体方案设计为什么是“Cascade R-CNN 旋转锚框FCN”2.1 VMRD任务到底在做什么VMRD数据集发布自ECCV 2020全称是Visual Manipulation Relationship Detection。它不同于传统的目标检测数据集标注的不只是“物体的类别和框”还有物体两两之间的操作关系Manipulation Relationship。具体来说关系分为两类一类是“操作者-物体”如手拿着马克杯另一类是“物体-物体”如杯子放在桌子上、剪刀剪纸张。整个数据集的标注体系包含物体类别如马克杯、剪刀、方形木块、圆形木块、胶带等桌面常见物品操作关系三元组(subject, relation, object)比如(手, hold, 马克杯)、(杯子, on, 桌子)物体框水平矩形框旋转角度信息这也是后面要用旋转锚框的原因这个任务的核心难点在于关系推理不是简单的“框与框的IoU”能解决的。比如杯子和桌子之间的IoU可能很小但在语义上它们是“放置”关系手和杯子的框高度重叠但到底是“握”还是“触碰”需要更细粒度的特征来区分。这就需要模型不仅会检测还要会做区域间的交互推理。2.2 为什么选Cascade R-CNN而不是Faster R-CNN如果你只做“检测”这一步Faster R-CNN完全够用。但我的场景是“检测关系推理”检测质量直接影响关系预测的准确性。这里有两个关键问题关系推理的输入特征是成对ROI的联合特征如果某个ROI框得不准比如偏移了10个像素特征交互时会把背景噪声也带进去关系分类就容易被带偏VMRD数据集中有不少小物体和遮挡物体单级IoU阈值的检测器容易产生低质量proposalCascade R-CNN的核心思路是用三个级联的检测头IoU阈值从0.5逐步提升到0.6、0.7。这样做的好处是每一级检测头都在前一级的基础上精化proposal相当于“三次质检”最终输出的ROI质量远高于单级检测器。实测下来在VMRD上Cascade R-CNN的proposal质量比Faster R-CNN高不少关系分类的mAP也因此提升了3到4个百分点。注意Cascade R-CNN的三个检测头不是简单的多次推理而是每一级都用上一级输出的proposal重新采样、重新回归。训练时三个头都参与loss计算推理时只走最后一个头的输出。2.3 旋转矩形锚框的必要性VMRD数据集里的物体有一个显著特点很多物体不是水平对齐的。比如马克杯的把手朝向任意角度、剪刀斜着放、方形木块旋转45度。如果用水平锚框框里会包含大量背景区域特别是在物体密集堆叠的桌面场景中一个水平框可能同时框住两个物体直接导致后面的关系推理输入特征混乱。旋转矩形锚框的思路是在RPN阶段为每个位置生成多个角度的锚框通常是-90°到90°之间均匀采样几个角度然后回归参数从4个变成5个(x, y, w, h, theta)。这里theta就是旋转角。检测头输出的也不再是水平框而是带角度的旋转框。旋转框和水平框之间的IoU计算不能直接用标准IoU公式需要计算两个旋转多边形之间的交并比。这个操作没有GPU原生支持我用的是OpenCV的cv2.rotatedRectangleIntersection接口在CPU上算或者用shapely的Polygon.intersection。训练时如果每张图都实时算旋转IoU速度会非常慢所以要预先缓存或做批量处理。2.4 FCN网络如何做关系推理关系推理分支我采用的是FCN结构。具体做法是对一对ROI比如手和马克杯从特征图上裁剪出对应的区域分别经过ROI Align统一尺寸我设为7×7然后拼接成一个14×14×C的特征图输入到一个小型FCN中最终输出关系类别的概率分布。这里为什么要用FCN而不是直接拉平接全连接层两个原因 一是空间信息保留。关系类别对空间位置非常敏感比如“left”和“right”就是纯粹的空间关系全连接层会把空间位置打散FCN通过卷积保持空间结构。 二是参数量更少、更容易收敛。VMRD的关系类别数量有限大约10来种一个小型FCN就足够拟合不需要堆参数。3. 数据准备与预处理VMRD数据集使用细节3.1 数据集目录结构和标注格式VMRD数据集可以从官方网站下载解压后目录结构大致如下VMRD/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── annotations/ │ ├── vg_vmr_train.json │ ├── vg_vmr_val.json │ └── vg_vmr_test.json └── classes.txt标注文件是COCO风格的JSON格式关键字段包括images每张图片的id、宽高、文件名annotations每个物体的bbox[x, y, w, h]和类别idrelations关系三元组列表每个关系由subject_id、object_id和relation_id组成有一点要注意VMRD的标注中物体框的坐标是水平框并没有直接提供旋转角度。旋转角度信息需要我自己通过物体的掩膜或者几何特征来估计。官方没有提供掩膜标注所以我的做法是通过物体框的宽高比和上下文信息推断旋转角。如果物体框明显是长条形比如剪刀就根据框内边缘方向计算主方向角如果接近正方形比如木块则默认角度为0。这个推断并不完美但对训练来说够用了。3.2 数据增强策略VMRD数据集的规模不大训练集大约5千多张图如果不做增强模型很容易过拟合。我采用了以下几类增强策略随机水平翻转翻转时需要注意关系三元组的subject和object顺序也要对应翻转不能只翻图片不翻标注随机亮度/对比度扰动由于桌面场景光照变化大这对提升泛化能力帮助明显随机旋转小角度旋转后所有box坐标都需要重新计算比较麻烦我控制在±10度以内多尺度训练图像短边在480-800之间随机缩放长边不超过1333训练时有个容易忽略的细节随机翻转会改变关系的“左右”语义。如果你预测的关系包含“left”“right”翻转后必须把left和right的标签互换否则模型学到的方向语义是矛盾的。3.3 关系标签的类别分布处理VMRD中的关系类别分布极不均衡。我统计了一下出现频率最高的几个关系例如“on”“hold”占据了绝大多数样本而一些细粒度的关系如“pull”“push”数量很少。这种长尾分布如果不处理模型会倾向于把所有关系都预测为常见类别。我的处理方案是关系分类分支使用带类别权重的交叉熵损失权重与类别样本数的倒数成正比对“无关系”样本做负采样一张图片中物体对的数量是O(n²)但真正有关系的对很少。如果所有物体对都参与关系分类训练负样本会淹没正样本。我只保留正样本对随机采样的负样本对数量约为正样本的3倍这里说下采样细节。假设一张图里有6个物体那么物体对就是6×5/215对。如果其中只有2对有标注关系剩余13对就是负样本。不是全部丢弃负样本因为关系分类器也需要知道“没有关系”长什么样。但13个负样本全部参与训练会比例失衡所以我按正负比例1:3采样只保留6个负样本。4. 模型架构实现与训练细节4.1 主干网络选型我尝试了ResNet-50和ResNet-101两种主干最终线上使用的是ResNet-50。原因是VMRD数据集规模有限ResNet-101的表达能力虽然更强但在千张级别的数据上更容易过拟合训练时间也更长。ResNet-50搭配FPN特征金字塔已经能覆盖多尺度物体尤其是桌面场景中大小差异明显的物体马克杯和剪刀尺寸差别很大。4.2 旋转锚框的RPN设计RPN部分的修改是这套系统最核心的工程点。原来的RPN为每个位置生成3种尺度和3种宽高比共9个锚框。我在这个基础上增加了旋转角度的维度每个位置额外生成多个角度的锚框。这里有个工程取舍如果把角度维度直接并入锚框枚举锚框数量会爆炸。假设原来9个锚框增加5个角度就是45个RPN的计算量和内存占用会翻好几倍。我的做法是对于接近正方形的物体只生成0°、45°、90°三个角度的锚框对于长条形物体宽高比大于2额外生成-45°和135°两个角度角度预定义不参与学习学习的是每个锚框的角度回归残差实际效果这种设计在VMRD上的召回率相比纯水平锚框提升了约8个百分点主要提升在剪刀、胶带等长条形物体的检测上。4.3 旋转框的目标匹配策略旋转框的训练匹配比水平框复杂。水平框可以直接用IoU做匈牙利匹配但旋转框的IoU计算没有现成的CUDA实现用CPU算又慢。我用了一个折中方案先用水平外接矩形即旋转框的AABB包围盒的IoU做初步筛选快速排除大量非匹配锚框对筛选后的候选框再用精确的旋转IoU做最终匹配这样既控制了计算量又保证了匹配精度。在整个训练过程中RPN阶段的目标匹配耗时约占十分之一是可以接受的。4.4 关系推理分支的输入构造关系推理分支的输入是一对候选框的特征。具体实现流程从Cascade R-CNN的最后一个检测头拿到高置信度的检测框得分大于0.5对每一对检测框从FPN的P2-P5层中按框的尺寸选择对应层应用ROI Align分别提取特征将两个ROI特征在通道维度上拼接输入FCN关系分类器这里有个细节两个ROI的区域大小可能差异很大比如手和桌子直接把特征拼接会让大物体的特征主导分类。我做了归一化两个ROI的特征分别做L2归一化后再拼接同时额外加入两个归一化的几何特征中心点距离和面积比作为FCN的附加输入通道。这个操作实测让关系分类的mAP提升了2个百分点左右。4.5 损失函数设计整个网络的损失函数分为三部分检测损失Cascade R-CNN的标准损失RPN分类回归三个检测头的分类回归关系分类损失带类别权重的交叉熵常规正则化权重衰减系数0.0001关系分类损失的权重系数我设为了1.0检测损失的权重也是1.0。最开始我把关系分类权重设为0.5发现模型倾向于优先优化检测分支关系分类收敛很慢调到1.0后两者平衡了很多。4.6 训练配置训练环境是单卡RTX 309024GBPytorch版本1.10CUDA 11.3。以下是关键训练参数参数值优化器SGDmomentum0.9初始学习率0.01学习率衰减第8和第11个epoch衰减0.1总训练epoch12batch size4预热warmup前500步线性预热从实际训练曲线看检测loss在第4个epoch左右就开始收敛但关系分类loss直到第8个epoch才趋于稳定。所以如果你的场景也包含多任务训练建议把总epoch数拉长一些不要因为检测loss收敛快就提前停止。5. 训练过程中的典型问题与排查实录5.1 旋转锚框角度回归不收敛我第一次训练旋转锚框版本时角度回归loss几乎不下降。排查后发现原因是角度回归的目标没有做好规范化。角度是一个周期性变量-90°和90°是同一个角度的两个表示。直接对角度差做L1 Loss会让模型在边界处产生巨大的梯度震荡。解决方案是把角度回归改成“带周期性的平滑L1损失”或者把角度拆成sin和cos两个值分别回归。我选择的是后者把角度theta拆成(sin(theta), cos(theta))两个值作为回归目标然后对回归出的值做atan2还原。改了之后角度loss迅速收敛。5.2 关系类别严重误判把“无关”预测成“on”训练到后期发现验证集上“on”关系放在上面的精确率很低大量负样本被误判为“on”。分析了错误样本之后发现是负采样比例的问题。我原本把正负样本比例控制在1:3但实际VMRD中“on”关系出现频率很高占了正样本的30%以上。这么高的类别频率配合1:3的负采样相当于在给“on”类别特供负样本。我调整了采样策略对每个batch确保“on”关系对应的负样本数量不超过其正样本数量的2倍同时增加其他稀有关系类别的正样本数量通过复制增强。调整后“on”的精确率稳定在了85%以上。这类问题很难通过单纯的调loss权重解决。建议多花点时间分析混淆矩阵对症下药比瞎调参数有效得多。5.3 ROI Align的坐标对齐问题VMRD的标注坐标是相对于原图的FPN特征图的坐标系统经过多次下采样后会产生偏移。如果直接用原图坐标除以stride来映射到特征图会有几个像素的偏差。对检测来说几个像素的偏差无所谓但对关系推理这种精细任务ROI位置的微小偏移会直接影响特征提取的质量。我的解决方案是严格使用Pytorch官方torchvision.ops.roi_align的实现传入的是原图坐标系的box不需要自己手动映射。roi_align内部会处理坐标变换。如果你是自己实现的ROI采样一定要注意坐标变换的细节特别是spatial_scale参数要设置正确。6. 推理与抓取规划的结合6.1 推理流程模型训练完成后推理流程分三步输入一张RGB图像Cascade R-CNN输出物体的旋转检测框和类别关系推理分支对每个物体对输出关系概率取概率大于0.6的关系作为推理结果一个典型的输出示例检测到的物体 - 马克杯 (置信度0.92, 旋转角-12°) - 手 (置信度0.88, 旋转角0°) - 盘子 (置信度0.95, 旋转角5°) 检测到的操作关系 - (手, hold, 马克杯), 置信度0.87 - (马克杯, on, 盘子), 置信度0.916.2 从关系推理到抓取策略拿到这些检测结果后怎么用呢我做了这样一个策略映射如果检测到(手, hold, 物体A)说明物体A正在被操作不应该去抓否则会和手发生碰撞如果检测到(物体A, on, 物体B)说明A在B上面抓A之前需要先确认B是否稳固如果B是易碎品需要考虑先移开A再处理B如果物体C没有与任何物体产生关系说明它是孤立的可以作为第一优先抓取目标这套策略听起来简单但实际部署时帮了大忙。最典型的场景是桌子上有剪刀和纸模型检测到(剪刀, cut, 纸)的关系机械臂就会先把纸移开再抓剪刀避免把纸带翻。6.3 与机械臂控制系统的接口关系推理模块输出的是结构化数据我通过ROS topic发布格式如下geometry_msgs/PoseArray detected_objects 自定义消息ObjectRelationship int32 subject_id int32 object_id string relation float32 confidence机械臂的抓取规划节点订阅这些消息按上面的策略生成抓取序列。整个系统的时延大约是检测150ms 关系推理80ms单帧总耗时230ms左右能达到接近4FPS的处理速度对低速抓取场景完全够用。7. 部署到Jetson平台的适配经验有不少朋友问我能不能在Jetson上跑这套系统。我实测过Jetson AGX OrinJetPack 6.2把推理速度压到了单帧约400msTensorRT FP16。这里有几个适配关键点Pytorch版本选择JetPack 6.2对应的是Pytorch 2.8.0官方预编译的wheel包需要从NVIDIA官网下载对应的轮子文件。注意不要在conda里直接用pytorch官网的安装命令那会装上CPU版或者版本不匹配模型导出ONNX再转TensorRTCascade R-CNN的ROI Align在导出ONNX时可能会遇到算子不支持的问题建议把ROI Align替换成Pytorch的torchvision.ops.roi_align对应的ONNX导出路径或者直接跳过转换用Pytorch推理实测下来Pytorch原生推理在Orin上单帧大约900ms用TensorRT优化后能到400ms。如果你的实时性要求更高有两个方向换更轻量的主干比如MobileNetV3或者降低ROI数量从300降到100。8. 实操心得与后续扩展做这个项目让我最有感触的一点是关系推理的瓶颈往往不在模型结构而在检测质量。如果检测框偏了再好的关系分类器也白搭。所以如果你准备在这个方向深耕建议先花时间把检测分支做扎实再考虑关系推理的改进。另外VMRD数据集本身规模有限模型的泛化能力受限于数据多样性。我在实际部署中发现数据集之外的场景比如不同光照、不同桌面纹理性能会有明显下降。一个可行的改进方向是用自监督预训练比如用DINO之类的视觉基础模型做backbone初始化或者用领域自适应方法做场景迁移。后续我计划做两件事一是把旋转框检测扩展到更多类别、更复杂的场景二是把关系推理从“类别分类”升级为“结构化描述生成”让机器人不仅知道“杯子和盘子是on关系”还能理解“杯子在盘子的中央偏左位置”。这些改进会让抓取规划更精准也更贴近真实世界的需求。如果你也在做方向类似的项目欢迎一起交流。尤其是在旋转锚框匹配、关系推理loss设计这两块环境不同、数据不同踩的坑很可能也不一样多聊聊总能少走些弯路。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门