
简介面向环境监测、工业安全与人工智能目标检测研究的粉尘检测数据集采用YOLO标注格式以dust为唯一类别总计922张图片并已划分为训练集797张、验证集83张、测试集42张可直接进入主流目标检测框架进行训练与评估。压缩包共包含1846个文件除922张jpg原始图片外还有922份对应的txt标签文件、1个yaml数据配置文件和1份docx说明文档整体大小约59.23MB目录组织清晰便于按批次取用。数据来源覆盖真实环境监测场景粉尘分布形态多样适合用于空气质量预警、工地与工厂粉尘监控、环保技术研究以及目标检测教学实践能够帮助研究人员和学生快速搭建粉尘识别模型。目前已有261人学习浏览内容专一、标注一致适合作为工业级数据集用于专项算法验证与落地试验。1. 粉尘检测数据集922张YOLO标注图把工业粉尘识别直接拉到训练阶段粉尘检测数据集一套面向环境监测和工业安全的YOLO目标检测数据集。922张真实场景图片其中训练集797张、验证集83张、测试集42张全部标注成dust单类别边界框标注文件是YOLO标准txt格式解压后补一个data.yaml就能直接喂给YOLOv8训练。它解决的是粉尘识别项目里最耗时的采数和标注环节适合做工地扬尘监控、工厂粉尘预警、环保监管系统原型验证也适合刚接触目标检测的工程师拿一份真实的工程类数据集跑通完整的训练、验证、导出流程。下文从解压对目录开始一路拆到训练、调参和避坑。2. 数据集结构与标注格式先弄清922张图是怎么组织的训练跑挂一半原因出在数据和路径没对齐。这一章先不提模型把数据集结构拆清楚后面能少踩一半坑。2.1 文件命名里的Roboflow痕迹与目录结构确认从文件清单里能看到大量这样的文件名fa57ce42-a308-4bcf-92be-6bd7569625d9_jpg.rf.e7fcae8f60b2d154cd5ee5bd0e7112d1.jpg前面那段长UUID是原图标识中间的_jpg.rf和末尾的哈希值是Roboflow平台导出的标记。Roboflow在导出YOLO格式时会把图片统一重命名同一张图片的标注文件就是同名txt。这个命名本身不影响训练但它提示了两件事一是数据集在Roboflow上做过一遍预处理二是解压后的目录结构可能是train/valid/test三个子文件夹各自带images和labels也可能被二次打包拍平所有jpg和txt堆在同一层。拿到zip后先解压再跑一次tree看结构不用急着训练unzip 粉尘检测数据集.zip -d dust_project cd dust_project tree -L 2如果tree输出里images和labels目录是分开的且每个split目录下图片和标签数量对得上说明结构是完整的。如果看到的是几百个jpg和txt平铺在一起就要按85%、10%、5%重新切分这也基本对应数据自带的797/83/42比例。我一般用一段Python脚本做这件事import os import shutil import random src dust_all # 平铺目录所有jpg和txt dst dust_project # 目标目录 ratios {train: 0.85, valid: 0.10, test: 0.05} os.makedirs(dst, exist_okTrue) imgs sorted([f for f in os.listdir(src) if f.lower().endswith(.jpg)]) random.seed(42) random.shuffle(imgs) train_n int(len(imgs) * ratios[train]) valid_n int(len(imgs) * ratios[valid]) for i, img in enumerate(imgs): stem os.path.splitext(img)[0] label stem .txt if not os.path.exists(os.path.join(src, label)): print(缺标签跳过:, img) continue if i train_n: split train elif i train_n valid_n: split valid else: split test os.makedirs(os.path.join(dst, split, images), exist_okTrue) os.makedirs(os.path.join(dst, split, labels), exist_okTrue) shutil.copy(os.path.join(src, img), os.path.join(dst, split, images, img)) shutil.copy(os.path.join(src, label), os.path.join(dst, split, labels, label)) print(切分完成)这段脚本先按固定随机种子打乱图片顺序再按比例切到三个split目录图片复制到images、标签复制到labels文件名保持同名。随机种子固定成42是为了每次重跑都得到同一份切分后面调参时才能对比出模型本身的变化而不是数据分布变化。2.2 YOLO标签逐行解析五个数字背后是归一化坐标YOLO标签txt里每行五个数字含义分别是类别ID、框中心点x、框中心点y、框宽、框高。粉尘检测数据只标dust这一类所以每行第一个数字固定是0。后面四个数字全部做了归一化处理也就是除以图片宽和高取值范围在0到1之间跟图片实际分辨率解耦。好处是训练时换imgsz不需要回头改动标注。动手训练前我习惯先写一段校验脚本把标注坐标换算回像素看看有没有越界或异常行import os from PIL import Image def check_labels(img_dir, lbl_dir): for img_name in sorted(os.listdir(img_dir)): if not img_name.lower().endswith(.jpg): continue stem os.path.splitext(img_name)[0] lbl_path os.path.join(lbl_dir, stem .txt) if not os.path.exists(lbl_path): print(缺标注:, img_name) continue img Image.open(os.path.join(img_dir, img_name)) w, h img.size with open(lbl_path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(格式异常:, lbl_path, line.strip()) continue cls, xc, yc, bw, bh map(float, parts) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) if x1 0 or y1 0 or x2 w or y2 h: print(坐标越界:, lbl_path, line.strip()) if cls ! 0: print(类别超出范围:, lbl_path, line.strip())这段代码做的事情很直接遍历图片目录找同名txt把归一化坐标乘以图片宽高还原成像素框再检查四个角是否落在有效范围内。工业数据集里最容易出现两类脏数据一类是标注行少了一个数字另一类是复制粘贴时坐标写超了图片边界。这两种情况不会让训练直接报错但会让对应图片的loss一直异常拉低整体精度。第一次跑完校验如果报了一堆越界样本别急着删先把它们单独挑出来看一遍原图判断是框贴歪了还是确实粉尘贴着边缘再决定剔除还是修正。2.3 单类别dust的数据取舍与扩展空间全量只标dust一个类别这种做法在工业专项数据集里很常见它把任务收敛得很干净模型不需要学几十个类别的区分逻辑mAP也更容易拉高。但它的边界也很明显检测框只能告诉你这块区域看起来像粉尘漂浮物不能直接告诉你浓度等级。实际项目里要输出轻度、中度、重度这样的分级预警还得在框的基础上做二次统计比如用框面积占整帧比例的变化率或者统计单位时间内框数量的增长趋势。背景负样本的问题同样不能忽略。如果训练数据全是含有dust框的图模型会把纹理相近的阴影、水雾、砂石堆也框出来。后续集成到工地或工厂监控时这类误报会很明显。常见做法是补一些同一监控视角下无粉尘的干净帧单独作为一个背景类参与训练或者用标签里的忽略区域处理。要不要加取决于业务容错率工地扬尘预警可以容忍少量误报宁可多报不漏报但室内工厂的粉尘报警如果频繁误触值班人员很快就会把系统关掉。3. 从解压到YOLOv8训练跑通一套粉尘检测模型的关键步骤3.1 目录对账与图片标签配对检查解压完成后第一件事不是启动训练而是做一遍配对检查。图片和标签必须同名只是后缀不同缺少任何一个文件训练时就会出现数据加载不完整的情况。我习惯先用一段Python脚本把三个split目录全部扫一遍import os src dust_project for split in [train, valid, test]: img_dir os.path.join(src, split, images) lbl_dir os.path.join(src, split, labels) if not os.path.exists(img_dir) or not os.path.exists(lbl_dir): print(目录缺失:, split) continue imgs sorted(os.listdir(img_dir)) missing [] for img in imgs: stem os.path.splitext(img)[0] if not os.path.exists(os.path.join(lbl_dir, stem .txt)): missing.append(img) print(f{split}: 图片{len(imgs)}张, 缺标签{len(missing)}张) for m in missing[:5]: print( 例如:, m)这里会输出每个split的图片总量和缺标签数量。如果train显示797张、valid显示83张、test显示42张且缺标签为0结构就算通过了。如果打出来缺了几十张先看是文件后缀大小写问题还是标签确实没拷全。.jpg和.JPG在Linux下是不同文件Windows下则区分大小写这一点在跨平台拷贝时特别容易翻车。3.2 写data.yaml目录命名必须遵守YOLO的兄弟目录约定YOLOv8读训练数据时只看data.yaml里train、val、test三个字段指向的图片目录然后自动去同级的labels目录找对应txt。也就是说images和labels必须在同一个父目录下且目录名不能随便改。以下是一个可以直接用的配置文件path: /home/yourname/dust_project train: train/images val: valid/images test: test/images nc: 1 names: 0: dustpath字段用于定位项目根目录。train、val、test的值是相对path的路径也可以填绝对路径。这里有一个隐藏规则你填的路径是到images这一级YOLO框架会自动把images替换成labels去找标签。比如train填了train/images框架会去train/labels下找同名txt。如果目录名是annotation或者label训练就会提示Found 0 labels然后整个epoch里模型什么都没有学到。3.3 启动训练命令与关键参数数据集本身是922张图的小规模专项数据用yolov8n这种轻量模型起步就够先验证流程再视精度换更大模型。我常用的首次训练命令是yolo detect train datadust.yaml modelyolov8n.pt \ epochs100 batch16 imgsz640 device0 \ projectrun_dust namev8n patience20几个参数拆开说明一下参数取值说明datadust.yaml数据集配置路径modelyolov8n.pt预训练权重轻量适合小数据集epochs100训练轮数看loss收敛情况再增减batch168GB显存一般能撑住OOM就降到8imgsz640输入分辨率小目标多时可上调到960patience20验证指标连续20轮不提升即早停project/namerun_dust/v8n输出目录避免覆盖旧结果训练正常启动后终端会先打印模型结构、参数量然后开始打印每个epoch的box_loss、cls_loss、dfl_loss和验证指标。首次跑建议盯着前几个epoch的loss看如果loss在持续下降说明数据路径和数据本身都没问题可以放心让它跑完。如果loss来回震荡没有明显下降趋势先停掉回到第2章的校验脚本排查标注。4. 踩坑与排查粉尘检测数据集训练中五条高概率翻车记录4.1 现象训练一启动就提示Found 0 labels训练过程中每个epoch都会输出一条提示比如Found 83 labels如果看到0 labels说明标签一条都没加载进来。原因通常是data.yaml里的路径没有指到正确的images目录或者labels目录名不叫labels。也遇到过一种情况zip在Windows解压后再传到Linux路径里多了一层嵌套目录导致data.yaml的train路径实际不存在。解决方式分三步先确认data.yaml里的path是绝对路径且存在再确认train/images和train/labels在同一个父目录下最后用Python脚本扫描一个图片目录打印出它对应的labels路径看看是不是真能访问到。我一般会临时在脚本里加一行print(lbl_path)直接看到解析出的最终路径。4.2 现象训练曲线正常但val mAP一直很低模型把阴影和墙面当粉尘训练loss降得很好验证mAP却上不去画出来的检测结果里全是阴影、水泥墙面、砂石堆的误检。这种问题的根子不在训练参数而在数据背景多样性。如果训练集里粉尘框大多是亮色调的图像模型很容易学到灰度高的团块就是dust这种偷懒特征。解决路径有两条一是从原始监控里抽无粉尘帧当负样本单独标一个背景类强制模型学会区分二是训练时把hsv_h、hsv_s、hsv_v这些颜色增强参数打开让模型不依赖固定的灰度分布。yolov8默认就开了部分增强但面对这类阴影误检我建议再调高hsv_v的幅度把亮度变化范围拉大。4.3 现象mAP曲线到某个epoch突然掉一截之后又涨回来验证集只有83张图样本量小单张图的检测结果好坏对mAP的影响会被放大。某个epoch里如果一张粉尘浓度较低的图没有被召回mAP就可能掉三四个点。这看起来像玄学实际上是统计波动。处理方式是把patience从默认的100改小到20让早停不要被单次波动误导同时训练结束后对比last.pt和best.pt的验证结果。如果best.pt确实是在中间某个epoch产生的说明波动影响不大直接用best.pt做后续推理就行不需要重训。4.4 现象笔记本CPU训练慢到怀疑人生922张图不算大但在纯CPU环境下yolov8n跑100epoch的时间也足够把午饭时间都耗进去。第一次跑不建议直接在完整数据上硬刚先做一轮冒烟测试imgsz改成256epochs改成3batch改成4跑一个能结束的完整流程确认数据读取、loss计算、验证流程都没报错再投入正式训练。正式训练如果还是要留在CPU上batch设为8以下workers设为0避免DataLoader多进程在Windows下频繁报错。有条件的话用Google Colab的免费GPU跑这种小数据集一个多小时能出结果比本地硬等省时间。4.5 现象粉尘小目标几乎全部漏检大团粉尘能检出来粉尘颗粒在监控画面里往往只占几十个像素imgsz640时下采样几次特征就没了。这是小目标检测的典型问题。最直接的办法是把imgsz提到960或1280代价是显存占用翻倍训练时间变长。另一种思路是改用SAHI切片推理把大图切块再检测。还有一招是把模型从yolov8n换成yolov8m或yolov8l大模型的特征金字塔对小目标更敏感但推理速度会下降。具体怎么选取决于部署环境边缘盒子算力有限优先牺牲召回率换速度服务器推理可以放开用大模型加高分辨率。5. 进阶验证与部署混淆矩阵、切片推理和ONNX导出5.1 混淆矩阵与PR曲线单类别模型重点看什么单类别检测模型的混淆矩阵只有两行两列看似简单但隐含信息不少。正常训练后混淆矩阵里真正的正样本行和负样本行应该数值分布清晰。如果看到正样本一行的漏检数特别多说明召回率不行如果背景行里误检数飘高说明假阳性严重。PR曲线比mAP更值得看。mAP是PR曲线下面积的一个积分值它会掩盖部分区间的性能问题。我经常会单独看置信度阈值在0.5附近时的precision和recall用一句简单的话说就是这台设备到底要设置多大的置信度才能接受误检率。粉尘预警这类场景宁可召回率高一些让误报交给后端逻辑去过滤也不要漏检。5.2 大图切片推理解决小目标粉尘漏检SAHI是处理大图小目标的一个实用工具箱核心思路是把大图切成有重叠的切片对每个切片单独推理再把结果合并回原图坐标。对大分辨率监控画面里的小团粉尘切块后目标在切片中占比变大模型识别率会明显提高。使用方式大致如下加载训练好的yolov8模型对测试图做切片推理设置切片大小640、重叠率0.2收集所有预测框按坐标映射回原图。最终输出的框数量和置信度会比直接整图推理好看很多。缺点是推理总时长增加切20块就要跑20次前向在边缘设备上要先估算一下算力是否够。5.3 导出ONNX并做一次推理比对训练完成后导出一个onnx模型部署阶段更通用且不依赖Python环境。导出本身很简单from ultralytics import YOLO model YOLO(run_dust/v8n/weights/best.pt) model.export(formatonnx, imgsz640, halfTrue)导出后做一次推理比对确保onnx和pytorch结果一致from ultralytics import YOLO model YOLO(run_dust/v8n/weights/best.onnx) res model.predict(test_sample.jpg, conf0.25, imgsz640) for r in res: boxes r.boxes.xyxy.cpu().numpy() scores r.boxes.conf.cpu().numpy() print(框数量:, len(boxes)) for box, score in zip(boxes, scores): print(box, float(score))这一步我在几个项目里都栽过跟头主要问题集中在半精度会不会掉点、输出层shape对不对、坐标是否需要还原到原图尺寸。从那以后我每次拿到新的数据集训练完做部署前都会强制跑一遍onnx与pytorch的逐张比对框数一致、坐标误差控制在几个像素以内才往下走。粉尘检测这种场景误报后果不小事前多花十分钟现场就能少折腾半天希望帮到你。本文还有配套的精品资源点击获取