
简介面向工业质检与智能安防场景的传送带异物检测数据集可识别铁棍、垃圾等常见异物适合从事目标检测算法训练、产线异常监控及边缘部署的开发者与研究人员使用。资源包共108个文件以105张jpg现场图像为主另附3个json标注文件采用COCO JSON格式组织可直接对接主流检测框架进行模型训练与验证压缩包整体约4.65MB体积轻便便于快速下载与本地调试。图像取自真实传送带监控画面覆盖不同时段与异物形态为小样本场景下的数据增强与迁移学习提供基础素材。目前已有413人学习下载具备一定参考热度。读者可据此搭建异物检测基线模型完成类别标注解析、训练集与验证集划分及推理效果评估也可用于课程设计、毕业项目或产线视觉方案的原型验证。1. 传送带异物检测数据集从监控抽帧到 COCO JSON 的落地路径工厂传送带最怕的不是停机而是铁棍、垃圾这类异物混进物料流轻则卡住滚筒撕裂皮带重则打坏下游设备。很多做视觉检测的团队卡在第一步没有贴合真实产线的标注数据。这份传送带异物检测识别数据集采集自 NVR 监控通道的连续录像抽帧文件名里带着NVR_ch1_main_20220912160000_20220912170000这样的时间戳和帧序号说明它是按小时段切分、逐帧导出的真实工业画面。标注采用 COCO JSON 格式可识别铁棍、垃圾两类目标适合直接喂给 YOLOv8、MMDetection、Detectron2 这类主流框架做训练和微调。如果你正在做异物检测、数据标注或工业质检方向这份资源能省掉最耗时的采集与标注环节把精力留给模型调优和部署。2. COCO JSON 标注结构拆解字段含义与传送带场景的适配点拿到一份 COCO JSON第一件事不是急着转 YOLO而是先读懂它到底标了什么、怎么标的。传送带异物检测这个场景有它的特殊性目标小、背景纹理重复、异物和物料颜色接近标注质量直接决定模型上限。这一章把 JSON 结构拆开讲清楚每个字段在传送带语境下意味着什么。2.1 images、annotations、categories 三张表的关系COCO JSON 顶层是三个核心数组images记录每张图的文件名、宽高和唯一idannotations记录每个标注框的image_id、category_id、bbox和areacategories定义类别名和id的映射。三者靠 id 关联缺一不可。{ images: [ { id: 1, file_name: NVR_ch1_main_20220912160000_20220912170000-dav_005736-161_jpg.rf.e455dd23d6c7730174a7cc32f9f18ced.jpg, width: 1920, height: 1080 } ], annotations: [ { id: 1, image_id: 1, category_id: 1, bbox: [820, 430, 96, 210], area: 20160, iscrowd: 0 } ], categories: [ {id: 1, name: iron_rod, supercategory: foreign_object}, {id: 2, name: garbage, supercategory: foreign_object} ] }bbox是[x, y, width, height]原点在左上角单位是像素。area是框面积训练时用于区分大小目标。iscrowd为 0 表示单实例标注传送带异物一般不会出现密集遮挡这个值基本恒为 0。categories里的supercategory可以统一写成foreign_object方便后续扩展更多异物类别。2.2 传送带场景下 bbox 标注的三个适配点第一异物形态差异大。铁棍通常是细长条宽高比可能到 1:8 甚至更极端垃圾则形状不规则边界模糊。标注时铁棍要贴紧两端垃圾要框住可见主体不要为了凑面积把背景框进去。第二监控画面有畸变和压缩噪声。NVR 抽帧的 JPG 经过 H.264 压缩边缘有块效应标注框如果压到目标边缘训练时模型容易学到压缩伪影。常见做法是框比目标实际边界外扩 2 到 4 像素给噪声留余量。第三时间戳文件名隐含帧间关系。同一小时段内dav_005736-161和dav_005820-642是不同帧如果做视频级检测可以按文件名前缀分组避免同一段连续帧被随机划分到训练集和验证集造成数据泄漏。2.3 用 pycocotools 做一次标注体检在训练之前先跑一遍统计确认没有空图、没有越界框、类别分布是否失衡。from pycocotools.coco import COCO import collections coco COCO(annotations/instances_train.json) # 统计每类标注数量 cat_counter collections.Counter() for ann in coco.dataset[annotations]: cat_counter[ann[category_id]] 1 for cid, name in [(c[id], c[name]) for c in coco.dataset[categories]]: print(f{name}: {cat_counter[cid]} 个标注) # 检查越界框 img_map {img[id]: img for img in coco.dataset[images]} bad 0 for ann in coco.dataset[annotations]: img img_map[ann[image_id]] x, y, w, h ann[bbox] if x 0 or y 0 or x w img[width] or y h img[height]: bad 1 print(f越界框数量: {bad})这段脚本输出两个关键指标类别标注数和越界框数。如果铁棍和垃圾数量差距超过 5:1训练时建议开类别权重或者对少数类做过采样。越界框必须清零否则转 YOLO 格式时会直接报错或产生负坐标。注意pycocotools 在 Windows 上安装偶尔需要编译工具链如果pip install pycocotools失败可以换pycocotools-windows或者直接用 conda 装。3. 从 COCO JSON 转 YOLO 格式转换脚本与四个边界坑COCO 是通用标注格式但实际训练时 YOLOv8 吃的是每张图一个.txt的归一化坐标。这一章给出一份可直接跑的转换脚本并把转换过程中最容易翻车的四个边界情况讲透。3.1 转换脚本COCO 到 YOLO txtimport json import os from pathlib import Path def coco_to_yolo(json_path, img_dir, out_dir): with open(json_path, r, encodingutf-8) as f: data json.load(f) # 建立 image_id - 图片信息 的映射 img_map {img[id]: img for img in data[images]} # 建立 category_id - 连续索引 的映射YOLO 要求从 0 开始 cat_ids sorted([c[id] for c in data[categories]]) cat2idx {cid: i for i, cid in enumerate(cat_ids)} os.makedirs(out_dir, exist_okTrue) # 按 image_id 聚合标注 ann_by_img {} for ann in data[annotations]: ann_by_img.setdefault(ann[image_id], []).append(ann) for img_id, img_info in img_map.items(): w, h img_info[width], img_info[height] lines [] for ann in ann_by_img.get(img_id, []): x, y, bw, bh ann[bbox] # 归一化并转为中心点坐标 cx (x bw / 2) / w cy (y bh / 2) / h nw bw / w nh bh / h # 裁剪到 [0,1]防止越界 cx, cy min(max(cx, 0), 1), min(max(cy, 0), 1) nw, nh min(max(nw, 0), 1), min(max(nh, 0), 1) cls cat2idx[ann[category_id]] lines.append(f{cls} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) stem Path(img_info[file_name]).stem with open(os.path.join(out_dir, stem .txt), w) as f: f.write(\n.join(lines)) coco_to_yolo( annotations/instances_train.json, images/train, labels/train )逻辑说明先把category_id重映射成从 0 开始的连续整数因为 YOLO 的类别索引必须连续COCO 里如果 id 是 1 和 2直接拿来用会多一个空类。然后按image_id聚合标注逐图生成 txt。坐标转换公式是中心点 (左上角 宽高/2) / 图像尺寸这是 YOLO 的标准格式。参数说明json_path是 COCO 标注文件路径img_dir是图片目录脚本里其实只用了文件名没读图但保留参数方便扩展out_dir是 txt 输出目录。归一化后保留 6 位小数足够再多是浪费。3.2 四个边界坑空图、越界、类别映射、文件名匹配空图坑COCO 里有些图可能没有任何标注转换后会生成空 txt。YOLO 训练时空 txt 是合法的负样本但如果你的数据集里空图比例过高模型会偏向预测背景。建议统计一下空图比例超过 20% 就考虑剔除一部分。越界坑监控抽帧的标注偶尔会有框超出图像边界归一化后出现负数或大于 1 的值。脚本里做了裁剪但裁剪会改变框的实际覆盖区域。更稳妥的做法是在标注阶段就修正转换时只做检测和报警不静默裁剪。类别映射坑如果 COCO 的categories里 id 不连续比如只有 1 和 3直接当索引用会出错。脚本里用sorted加枚举重建映射保证从 0 开始连续。转换后建议打印一次cat2idx确认铁棍和垃圾对应的索引和你训练配置里的names一致。文件名匹配坑COCO 的file_name可能带路径前缀而 YOLO 要求 txt 和图片同名同目录结构。脚本用Path(file_name).stem取纯文件名但如果你的图片实际存放路径和 JSON 里的file_name不一致需要手动对齐。常见做法是转换后跑一遍校验遍历 labels 目录确认每个 txt 都能在 images 目录找到同名图片。3.3 转换后的校验脚本from pathlib import Path img_dir Path(images/train) lbl_dir Path(labels/train) img_stems {p.stem for p in img_dir.glob(*.jpg)} lbl_stems {p.stem for p in lbl_dir.glob(*.txt)} print(f图片数: {len(img_stems)}, 标签数: {len(lbl_stems)}) print(f有图无标签: {len(img_stems - lbl_stems)}) print(f有标签无图: {len(lbl_stems - img_stems)})输出里「有标签无图」必须为 0否则训练时 YOLO 会找不到图片直接报错。「有图无标签」是负样本数量可控就没问题。4. 用这份数据集训练 YOLOv8配置、参数与显存控制数据转好了接下来是训练。这一章以 YOLOv8 为例给出从 data.yaml 到启动命令的完整配置并说明传送带异物检测场景下几个关键参数怎么设。4.1 data.yaml 与目录结构YOLOv8 要求固定的目录结构图片和标签分开放路径在 yaml 里声明。path: /data/conveyor_foreign train: images/train val: images/val test: images/test names: 0: iron_rod 1: garbagepath是数据集根目录train/val/test是相对路径。names的顺序必须和转换脚本里的cat2idx一致铁棍是 0垃圾是 1。如果顺序反了模型会把铁棍预测成垃圾指标看着还行但实际全错。目录结构建议这样组织conveyor_foreign/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml4.2 训练命令与关键参数yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ patience30 \ projectruns/conveyor \ nameexp01参数说明model选yolov8s而不是n因为传送带异物目标偏小s 的特征提取能力更稳显存够就上 s 或 m。imgsz640是默认值如果铁棍在画面里只占几十像素可以提到 960 或 1280但显存占用会翻倍。batch16在 8G 显存上跑 640 尺寸基本安全12G 可以上 32。patience30表示 30 轮验证指标不提升就早停避免过拟合。lr00.01是初始学习率如果 loss 震荡厉害降到 0.005。4.3 小目标检测的增强策略传送带上的铁棍往往又细又长默认增强可能不够。在训练配置里可以加几项针对性增强yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs150 \ imgsz960 \ batch8 \ mosaic1.0 \ scale0.5 \ copy_paste0.3 \ projectruns/conveyor \ nameexp02_smallmosaic1.0是默认开启的四图拼接对小目标友好。scale0.5允许随机缩放增强尺度鲁棒性。copy_paste0.3是分割任务常用的增强检测任务里也能用把目标复制粘贴到其他位置增加小目标出现频率。注意imgsz提到 960 后batch要相应降到 8否则显存溢出。提示训练前先用yolo detect train ... epochs1跑一轮确认数据加载和类别映射没问题再开完整训练。这一步能省掉几小时的无效等待。5. 避坑与排查标注、转换、训练里最容易翻车的五件事这一章把实际做异物检测项目时踩过的坑集中列出来每条按现象、原因、解决写方便对照排查。现象一训练 loss 正常下降但验证集 mAP 始终在 0.1 以下。原因类别映射错位。COCO 的category_id和 YOLO 的类别索引没对齐模型学的是错的标签。 解决转换后打印cat2idx和 data.yaml 的names逐行核对。再抽查几张图的 txt用可视化脚本把框画回原图确认铁棍框在铁棍上。现象二模型把传送带边缘的阴影预测成铁棍。原因标注时把传送带边缘的暗纹也框进去了或者负样本不足。 解决回查标注剔除误标同时增加不含异物的纯背景图作为负样本比例控制在总数据的 10% 到 15%。现象三转换脚本报KeyError: image_id。原因annotations 里引用了 images 中不存在的image_id通常是标注文件被手动改过或合并时出错。 解决在转换脚本开头加校验遍历 annotations 检查image_id是否都在img_map里不在就打印出来人工处理。现象四训练到一半显存溢出CUDA out of memory。原因imgsz或batch设太大或者 dataloader 的workers过多导致内存泄漏。 解决先把batch减半再降imgsz。workers在 Windows 上建议设 0 或 2Linux 上可以设 8。如果还溢出用yolo detect train ... ampFalse关掉混合精度试试。现象五验证集指标很好但实际产线部署后漏检严重。原因训练集和验证集来自同一小时段的连续帧数据泄漏导致指标虚高。 解决按时间段划分数据集比如用 16:00 到 17:00 的帧做训练17:00 到 18:00 的帧做验证确保验证集的时间段和训练集不重叠。文件名里的时间戳就是天然的分组依据。6. 进阶技巧用时间戳做数据划分与难例挖掘这份数据集的文件名里藏着一条容易被忽略的信息NVR_ch1_main_20220912160000_20220912170000明确标出了录像的小时段。用这个时间戳做数据划分比随机划分更贴近真实部署场景也能避免连续帧泄漏。我一般会按小时段分组前几个小时的帧做训练中间小时做验证最后小时做测试。这样验证集上的指标更接近产线实际表现不会出现「训练时 0.95上线后 0.6」的落差。具体操作上先用脚本按文件名前缀分组import re from pathlib import Path from collections import defaultdict img_dir Path(images/all) groups defaultdict(list) for p in img_dir.glob(*.jpg): # 提取时间戳段如 20220912160000_20220912170000 m re.search(r(\d{14}_\d{14}), p.name) if m: groups[m.group(1)].append(p.name) for ts, files in sorted(groups.items()): print(f{ts}: {len(files)} 张)输出会告诉你每个小时段有多少帧。然后按时间段分配取前 60% 的小时段做训练中间 20% 做验证最后 20% 做测试。如果某个小时段帧数特别少可以合并相邻时段。难例挖掘是另一个提分点。训练完第一版模型后用它在验证集上推理把漏检和误检的图挑出来人工重新标注或修正再加入训练集做第二轮微调。传送带场景的难例通常是铁棍和传送带边缘平行导致混淆、垃圾和物料颜色接近、监控画面过曝或过暗。把这些难例喂回去第二轮 mAP 通常能涨 3 到 8 个点。还有一个习惯每次转换完数据我都会用yolo detect val跑一遍预训练模型看 baseline 指标。如果 baseline 低得离谱说明数据或配置有问题先排查再训练别急着调参。从那以后我每次拿到新数据集都强制走一遍「统计 → 转换 → 校验 → baseline」四步省下的返工时间比调参多得多。希望帮到你。本文还有配套的精品资源点击获取