ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于YOLOV3和Pytorch的UR5机械臂视觉抓取系统实现

基于YOLOV3和Pytorch的UR5机械臂视觉抓取系统实现 这个系列博客写到第四部分终于轮到视觉这块了。前几篇已经把 Win10 下的 V-rep 仿真环境、UR5 机械臂加 RG2 夹爪的运动控制、还有 Kinect 相机的图像获取都铺好了路整套系统在仿真世界里基本能跑通。但一台机械臂光会按预定轨迹动没用桌面上工件位置稍微偏一点它就抓瞎。这第四部分要解决的就是这个问题让 UR5 真正“看见”目标物体用 YOLOV3 在 Pytorch 框架下做目标检测识别出物体在图像中的位置为后续 DDPG 强化学习决策提供关键的视觉输入。这篇文章我会从整体方案选型讲起把数据集怎么做、模型怎么训、训练完怎么接回 V-rep、像素坐标怎么换算成机械臂能用的世界坐标全流程捋一遍。适合正在做机器人仿真视觉抓取、或者打算把 YOLO 系列检测算法接进机器人项目的同学参考不管你是刚开始搭环境还是已经卡在某个环节应该都能找到对应的干货。1. 先把视觉在整套系统里的位置摆清楚1.1 完整的数据链路在做任何代码之前我习惯先把整个系统的数据流画清楚。我们这个项目的最终目标是让 UR5 机械臂配合 RG2 夹爪完成抓取任务而 DDPG 强化学习算法负责生成运动决策。这里面有个关键问题DDPG 输入的是什么在仿真环境里如果直接用物体的真实坐标V-rep 里其实很容易拿到那训练出来的策略到了现实世界根本没法用因为现实中没有可以直接读取坐标的接口。所以要走视觉这条更接近真实落地的路线Kinect 相机采集图像YOLOV3 检测出目标在图像里的像素位置再结合深度信息换算成三维坐标最后把处理好的状态信息喂给 DDPG。这条链路里的每一步都有坑但视觉部分往往是第一个大坎。YOLOV3 在整个系统里承担的是“感知层”角色它输出的检测框决定了后续所有控制逻辑的输入质量。检测不准后面 DDPG 学出来的策略也是空中楼阁。1.2 为什么选 YOLOV3 而不是其他检测模型很多朋友会问都这个时间点了为什么不直接用 YOLOv5、YOLOv8 甚至更轻量的模型这个问题我在选型时也纠结过最后坚持用 YOLOV3核心原因是三方面这个系列项目已经明确指定了 YOLOV3 Pytorch 的技术栈。对系列教程来说技术栈的连续性比单纯追求指标更重要。YOLOV3 结构经典原理相对容易讲清楚适合作为教学和二次开发的底座。YOLOV3 在仿真环境里精度和速度的平衡完全够用。V-rep 里的场景相比现实世界要简单得多算是“半受控环境”默认的 COCO 预训练权重微调一下就能有不错的效果。实测在 GTX 1660 上416x416 输入跑一遍推理大概 20-30ms一秒钟能处理几十帧完全够机械臂决策用。YOLOV3 是 YOLO 系列里结构设计和代码实现都比较清晰的一个版本拆分方便想改损失函数、改网络结构都比较容易。对于要做算法研究的同学理解 YOLOV3 再迁移到其他版本学习曲线会平滑很多。当然如果你是纯工程项目追求极致性能YOLOv8 这类新模型显然更好。但在这个系列里YOLOV3 承担的是“把检测链路跑通”的核心角色先把这条路走通后面换任何检测器都是替换模块的事。2. Win10 下的开发环境配置2.1 Pytorch 安装的两种方案这一部分原本应该是前面几篇的内容但考虑到视觉部分对依赖环境的要求比较特殊而且很多卡住的朋友其实就是卡在环境上我在这里重新梳理一遍。首先明确一点YOLOV3 的训练建议用 GPU。虽然 CPU 也能跑但训练一个像样的检测模型可能要几十个小时而 GPU 可能一两个小时就搞定了。我用的配置是 Win10 Python 3.8 CUDA 11.8 Pytorch 2.0.1。GPU 版的 Pytorch 安装推荐直接用 conda 建一个独立环境conda create -n yolo python3.8 conda activate yolo conda install pytorch2.0.1 torchvision0.15.2 pytorch-cuda11.8 -c pytorch -c nvidia安装完成后一定要在 Python 里验证一下 CUDA 是否真的可用import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果输出torch.cuda.is_available()为 True说明环境没问题。这里有个最常见的坑Pytorch 装的是 CPU 版或者 CUDA 版本和驱动不匹配。可以用nvidia-smi先查看自己驱动的最大支持版本再选择对应的 CUDA。注意nvidia-smi显示的版本是驱动支持的最高 CUDA 版本不代表你安装的 Pytorch 就是那个版本两者不要搞混。如果你是纯 CPU 环境或者显卡性能太弱建议改用 YOLOV3-tiny或者考虑用云端 GPU。别在 CPU 上硬跑完整版 YOLOV3浪费时间不说训练效果打折还容易劝退。2.2 YOLOV3 代码仓库怎么选YOLOV3 的 Pytorch 实现版本很多我当时比较了主流的几个最后选了 ultralytics/yolov3 这个仓库。原因很简单它在 YOLOv5 火了之后依然保持维护代码风格统一训练和推理的接口也很清晰而且把 cfg 解析、数据加载、训练流程这些全都封装好了开箱即用。另一个经典的仓库是 eriklindernoren/PyTorch-YOLOv3代码结构更加“教科书化”适合深度学习初学者拿来一行一行研读。但它的训练流程相对粗糙数据加载速度也比较慢真要拿来训大型数据集效率不高。我的建议是如果是跟着本系列做项目直接选 ultralytics 版本如果你是冲着学习原理去的可以结合 eriklindernoren 版本理解 Darknet53 结构和损失函数细节。注意克隆完代码后记得查看requirements.txt里的依赖版本。有些旧版本代码在 Pytorch 2.x 下会有兼容性问题主要是torch.nn.functional.interpolate的参数变化和小概率的torch.load默认weights_only参数调整。遇到类似报错直接按报错信息升级或降级对应依赖即可不用太慌。3. 数据集的来源与标注那点事3.1 在 V-rep 里用 Vision Sensor 批量采集图像很多做视觉算法的人在仿真环境里会忽略一个问题数据集从哪来如果全部人工从 V-rep 截图再手动标注那效率低到怀疑人生。好在 V-rep 提供了脚本化的图像采集接口可以批量生成大量带标签的训练数据。我之前在 V-rep 的场景里加了一个 Vision Sensor挂在 Kinect 模型的 RGB 相机位置分辨率设成 640x480。然后写了一个简单的控制脚本让相机围绕目标物体变换角度和位置每隔 0.1 秒采集一帧图像并保存到本地。关键代码如下-- 在 V-rep 的 child script 或者通过 remote API 调用 local sensorHandle sim.getObjectHandle(Kinect_rgb_sensor) local x, y, z 0, 0, 0 -- 设置保存路径和文件名编号 local fileIndex 0 while true do -- 读取图像数据 local result, resolution, image sim.getVisionSensorImage(sensorHandle) if result ~ -1 then -- image 是原始 RGB 数据需要转成 png 保存 local w, h resolution[1], resolution[2] local imageRGBA sim.transformBuffer(image, sim.buffer_uint8, {w, h, 3}, {0, 0, 3}) sim.saveImage(imageRGBA, {w, h}, 0, string.format(D:/dataset/img_%04d.png, fileIndex)) fileIndex fileIndex 1 end -- 移动相机到新位置或者是旋转目标物 -- 这里可以通过 sim.setObjectPosition / sim.setObjectOrientation 实现 end这个思路的核心优势是仿真环境里物体的真实位置是已知的。你完全可以在采集图像的同时从场景中读取每个物体的实际坐标和边界框信息直接生成 YOLO 格式的标注文件。这一步就是仿真环境做视觉最大的红利——标注成本趋近于零。3.2 自动标注的“作弊”捷径这招当时帮我省了至少一天时间强烈推荐给大家。V-rep 里每个物体都有自己的位置信息把物体中心投影到图像平面上就能算出它在图像里的像素坐标。结合已知的物体尺寸就能估算出近似的边界框。具体做法是从 V-rep 的sim.getObjectPosition获取物体在相机坐标系下的坐标然后根据相机内参做投影。V-rep API 可以直接获取物体的相对相机坐标我们需要的是以相机为参考系的坐标值-- 获取物体相对于 Vision Sensor 的变换矩阵 local objectPos sim.getObjectPosition(objHandle, sensorHandle) -- 此时 objectPos 是物体在相机坐标系下的位置 -- 如果物体在相机前方z 值代表深度得到相机坐标系下的坐标 (X, Y, Z) 后再用相机内参进行透视投影u fx * X / Z cx v fy * Y / Z cy这里 fx、fy 是相机焦距像素单位cx、cy 是主点坐标。V-rep 里的 Vision Sensor 属性里有perspective模式和orthographic模式默认是透视并且可以在 API 中拿到视角大小perspectiveAngle。焦距可以通过分辨率换算fx (width / 2) / tan(perspectiveAngle / 2)有了物体中心像素坐标再根据物体实际的物理尺寸估算边界框宽高。这里要注意物体在相机图像里的大小取决于它离相机的距离和朝向可以适当放宽边界框留一些余量后面模型也不会因为框太紧而学崩。用这种自动标注方式我大概半小时就生成了一千多张带标注的图像。生成的标注格式要统一转换成 YOLO txt 格式class_id x_center y_center width height # 归一化到 [0,1]注意V-rep 的图像坐标原点在左上角Y 轴向下这和大多数图像处理框架一致直接算就行。真正容易出问题的是宽度高度的归一化记得统一除以图像尺寸。3.3 数据增强的几个实用策略仿真图像有个天然问题过于干净。现实里光照变化、遮挡、背景杂乱这些在默认 V-rep 渲染里都不存在导致训出来的模型一到稍微复杂点的场景就掉链子。解决思路是在数据增强环节拉宽泛化边界。我常用的增强策略是随机亮度、对比度调整把图像调暗调亮模拟不同光照随机水平翻转注意翻转后 bbox 坐标要做相应变换
返回列表