
简介这份包裹与条码实例分割数据集面向物流自动化、智能仓储与计算机视觉方向的研究者和开发者用于训练模型在真实场景中精确识别包裹与条码轮廓。数据覆盖条码、单个包裹及多个包裹三类目标采用多边形坐标标注的YOLO格式可直接接入主流检测与分割框架减少预处理成本。压缩包共322个文件以160张JPEG实景图片和160个TXT标注文件为主另含1个yaml配置文件与1份docx说明文档整体约13.97MB训练、验证与测试集划分清晰。目前已有206人学习下载。借助该数据集读者可快速搭建实例分割实验完成包裹定位、条码识别与多包裹计数等任务并用于自动化分拣、库存管理及安防监控等场景的算法验证与创新研究。1. 包裹与条码实例分割数据集从拿到 zip 到跑通第一轮训练电商分拣线上一个纸箱贴着面单面单上有条形码、二维码、文字和胶带反光。你要让模型不仅框出「条码在哪」还要给出条码的像素级轮廓——这就是实例分割要干的事。包裹与条码实例分割数据集.zip这个标题指向的正是这类场景的数据集图像里同时存在包裹主体和条码区域标注以多边形或掩码形式给出每个条码实例单独成 mask。它解决的是「检测框够用但边缘不准」的问题适合做物流分拣、仓储扫码、面单质量检测的团队。拿到 zip 之后真正要回答的是三件事标注格式能不能直接喂给 YOLO 系列实例分割、类别和实例数够不够训、以及从解压到跑通第一轮训练最短路径是什么。下面按我实际处理这类数据集的顺序拆开讲。2. 先看清 zip 里到底是什么标注格式与目录结构判定2.1 实例分割数据集常见的三种标注形态包裹与条码这类数据集落到磁盘上通常不会只有一种格式。我见过最多的是三种COCO JSON、YOLO 多边形 txt、以及 LabelMe 的 JSON。COCO 的annotations里每个实例有segmentation字段值是多边形点串或 RLEYOLO 分割格式则是每行class x1 y1 x2 y2 ...坐标是归一化后的LabelMe 是每个图一个 JSONshapes里带label和points。判定方法很直接解压后先看有没有annotations.json或instances_*.json有就是 COCO 系如果每张图旁边有个同名 txt打开第一行看是不是五个以上数字是就是 YOLO 分割如果是一堆.json且里面有imageData字段基本是 LabelMe。这一步不能跳。因为后面训练脚本吃哪种格式决定了你要不要写转换。我一般会先跑一段统计脚本把类别分布和实例数摸清楚避免训到一半发现某个类只有个位数实例。import json, os, glob from collections import Counter # 假设解压后根目录下有 annotations.jsonCOCO 格式 ann_path package_barcode/annotations.json with open(ann_path, r, encodingutf-8) as f: coco json.load(f) # 类别名与 id 映射 cats {c[id]: c[name] for c in coco[categories]} print(类别:, cats) # 统计每个类别的实例数 inst_counter Counter() for ann in coco[annotations]: inst_counter[cats[ann[category_id]]] 1 print(各类实例数:, inst_counter) # 统计每张图的实例数分布判断是否过于稀疏 img_inst Counter() for ann in coco[annotations]: img_inst[ann[image_id]] 1 print(图片总数:, len(coco[images])) print(有标注图片数:, len(img_inst)) print(单图实例数样例:, list(img_inst.items())[:5])这段脚本做三件事读 COCO JSON、按类别统计实例数、按图片统计实例密度。参数上唯一要改的是ann_path指向你解压后的标注文件。如果输出里某个类别实例数低于 50训练时就要考虑过采样或合并类别如果「有标注图片数」远小于「图片总数」说明大量图是负样本实例分割任务里负样本太多会拉低召回需要确认是否保留。2.2 目录结构决定你后面要不要重写 dataloader包裹与条码数据集常见的目录有两种一种是images/和annotations/分离另一种是train/、val/下各自带images和labels。前者多见于 COCO 导出后者多见于已经切分好的 YOLO 格式。判定完格式后我习惯先建一个工作目录把图片和标注按 split 重新组织避免训练脚本里写一堆路径判断。# 查看解压后的顶层结构先不急着改 unzip -l package_barcode.zip | head -40 # 解压到独立目录避免污染当前工作区 mkdir -p ~/data/package_barcode unzip package_barcode.zip -d ~/data/package_barcode # 看目录树重点看 images 和 labels/annotations 的对应关系 find ~/data/package_barcode -maxdepth 3 -type d | sortunzip -l先列内容是为了确认 zip 里有没有嵌套一层同名目录很多数据集会多包一层直接解压会导致路径多一级。find看目录深度如果images和labels不在同一级后面转换脚本里就要做路径映射。这一步的产出是一张目录结构图后面所有转换和训练配置都基于它。2.3 用可视化抽查标注质量别等训练翻车才发现标注质量是实例分割里最容易被忽略的坑。条码区域小、边缘反光、胶带遮挡都会导致多边形点漂移。我一般会抽 20 张图把 mask 叠上去看重点看条码 mask 有没有把面单文字也包进去、包裹主体 mask 有没有漏掉被遮挡部分。import json, cv2, numpy as np, random with open(package_barcode/annotations.json, r, encodingutf-8) as f: coco json.load(f) img_info {img[id]: img for img in coco[images]} anns_by_img {} for ann in coco[annotations]: anns_by_img.setdefault(ann[image_id], []).append(ann) # 随机抽 5 张有标注的图做叠加 sample_ids random.sample(list(anns_by_img.keys()), 5) for iid in sample_ids: info img_info[iid] img cv2.imread(os.path.join(package_barcode/images, info[file_name])) overlay img.copy() for ann in anns_by_img[iid]: for seg in ann[segmentation]: pts np.array(seg, dtypenp.int32).reshape(-1, 2) cv2.fillPoly(overlay, [pts], (0, 255, 0)) vis cv2.addWeighted(overlay, 0.4, img, 0.6, 0) cv2.imwrite(fcheck_{iid}.jpg, vis)这里segmentation可能是多边形列表也可能是 RLE 字典如果是 RLE 就要先用pycocotools解码。叠加时透明度 0.4 是我常用的值太低看不清边界太高盖住原图细节。抽查重点看两类问题条码 mask 是否只覆盖条码本身、包裹 mask 是否把背景也吃进去。发现系统性偏移就要考虑重新标注或至少做一轮清洗。3. 把标注转成 YOLO 实例分割格式脚本、参数与边界处理3.1 为什么优先转 YOLO 分割格式而不是直接读 COCOYOLOv8/v11 的实例分割训练入口吃的是 YOLO 格式的 txt每行一个实例格式为class_id x1 y1 x2 y2 ... xn yn坐标归一化到 0~1。直接改 dataloader 读 COCO 也能跑但会失去官方脚本里的缓存、增强和验证逻辑后期排查问题成本高。我一般先把 COCO 转成 YOLO 分割 txt再按 split 组织目录这样训练脚本几乎不用改。转换的核心是把 COCO 的绝对坐标多边形除以图像宽高同时把category_id映射成从 0 开始的连续整数。包裹与条码数据集里如果类别只有「包裹」和「条码」映射后就是 0 和 1。注意 COCO 的category_id可能不是从 0 开始直接拿来当 YOLO 的 class_id 会越界。import json, os from pathlib import Path def coco_to_yolo_seg(coco_json, img_dir, out_label_dir, class_map): with open(coco_json, r, encodingutf-8) as f: coco json.load(f) img_info {img[id]: img for img in coco[images]} Path(out_label_dir).mkdir(parentsTrue, exist_okTrue) for ann in coco[annotations]: info img_info[ann[image_id]] w, h info[width], info[height] cls_name next(c[name] for c in coco[categories] if c[id] ann[category_id]) if cls_name not in class_map: continue cls_id class_map[cls_name] seg ann[segmentation] if isinstance(seg, dict): # RLE 跳过需先解码 continue for poly in seg: if len(poly) 6: # 少于 3 个点无法构成多边形 continue norm [] for i in range(0, len(poly), 2): norm.append(poly[i] / w) norm.append(poly[i1] / h) line f{cls_id} .join(f{v:.6f} for v in norm) label_path Path(out_label_dir) / (Path(info[file_name]).stem .txt) with open(label_path, a, encodingutf-8) as lf: lf.write(line \n) coco_to_yolo_seg( package_barcode/annotations.json, package_barcode/images, package_barcode/labels, {package: 0, barcode: 1} )参数说明class_map必须和你的data.yaml里names顺序一致否则训练时类别会错位。len(poly) 6是过滤掉退化多边形少于 3 个点无法构成有效 mask。坐标保留 6 位小数是 YOLO 官方脚本的习惯精度足够且文件不会太大。如果segmentation是 RLE这段会跳过需要先用pycocotools的frPyObjects解码成多边形再转。3.2 按 split 组织目录并写 data.yaml转完 txt 后目录要整理成 YOLO 训练脚本认识的样子images/train、images/val、labels/train、labels/val。如果原数据集没给 split我一般按 8:2 随机切且保证每个 split 里两类实例都有。切分脚本要固定随机种子否则每次跑结果不一样排查问题时没法复现。import random, shutil from pathlib import Path random.seed(42) img_dir Path(package_barcode/images) lbl_dir Path(package_barcode/labels) out_root Path(package_barcode_yolo) stems [p.stem for p in img_dir.glob(*.jpg)] random.shuffle(stems) split int(len(stems) * 0.8) splits {train: stems[:split], val: stems[split:]} for phase, names in splits.items(): (out_root / images / phase).mkdir(parentsTrue, exist_okTrue) (out_root / labels / phase).mkdir(parentsTrue, exist_okTrue) for stem in names: shutil.copy(img_dir / f{stem}.jpg, out_root / images / phase / f{stem}.jpg) lbl lbl_dir / f{stem}.txt if lbl.exists(): shutil.copy(lbl, out_root / labels / phase / f{stem}.txt)random.seed(42)是固定切分保证每次跑同一份数据得到同样的 train/val。shutil.copy而不是 move是为了保留原始数据后面如果发现切分不合理还能重来。切完后要检查labels/val里有没有空文件空文件代表该图没有实例实例分割里可以保留作为负样本但比例不宜超过 10%。对应的data.yaml写法path: /home/user/data/package_barcode_yolo train: images/train val: images/val names: 0: package 1: barcodepath用绝对路径避免训练时工作目录变化导致找不到数据。names的顺序必须和转换时的class_map完全一致这是最常见的翻车点之一。3.3 转换后必须做的三项校验转换脚本跑完不代表数据就能用。我一般做三项校验一是随机抽 10 个 txt 看坐标是否都在 0~1 之间出现大于 1 说明归一化除了错宽高二是用 YOLO 官方可视化脚本把 mask 画回图上确认和原图对齐三是统计每个 split 的实例数确认 val 里两类都有足够实例。# 检查是否有坐标越界 awk {for(i2;iNF;i) if($i0 || $i1) print FILENAME: $0} package_barcode_yolo/labels/train/*.txt | head # 统计 train/val 的实例数 for d in train val; do echo -n $d 实例数: cat package_barcode_yolo/labels/$d/*.txt | wc -l doneawk那行会打印所有坐标越界的行正常应该没有输出。如果大量越界回去检查转换脚本里除的是width还是height这两个写反是血泪经验里排前三的错误。实例数统计用来判断 val 是否太小如果 val 实例数低于 100验证指标波动会很大建议调大切分比例或做交叉验证。4. 用 YOLOv8 实例分割跑通第一轮训练参数怎么设、显存怎么省4.1 环境与最小训练命令环境上YOLOv8 实例分割依赖ultralytics包装的时候注意 torch 版本和 CUDA 匹配。我一般用 conda 建独立环境避免和系统里的 torch 冲突。最小训练命令不需要写 Python直接命令行调yolo segment train即可。conda create -n yolo_seg python3.10 -y conda activate yolo_seg pip install ultralytics # 最小训练用 yolov8n-seg 先跑通确认数据和流程没问题 yolo segment train \ modelyolov8n-seg.pt \ datapackage_barcode_yolo/data.yaml \ epochs50 \ imgsz640 \ batch8 \ device0 \ projectruns/package_barcode \ nameexp1modelyolov8n-seg.pt是最小的分割模型先用它跑通确认数据管道没问题再换大模型。imgsz640是默认值如果条码在图中占比很小可以提到 1024但显存会翻倍。batch8是保守值8G 显存跑 640 一般够用不够就降到 4。device0指定第一块 GPUCPU 训练会慢到无法接受。project和name决定输出目录方便多次实验对比。4.2 条码小目标场景下必调的几个参数包裹与条码数据集里条码往往只占图像很小一块默认参数下 mask 质量会差。我一般会调这几个imgsz提到 1024、overlap_mask保持默认 True、mask_ratio设为 2 或 4、lr0从 0.01 降到 0.005。mask_ratio控制 mask 下采样倍率值越小 mask 越精细但显存越高条码这种小目标建议用 2。yolo segment train \ modelyolov8s-seg.pt \ datapackage_barcode_yolo/data.yaml \ epochs100 \ imgsz1024 \ batch4 \ mask_ratio2 \ lr00.005 \ patience20 \ device0patience20是早停验证指标 20 轮不升就停省时间。lr00.005比默认低是因为小目标对学习率敏感太大容易在早期把 mask 学崩。如果显存不够优先降batch而不是降imgsz因为imgsz直接影响小目标能否被看到。4.3 训练日志里该盯哪几个指标实例分割训练日志里除了box_loss和seg_loss重点看metrics/mAP50(M)和metrics/mAP50-95(M)M 代表 mask。条码类如果mAP50(B)高但mAP50(M)低说明框对了但 mask 边缘不准通常是mask_ratio太大或标注多边形太粗糙。包裹类如果两者都低检查是不是遮挡样本太多、或者类别不平衡。# 训练结束后用验证集跑一次输出每类指标 yolo segment val \ modelruns/package_barcode/exp1/weights/best.pt \ datapackage_barcode_yolo/data.yaml \ imgsz1024 \ device0val命令会输出每类的 box 和 mask 指标重点看条码类的 mask mAP。如果条码 mask mAP 低于 0.3先回去看可视化结果大概率是标注问题而不是模型问题。这一步的产出是一张每类指标表决定下一步是调参还是清数据。5. 避坑与排查包裹条码实例分割里最容易翻车的五件事5.1 现象训练 loss 正常但 mask 全是背景原因YOLO 分割格式里 class_id 从 0 开始如果转换时直接用了 COCO 的category_id可能从 1 开始训练时类别越界模型学不到有效 mask。解决转换脚本里强制用class_map映射训练前用awk检查 txt 第一列最大值是否等于类别数减一。5.2 现象条码 mask 比实际大一圈把面单文字也包进去原因标注时多边形点贴的是文字外框而不是条码本身或者转换时坐标没做归一化导致缩放错位。解决抽查 20 张叠加图确认 mask 边界如果是标注问题要么重新标注要么在训练时用mask_ratio2让模型自己学更紧的边界但效果有限。5.3 现象验证集 mask mAP 波动很大每次跑差 0.1 以上原因val 集太小或者切分时没固定随机种子每次跑用的 val 图不一样。解决固定random.seedval 实例数至少 100如果数据总量少用 5 折交叉验证代替单次切分。5.4 现象显存溢出batch 降到 1 还是 OOM原因imgsz太大或mask_ratio太小导致 mask 分支显存占用高。解决先降imgsz到 640 跑通再逐步升mask_ratio从 2 改到 4 能省显存但 mask 会粗实在不够用混合精度ampTrueYOLO 默认开。5.5 现象包裹和条码类别混淆条码被预测成包裹原因两类在图像里空间重叠条码贴在包裹上模型学到的特征区分度不够。解决检查标注里条码 mask 是否独立于包裹 mask如果包裹 mask 把条码区域也包进去模型自然分不开另外可以加cls1.5提高分类损失权重但优先清标注。6. 进阶用验证集反查标注质量把 mask mAP 再提一截跑通第一轮之后真正拉开差距的不是换更大的模型而是用验证结果反查标注。我习惯把best.pt在 val 上跑一遍导出每张图的预测 mask 和 GT mask 叠加图重点看三类漏检的条码、mask 明显偏移的包裹、以及预测出但 GT 没有的实例。漏检的条码往往是标注时被漏掉的小实例补标后 mAP 能直接涨mask 偏移的包裹通常是多边形点太少补点后边缘会准很多预测出但 GT 没有的可能是标注遗漏也可能是模型误检需要人工判定。yolo segment predict \ modelruns/package_barcode/exp1/weights/best.pt \ sourcepackage_barcode_yolo/images/val \ imgsz1024 \ saveTrue \ save_txtTrue \ projectruns/package_barcode/pred_valsave_txtTrue会把预测结果存成 YOLO 格式 txt方便和 GT 做 diff。我一般写个小脚本对比预测 txt 和 GT txt 的实例数差得多的图优先看。这个反查过程通常跑两轮第一轮补漏标第二轮修 mask 边界之后再把imgsz提到 1280 做最终训练条码这种小目标的 mask mAP 通常还能再涨 3~5 个点。另一个技巧是冻结 backbone 先训几轮 head。包裹与条码数据量通常不大直接全量微调容易过拟合。我一般先freeze10训 20 轮让分割 head 先适配数据分布再解冻全量训。这样做的代价是多花一点时间但验证集指标更稳尤其是 val 实例数少的时候。# 先冻结 backbone 训 head yolo segment train modelyolov8s-seg.pt datapackage_barcode_yolo/data.yaml \ epochs20 imgsz1024 batch4 freeze10 device0 nameexp_freeze # 再解冻全量微调 yolo segment train modelruns/package_barcode/exp_freeze/weights/best.pt \ datapackage_barcode_yolo/data.yaml epochs80 imgsz1024 batch4 device0 nameexp_fullfreeze10冻结前 10 层具体层数看模型结构YOLOv8s 的 backbone 大概在前 10 层。解冻后用best.pt继续训学习率可以再降一半。这套流程我在几个小样本分割任务里反复用过比直接全量训稳定尤其是条码这种边缘细的目标mask 质量提升明显。最后说个习惯每次改完数据或参数先把runs目录按日期_改动点重命名不然一周后回头看一堆exp1、exp2根本分不清哪次改了什么。这个习惯帮我省过很多次后悔药。希望帮到你。本文还有配套的精品资源点击获取