ARTICLE DETAIL

资讯详情

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

托盘实例分割数据集:从目标检测框到逐像素掩码的AGV识别实战

托盘实例分割数据集:从目标检测框到逐像素掩码的AGV识别实战 简介托盘实例分割数据集面向物流自动化与工业视觉应用包含676张真实场景JPEG图像按训练、验证、测试划分为507、101、68张覆盖palletfront托盘正面与palletpocket托盘口袋两类关键部件适合用于YOLO格式实例分割模型的训练与算法验证。包内共有1354个文件主要包括jpg原图、txt多边形坐标标注、yaml配置文件以及docx说明文档压缩包大小约29.48MB目录结构清晰可直接加载到主流深度学习框架使用。标注采用细致的多边形边界可支撑托盘定位、抓取、堆叠与质量检测等任务也适合作为学术研究基准数据帮助开发者构建具备实际泛化能力的视觉模型。目前已有62人学习下载适合从事物流自动化、机器人视觉集成或实例分割算法研究的人员快速上手实践。1. 托盘实例分割数据集从“框住托盘”到“认出每一块托盘的轮廓”仓储AGV的托盘识别只靠目标检测框远远不够一板货物叠上去矩形框会把货物和托盘包在一起叉齿该插哪个点完全看不出来。实例分割把问题换成逐像素掩码每个托盘单独一个轮廓YOLO直接支持这种标注。这份托盘实例分割数据集就是为此准备的——像素级多边形标注、YOLO可直接读的txt格式典型的文件夹是images与labels分目录。适合做物流仓储视觉、AGV托盘识别、自动叉车作业监控的团队。下面拆解整个压缩包数据格式长什么样、训练参数怎么设、掩码怎么转成业务坐标以及我在这份数据上踩过的一串坑。从头跟一遍基本能判断它能不能落进你自己的产线。2. 为什么是实例分割而不是目标检测掩码带来的三个关键收益2.1 检测框算不出叉齿插入点掩码可以普通目标检测输出cx, cy, w, h是一个轴对齐矩形。托盘在过道上经常斜着放叉车是垂直于托盘短边插入的矩形框根本带不出角度信息。更麻烦的是托盘上叠着货物时矩形框的中心点被货物顶上去AGV拿这个点做叉取定位误差能到十几厘米。实例分割输出的是多边形轮廓。拿到掩码可以求质心、求最小外接矩形方向、算轮廓面积占比甚至利用掩码边缘拟合托盘底板的直线。托盘在画面里转了多少度、靠墙没靠墙、两板货是不是叠在同一托盘上掩码都能反映出来。我把这类数据集的最大价值总结成一句话它回答的不只是“图里有没有托盘”而是“托盘到底占据了哪些像素、长边朝向哪边”。关键行为目标检测实例分割输出形状矩形框多边形掩码位姿估计需要额外关键点模型掩码直接算角度与中心重叠托盘框大面积重叠每个实例独立掩码装载率估算不能面积占比可做粗估计算成本低略高但YOLO系列可接受这个表格不是用来证明实例分割“全面碾压”检测。检测的帧率更高、工程更简单如果你的现场只需要“有没有托盘挡住路径”目标检测更划算。但只要涉及叉取、倒车入位这类对位置精度有要求的动作掩码带来的几何信息就是刚需。2.2 数据集目录与标注格式长什么样压缩包解压后主流的YOLO分割数据集会把images和labels平级放训练集和验证集各一份。这份资料的目录结构我判断是下面这种常见组织方式datasets/pallet/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ ├── data.yaml └── classes.txtYOLO分割格式的txt和检测格式很像每行表示一个实例第一个数字是类别id后面是一串归一化后的多边形顶点坐标x1 y1 x2 y2……按顺序排列。和矩形框的四个数相比分割标注的坐标个数不固定这决定了这类数据集的质检重点顶点数少于6的多边形基本是无效标注坐标越界更是直接在训练时刷警告。我每次拿到新数据先跑一遍下面这个脚本import os from pathlib import Path root Path(datasets/pallet) lab_dir root / labels / train bad 0 for lab in lab_dir.glob(*.txt): for line in lab.read_text().splitlines(): parts line.strip().split() if not parts: continue cls int(parts[0]) coords list(map(float, parts[1:])) # YOLO分割的坐标必须是成对出现且归一化到 [0, 1] if len(coords) 6 or len(coords) % 2 ! 0: print(f多边形点数异常: {lab.name} - {line}) bad 1 if cls not in range(2) or any(c 0 or c 1 for c in coords): print(f类别或坐标越界: {lab.name} - {line}) bad 1 print(f发现 {bad} 条可疑标注)这段代码做了两件事一是检查多边形顶点合法性少于三个点六个坐标没法构成面二是确认类别id落在data.yaml配置的范围内。坐标越界通常是标注工具导出时没做归一化或者图像尺寸记错了。这些可疑标注不用急着删先把文件名列出来看一眼是不是集中在某几帧如果只是个别帧手工修正比全局重跑便宜得多。2.3 类别设计不要一上来就按颜色拆类别我见过不少人拿到托盘数据看到画面里有蓝色托盘、红色托盘第一反应就是按颜色拆类别。实例分割和检测一样类别越多模型要学的特征边界越细而颜色对叉齿插入点计算没有任何帮助。除非你的业务真的需要按颜色分流否则我更建议按工况拆空托盘、带货托盘顶多加一个破损或半遮挡托盘。如果压缩包里的data.yaml原本就定义了类别先用我上面的校验脚本确认每个类别都有足够样本。一个常见导向是空托盘类别的样本太少模型会把它并入背景表现在验证集上就是“空托盘漏检而带货托盘正常”。这种数据分布问题放到后面避坑章节里细说。2.4 实例分割不是语义分割同一个托盘要分开算语义分割给每个像素贴一个类别标签整张图所有托盘像素输出同一个连通域实例分割还要把同类对象再拆开让“1号托盘”和“2号托盘”各自拥有一份掩码。AGV上这两者的差别非常实际两个托盘并排放语义分割的掩码连成一块算中心点会落到两个托盘的缝隙里实例分割能给出两个独立掩码调度系统才能按每个托盘的独立位姿处理。判断一份数据是不是真正的实例分割标注不用看宣传直接打开labels里任意一张txt数一数是否存在多条相同类别id的记录。同一类别出现多行就说明标注层面已经做了实例级拆分这份数据才能用来训练YOLO分割模型。3. 把数据集喂进YOLO环境、配置与第一次训练3.1 环境准备先装ultralytics再解压数据训练环境我强烈建议先用官方ultralytics包跑通再去碰魔改分支。它把数据加载、增强、训练、导出封得很死对新手最友好同时对熟手也保留了足够的配置文件可调。pip install ultralytics yolo checksyolo checks会输出torch、cuda、GPU驱动各自的状态。这里有一个小习惯先跑校验再解压数据避免环境问题和解压问题混在一起排错会非常痛苦。版本方面我用的是8.x的ultralytics命令行参数在7.x到8.x之间有过一次调整如果你的教程来自更老的版本把yolo segment train这种写法和旧版yolo train tasksegment做个对照能省不少时间。解压用系统自带工具没问题但如果你在Windows下遇到诡异的“解压报错”先怀疑zip伪加密——部分打包工具会在文件头上写一个加密标志实际内容并没有加密Windows压缩文件夹会误判。解决方法是换成python的zipfile或者7-Zip重新解压后者通常能直接跳过这个标志。3.2 data.yaml路径写绝对还是相对YOLO的data.yaml有三个关键字段path、train、val。path指向数据集根目录train和val写相对路径。path: /home/you/datasets/pallet train: images/train val: images/val nc: 2 names: 0: empty_pallet 1: loaded_pallet我一般写绝对路径因为相对路径依赖当前工作目录训练脚本放在别的目录一跑就找不到数据。train和val保留相对路径这样数据整体搬家时只需要改path一个字段。names的顺序必须和标注txt里的第0列严格一致这是整个配置文件里最容易埋雷的地方——之前在另一个项目里我把names顺序调换过一次训练曲线全程正常推理时类别却整体错位排查了一整天才发现是配置问题。3.3 训练命令与参数怎么调数据校验脚本跑完、data.yaml指对路径后直接执行训练命令yolo segment train \ modelyolov8n-seg.pt \ datapallet.yaml \ imgsz640 \ batch16 \ epochs100 \ patience20 \ device0 \ projectruns/segment \ namepallet_seg几个参数按经验说。modelyolov8n-seg.pt是轻量级分割预训练权重首次跑通流程用它显存紧张时它能很快验证数据集本身有没有问题。imgsz640是默认值托盘场景如果现场相机分辨率高、托盘在远景里偏小可以改成1280代价是显存和推理耗时同步上升。batch按“显存装得下就大一点”的原则来16GB卡跑n-segbatch到32没问题。patience是早停轮数我习惯设20到30数据量小的时候训练震荡期靠后设太小会在收敛前误停。参数建议值说明imgsz640起步小目标明显时再上1280batch显存余量的70%先小后大跑通再增epochs100~200不要纠结早停兜底patience20~30防止前期震荡误停mosaic1.0默认出现贴边漏检时关掉mosaic这一行提前剧透一下实例分割的mask在mosaic增强里容易被裁剪吞掉如果训练到一半发现seg_loss降不下去把它关掉重跑往往是第一个验证动作。3.4 训练日志里哪些指标决定能不能用训练时终端每轮会刷好几个lossbox_loss、seg_loss、cls_loss、dfl_loss。对实例分割重点盯seg_loss它代表掩码预测的收敛程度。如果box_loss稳定下降而seg_loss波动先别急着加轮数回到数据去查那些多边形点数异常的标注。每个epoch结束后的验证阶段看metrics下的seg_mAP50和seg_mAP50-95。mAP50是宽松标准掩码轮廓只要大致对得上就给分mAP50-95对掩码边缘精度更严格这个分数才是你部署到产线上“轮廓贴不贴边”的预测指标。托盘识别更怕的是假掩码recall高但precision低意味着模型把地面反光、墙角也当成了托盘AGV会对着不存在的位置规划叉取路径比漏检危险得多。如果训练完发现precision和recall差异超过15个点先别动网络结构回到验证集把置信度阈值从0.25一路调到0.6观察recall曲线的掉速。掉速缓和说明误检集中在低置信度区阈值拉高就解决了掉速剧烈说明模型对托盘特征的置信本身不足单纯调阈值救不回来。4. 从掩码到业务坐标推理可视化与模型导出4.1 用训好的权重做推理和可视化训练在runs/segment/pallet_seg/weights/下生成best.pt和last.pt。验证新数据或者做可视化我习惯直接写一个短脚本而不是每次敲命令行from ultralytics import YOLO import cv2 model YOLO(runs/segment/pallet_seg/weights/best.pt) img cv2.imread(scene.jpg) results model.predict(img, conf0.45, iou0.5) for r in results: if r.masks is None: print(无掩码输出) continue for i, mask in enumerate(r.masks.data): cls_id int(r.boxes.cls[i]) conf float(r.boxes.conf[i]) area int(mask.sum()) print(f实例 {i}: 类别 {cls_id} 置信度 {conf:.2f} 掩码面积 {area})result.masks.data是一个n×H×W的列表每个mask对应一个实例boxes里的cls和conf与masks按索引一一对应。遍历时一定要用同一个索引分开遍历会出现“类别对到别的掩码上”的错位。iou参数在托盘相互遮挡时很关键两个托盘挨得近默认0.5可能把它们合并成一个大掩码调到0.35左右能让实例边界更干净代价是碎掩码变多需要配合置信度阈值做二次过滤。4.2 从掩码算位姿质心、外接矩形与叉齿参考线拿到掩码不是终点AGV要的是托盘在哪、朝什么方向。最简单的做法是用掩码算质心和面积占比import torch def analyze_mask(mask, img_size): ys, xs torch.where(mask 0) cx xs.float().mean().item() / img_size[1] cy ys.float().mean().item() / img_size[0] area_ratio mask.sum().item() / (img_size[0] * img_size[1]) return cx, cy, area_ratio归一化坐标方便和检测框统一口径。如果需要角度把mask转成OpenCV的轮廓调用cv2.minAreaRect返回的矩形自带旋转角托盘短边方向就是叉齿插入的参考方向。生产环境里我再把这个角度和相机外参组合换算到机械臂或AGV基座坐标系。这里有一个最常见的坐标坑模型输入经过letterbox缩放掩码坐标是在缩放后的图上算出来的必须按缩放比例映射回原图才能和现场坐标对得上。很多人第一步在PC上测试没问题接到机器人上就偏90%是漏掉了这一步坐标还原。4.3 导出ONNX并检查输出部署端我优先导出ONNX后续再转TensorRT或其它格式yolo export modelruns/segment/pallet_seg/weights/best.pt formatonnx imgsz640 dynamicTrue halfFalse不指定nmsFalse时导出的ONNX自带后处理输入是图像张量输出直接是检测框、置信度和掩码结果适合快速验证。如果你要在C里自己写前后处理加上nmsFalse输出会变成原始预测头一个分支是框与类别另一个分支是掩码系数。实例分割的掩码不是模型直接输出的最终图而是用掩码系数和原型掩码做矩阵乘再过sigmoid才得到实际掩码。这部分被很多人当成黑匣子直接套检测模型的推理代码导致分割模型导出的输出怎么都对不上。提示导出后不要只跑一张图看效果用onnxruntime跑一遍验证集中的一个批次和PyTorch输出逐项比较。数值对不上就检查预处理尤其是归一化方式和letterbox尺寸。5. 托盘实例分割避坑我在这个数据集上翻过的五个车这一章写的是真实项目里踩出来的坑每一条都按现象、原因、解决的顺序拆开。前三个坑在训练前和训练中后两个坑在部署环节越往后越容易被人忽视。5.1 解压后训练秒崩路径层级与txt编码问题现象解压完按data.yaml启动训练几秒之内报“No labels found”或者一堆图片找不到屏幕上全是红色的警告。原因两种情况最常见。一是zip伪加密某些压缩软件给zip写了加密标志但没实际加密标准解压工具要么直接报错要么解出残缺文件二是压缩包的顶层嵌套目录比data.yaml里的path多了一层比如实际路径是datasets/pallet/pallet/images/traindata.yaml里却指向datasets/pallet/images/train。解决先用python zipfile做一次干净的解压再用目录树命令确认层级最后才改data.yaml。改动原则是让path指向images和labels所在的那一层。import zipfile with zipfile.ZipFile(托盘实例分割数据集_20251120_043045.zip) as zf: zf.extractall(datasets/) # 解压后务必执行 tree datasets确认 images 所在层级5.2 边缘托盘掩码被增强吞掉seg_loss震荡不止现象训练在前几轮loss正常下降到中途开始震荡验证集里靠近图像边缘的托盘老是漏检或者掩码缺一大块。原因YOLO默认开mosaic增强把四张图拼起来随机裁剪托盘如果在原图里已经贴近边缘裁剪时掩码被切掉一半实例面积低于阈值就被丢弃。增强让模型反复看到残缺的托盘学习信号被污染。解决训练参数加mosaic0.0重跑一次先确认是不是这个原因。如果关掉后seg_loss立刻稳定再决定是否降低mosaic比例而不是彻底关闭。托盘是结构件轮廓完整度直接影响几何计算我宁可牺牲一点泛化也要保留完整掩码。5.3 类别失衡空托盘recall明显偏低现象整体mAP50还能看分类别统计时发现空托盘recall只有80%左右带货托盘却到了95%。现场表现为空托盘经常被当成背景。原因标注时带货托盘样本多空托盘样本少而且空托盘纹理少、颜色和地面接近模型天然倾向把低纹理区域判为背景。这不是网络结构的锅是数据分布和难例标注的问题。解决先统计每个类别在train和val的实例数量空托盘少于总数的30%就判定为失衡。短期做法是把置信度阈值调低以拉recall但会带来更多误检长期做法是给空托盘类补样本或者对空托盘帧做copy-paste增强把标注好的空托盘多边形随机贴到不同背景里同时生成新的标注文件。调loss权重是最后手段效果跟抽奖差不多属于玄学范畴。5.4 相邻托盘被预测成一个大掩码NMS阈值与标注边界现象两个托盘并排或前后半遮挡时模型输出一个大掩码把两个实例连成一片有时候甚至输出一个包含两个托盘的“超级多边形”。原因推理阶段iou阈值太高两个实例的预测掩码重叠面积大NMS把它们当成同一个目标合并掉了。数据层面如果标注时把遮挡边界画得太“完整”两个实例的标注掩码本身就高度重叠模型学到的区分信号就被削弱。解决先降到0.35做推理对比看实例是否被拆开。能拆开就是阈值问题后处理阶段修拆不开就是标注问题需要检查同图多实例的掩码重叠率把标注统一成“只标可见部分”不要脑补被遮挡的轮廓。这一点在托盘前后堆叠的仓库里尤其重要完整轮廓反而会教坏模型。5.5 导出后精度掉点onnx与板子上的输入不一致现象PyTorch推理掩码很干净同一张图导出ONNX后掩码变成碎片尤其是小托盘和远距离的托盘。原因fp16转换后掩码系数分支精度丢失或者部署端输入分辨率、letterbox和训练时不一致。边缘设备的算子优化对固定shape更友好dynamic输入会走通用算子路径精度和速度都受影响。解决先固定imgsz导出用onnxruntime在同一张图上对比fp32和fp16结果。需要量化时不要直接用训练集做校准采集一批现场光照和遮挡分布的真实图像当校准集。最后输入尺寸在训练和部署两端保持同一个letterbox策略这是“部署掉点”这个坑里最容易忽略的原因。6. 从训练集到验收掩码后处理与快速验证技巧训练完别急着上现场。我习惯把验证集压到很低的置信度跑一遍专门找模型“犹豫”的预测这些是假阳性重灾区。用面积阈值过滤碎掩码把可疑图输出成一个列表人工过一遍能省下大量在产线调试的时间。from ultralytics import YOLO model YOLO(runs/segment/pallet_seg/weights/best.pt) for r in model.predict(sourceval_imgs, conf0.05, iou0.5): if r.masks is None: continue for i, m in enumerate(r.masks.data): area int(m.sum()) if area 200: cls_id int(r.boxes.cls[i]) conf float(r.boxes.conf[i]) print(f{r.path}: 可疑碎片 cls{cls_id} conf{conf:.2f} area{area})把conf压到0.05目的就是让模型把所有拿不准的区域都吐出来。面积阈值200是经验值1920x1080的输入下小于200像素的掩码大概率是反光或噪声不值得信任。扫描出来的可疑样本存成一个子集用best.pt做增量训练的数据源比盲目加轮数有效。验收时我不只看mAP报告还坚持拿20张没进过训练集的现场图做肉眼检查。掩码比托盘轮廓大一圈说明模型对托盘边缘的置信不足近景会引入周围背景掩码小一圈则常是置信度阈值过高把边缘像素砍掉了。看几个数字不如看十几张叠加图来得快。我会把这类图按“掩码偏大/掩码偏小/碎片”三类归档作为下一轮迭代的标注重点。从那以后我每次拿到新数据集都强制自己先跑校验脚本、再做一次低置信度扫描最后才敢说精度达标。希望帮到你。本文还有配套的精品资源点击获取
返回列表