☰
无人机水面垃圾检测数据集实战:9627张VOC+YOLO双格式数据训练YOLOv8全流程
2026/10/3 5:51:31 网站建设 项目流程

1. 这个数据集到底解决了一个什么具体问题

先说说我为什么会盯上这个数据集。去年下半年我接了一个沿海城市的环保巡检项目,客户的需求很直接:用无人机沿着近岸海域飞一圈,把水面上的塑料瓶、泡沫箱、废弃渔网这些漂浮垃圾自动标出来,生成一份带坐标的巡检报告。听起来不难,但真正动手才发现,卡脖子的地方根本不在模型结构,而在数据。

公开渠道能找到的水面垃圾数据集,要么是内河湖泊的固定摄像头拍的,视角低、背景单一;要么是实验室里摆拍的水池图像,干净得不像真实海面。真正从无人机视角、低空俯拍、带真实海面反光和波浪纹理的标注数据,几乎找不到。这个9627张、VOC+YOLO双格式、单类别的水面垃圾检测数据集,恰好补上了这个缺口。

它的核心价值可以用一句话概括:把"无人机低空视角"和"水面漂浮垃圾"这两个条件同时满足的标注数据,做成了一个可以直接喂给YOLO系列模型训练的规模。9627张不是一个随便的数字,对于单类别检测任务来说,这个量级已经足够让一个中等规模的模型收敛到可用的精度,而不需要你再去做大量的数据增强来凑数。

适合谁来用?三类人最直接:一是做环保巡检、河道治理、海漂垃圾监测的工程团队,需要快速搭一个能跑的检测基线;二是做无人机视觉感知研究的学生和研究者,需要一个贴近真实低空场景的验证集;三是想练手YOLO训练全流程的开发者,单类别、双格式、数据量适中,拿来跑通"数据准备—训练—评估—部署"这条链路非常合适。

我拿到这个数据集之后,第一件事不是急着训练,而是先把它拆开看清楚:图像分辨率分布、标注框的尺寸分布、类别平衡情况、有没有重复和脏数据。这一步做扎实了,后面能省掉大量返工。下面我就按我实际处理的顺序,把这个数据集从里到外讲一遍。

2. 数据集整体设计与格式拆解

2.1 为什么同时提供VOC和YOLO两种格式

很多人看到"VOC+YOLO格式"会觉得是多此一举,其实这是数据集作者很务实的一个设计。VOC格式(XML标注)和YOLO格式(TXT标注)代表了两套完全不同的工具生态。

VOC格式的XML文件里,每个目标记录的是xmin, ymin, xmax, ymax四个绝对像素坐标,外加类别名、图像尺寸、难度标记等元信息。它的好处是信息完整、可读性强,用LabelImg打开就能直接看,也方便做数据统计和可视化。而YOLO格式的TXT文件里,每行是class_id x_center y_center width height,全部归一化到0到1之间,直接对应YOLO训练时的标签读取逻辑。

我实际用下来的感受是:VOC格式适合"看"和"改",YOLO格式适合"训"。你在做数据清洗、发现标注错误、调整类别的时候,用VOC的XML最顺手;而一旦进入训练环节,YOLO的TXT省掉了训练时的坐标转换开销,直接读进来就能用。

这里有个坑要提醒:两种格式之间的转换不是简单换个文件就完事。VOC转YOLO时,归一化用的图像宽高必须和实际图像一致,如果数据集里混入了尺寸标注错误的XML,转换出来的TXT坐标就会整体偏移。我建议在转换后随机抽20张做可视化叠加,把框画回原图上肉眼确认一遍,这一步花不了十分钟,但能避免训练出一个"框总是偏一点"的模型。

2.2 单类别设计的利与弊

这个数据集只有1个类别,通常命名为garbage或者litter之类的通用名。单类别的好处非常明显:训练目标单一,模型不需要在类别区分上花精力,收敛快,误检的类别混淆问题直接不存在。对于"有没有垃圾"这个二值判断需求来说,单类别是最经济的选择。

但单类别也有它的局限,你得心里有数。真实场景里,塑料瓶、泡沫、渔网、木板这些垃圾的形态差异极大,如果全部塞进一个类别,模型学到的是一个"平均意义上的垃圾",对小目标或者形态特殊的垃圾可能不够敏感。我在实际项目里的做法是:先用这个单类别数据集训一个基线模型,把召回率拉起来,然后再根据业务需要,把误检和漏检的样本挑出来,人工细分成子类别做二次微调。这样既享受了单类别数据集训练快的优势,又能在后期补上细粒度的需求。

2.3 9627张的规模意味着什么

9627张这个数字,放在通用检测数据集里不算大,但放在垂直领域里是相当扎实的。我做过一个粗略的估算:如果按常见的8:1:1划分训练、验证、测试集,训练集大约7700张,验证集和测试集各960张左右。对于单类别检测,7700张训练图配合标准的在线数据增强(随机翻转、缩放、色彩抖动、Mosaic),足够让YOLOv8n或者YOLOv8s这类轻量模型收敛到一个可用的mAP。

更关键的是,这个规模刚好卡在一个"甜点区":小到你能在一张消费级显卡上几个小时内训完,大到不至于过拟合。我见过太多人拿几百张图去训检测模型,结果验证集mAP虚高,一到真实场景就崩。9627张的体量,配合合理的划分,能给你一个相对可信的泛化能力评估。

数据划分图像数量(约)主要用途
训练集7700模型参数学习
验证集960超参调整、早停判断
测试集960最终精度评估

注意:划分时一定要按"场景"或"飞行架次"来分,而不是纯随机分。如果同一段视频抽出来的相邻帧被分到了训练集和验证集,验证精度会虚高,因为模型见过几乎一样的画面。这一点在无人机视频抽帧的数据集里尤其容易踩坑。

3. 从零跑通训练:核心细节与实操要点

3.1 拿到数据后的第一件事:体检

我拿到任何数据集,第一步永远是"体检",而不是直接开训。具体做这几件事:

第一,统计图像分辨率分布。无人机拍摄的图像分辨率往往不统一,有的是4000×3000,有的是1920×1080,甚至混入了手机拍的图。分辨率差异过大会影响训练时的缩放策略。我的做法是统计出主流的几个分辨率,然后决定统一缩放到哪个尺寸,通常640×640是YOLO的默认输入,但如果小目标多,我会考虑用960甚至1280的输入尺寸。

第二,统计标注框的尺寸分布。把每个框的宽高换算成相对于图像的比例,画个直方图。如果大量框的宽高都小于图像尺寸的2%,说明小目标占比高,这时候要么提高输入分辨率,要么在模型里加P2层(更高分辨率的特征图)来增强小目标检测。

第三,检查类别字段的一致性。单类别数据集最容易出的问题是类别名不统一,比如有的XML写garbage,有的写trash,有的写litter。转换的时候如果不做映射,就会变成多个类别,训练直接乱套。我一般会先跑一遍脚本,把所有出现的类别名列出来去重。

第四,查重复图和近似重复图。无人机视频抽帧很容易产生大量近似帧,用感知哈希(pHash)或者简单的直方图比对就能筛出来。重复图留在训练集里会让模型对某些画面过拟合。

3.2 标注质量抽查:别信"标注好了"这四个字

数据集标称标注完成,不代表标注质量过关。我抽查标注质量有一套固定流程:随机抽50张,把标注框画回原图,逐张看。重点看三类问题:

  • 漏标:水面上明明有垃圾但没框。这在低对比度、垃圾半透明或者被浪花遮挡时特别常见。
  • 误标:把浪花、反光、水鸟、漂浮的树叶当成垃圾框了。海面反光是重灾区,阳光一照,一片白花花的高光很容易被误标。
  • 框不准:框明显偏大或偏小,或者一个垃圾被拆成好几个框。

我实测下来,垂直领域数据集里,漏标和误标的比例通常在5%到15%之间,这个数据集我没法给你一个确切数字,但你自己一定要抽检。发现系统性问题的,要么修正,要么在训练时把这些样本剔除。宁可训练集少几百张干净的,也不要混入大量脏标注,后者对模型的伤害是隐性的、持续的。

3.3 数据增强策略:针对水面场景的定制

通用的YOLO增强(Mosaic、HSV抖动、随机翻转)直接拿来用没问题,但水面垃圾检测有几个特殊点,需要针对性调整。

水平翻转要慎用。水面垃圾的形态本身没有强方向性,水平翻转一般安全。但如果你的应用场景里,垃圾的分布和光照方向强相关(比如总是从某个方向漂来),翻转可能引入不真实的样本。我的做法是水平翻转保留,垂直翻转基本不用,因为无人机俯拍时上下翻转会产生物理上不合理的画面。

色彩抖动幅度要控制。海面颜色从深蓝到灰绿变化很大,适度的HSV抖动有助于模型适应不同水质。但抖动过大,可能把蓝色水面抖成绿色,反而引入噪声。我一般把HSV的H控制在±10,S和V控制在±30以内。

Mosaic增强对小目标有帮助,但要注意边界。Mosaic把四张图拼成一张,能显著增加小目标的出现频率。但水面场景里,拼接边界处可能出现"半截垃圾",如果标注没跟着调整,会引入错误标签。用Mosaic时确保标签同步处理。

可以补充的定制增强:模拟水面波纹的弹性形变、模拟阳光反光的局部亮度提升、模拟雨雾的低对比度处理。这些增强能让模型对真实海面的复杂光照更鲁棒。我用过albumentations里的ElasticTransform和RandomBrightnessContrast组合,效果不错。

3.4 模型选型:为什么我推荐从YOLOv8n或YOLOv8s起步

数据集是YOLO格式,模型自然优先考虑YOLO系列。我的建议是:先用YOLOv8n或YOLOv8s跑一个基线,别一上来就上大模型。

理由很实在。第一,单类别检测任务本身不难,轻量模型足够。第二,轻量模型训练快,你可以在几个小时内跑完一轮,快速验证数据质量和流程是否通畅。第三,无人机部署对模型体积和推理速度有硬要求,n或s级别的模型更容易塞进机载计算单元。

等你确认了数据没问题、流程跑通了,再考虑换YOLOv8m或者带P2小目标检测头的变体来提升精度。如果追求更新的架构,YOLOv10、YOLOv11也可以试,但要注意版本间的API差异,别在环境配置上浪费太多时间。

模型参数量级适用场景我的建议
YOLOv8n最小快速验证、边缘部署首选基线
YOLOv8s小精度与速度平衡主力选择
YOLOv8m中追求更高精度数据确认后再上
带P2头变体中小目标密集小目标多时启用

4. 完整实操流程:从数据到可部署模型

4.1 环境搭建与目录组织

我习惯用conda建独立环境,避免和系统里的其他包打架。核心依赖就是ultralytics、torch、opencv、numpy这几样。装的时候注意torch版本和CUDA版本的匹配,这个坑每年都有人踩。

目录结构我固定成这套,清晰且不容易出错:

dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml

data.yaml是YOLO训练的核心配置文件,内容大致是这样:

path: /path/to/dataset train: images/train val: images/val test: images/test nc: 1 names: ['garbage']

这里nc是类别数,单类别就是1,names里的名字要和标注里的类别对应上。我见过有人把nc写成0或者写成实际类别数加1,训练直接报错或者学出个空类别,这种低级错误检查一遍就能避免。

4.2 从VOC到YOLO的转换脚本要点

虽然数据集号称双格式,但你自己最好会写转换脚本,因为实际项目里你总会遇到只有VOC格式的情况。转换的核心逻辑就三步:读XML拿到图像宽高和框坐标,把绝对坐标归一化,按YOLO格式写TXT。

import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, img_w, img_h, class_map): tree = ET.parse(xml_path) root = tree.getroot() lines = [] for obj in root.findall('object'): cls_name = obj.find('name').text if cls_name not in class_map: continue cls_id = class_map[cls_name] bbox = obj.find('bndbox') xmin = float(bbox.find('xmin').text) ymin = float(bbox.find('ymin').text) xmax = float(bbox.find('xmax').text) ymax = float(bbox.find('ymax').text) x_center = (xmin + xmax) / 2.0 / img_w y_center = (ymin + ymax) / 2.0 / img_h w = (xmax - xmin) / img_w h = (ymax - ymin) / img_h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") return lines

转换完一定要做可视化验证。我写了个小工具,把YOLO的TXT读回来画到原图上,和VOC的XML画出来的框做对比,两者重合才算转换正确。这一步能抓出90%以上的坐标错误。

4.3 训练参数设置与我的调参记录

训练命令本身很简单,关键是参数怎么设。我拿YOLOv8s在单卡上跑过几轮,下面是我实际用的一套参数和背后的考虑:

yolo detect train \ data=dataset/data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ lrf=0.01 \ momentum=0.937 \ weight_decay=0.0005 \ warmup_epochs=3 \ patience=30 \ device=0

几个关键参数的解释:imgsz=640是输入尺寸,如果小目标多可以提到960,但显存占用会翻倍。batch=16是显存和训练稳定性的折中,显存够可以加到32。lr0=0.01是初始学习率,YOLO默认值,配合lrf=0.01做余弦退火,让学习率从0.01平滑降到0.0001。patience=30是早停,验证集30轮不提升就停,防止过拟合。

我实测下来,这个数据集在YOLOv8s上大概60到80轮就能收敛,mAP@0.5能到一个不错的水平。但具体数字取决于你的数据划分和标注质量,别拿别人的数字当自己的目标。

提示:训练时一定要开plots=True(默认开),训练完看results.png里的loss曲线和mAP曲线。如果训练loss一直降但验证loss开始上升,就是过拟合了,要么加数据增强,要么减模型复杂度。

4.4 评估指标怎么看才不被忽悠

YOLO训练完会输出一堆指标,很多人只看mAP@0.5,这是不够的。我建议重点看这几个:

mAP@0.5:IoU阈值0.5时的平均精度,反映"框得差不多对"的能力。这个指标通常最高,但参考价值有限。

mAP@0.5:0.95:IoU从0.5到0.95每隔0.05取一个阈值求平均,反映框的精准度。这个指标更严格,也更接近实际部署要求。

Precision和Recall:精确率和召回率。水面垃圾检测里,召回率往往比精确率更重要,因为漏检一个垃圾的代价通常高于误检。你可以通过调整推理时的置信度阈值来平衡两者。

混淆矩阵:单类别任务里混淆矩阵意义不大,但可以看背景被误判为垃圾的比例,这个比例高说明误检多。

我踩过的一个坑是:验证集mAP很高,但实际拿无人机视频去测,漏检严重。后来发现是验证集和训练集来自同一批飞行架次,场景太相似。评估一定要留出独立的、不同场景的测试集,否则指标再高也是自欺欺人。

5. 常见问题与排查技巧实录

5.1 训练不收敛或loss震荡

这是最常见的问题。排查顺序我固定成这套:先看学习率是不是太大,lr0=0.01对某些数据集偏大,可以降到0.001试试;再看batch size是不是太小,batch太小梯度噪声大,loss会震荡;然后检查标注有没有问题,比如坐标超出0到1范围、类别id越界;最后看数据本身,如果图像质量太差或者标注太乱,模型学不动是正常的。

我遇到过一次loss死活不降,最后发现是data.yaml里的路径写错了,模型一直在读空标签。这种问题看着低级,但排查起来很费时间,建议训练前先跑一遍数据加载的dry run。

5.2 小目标漏检严重

水面垃圾里,远处的塑料瓶、小片泡沫都是小目标。漏检的原因通常是特征图分辨率不够。解决办法有三个:提高输入尺寸(640提到960或1280)、在模型里加P2检测头、用切片推理(把大图切成小块分别检测再合并)。我一般先试提高输入尺寸,成本最低;不够再上P2头;如果部署时算力允许,切片推理对小目标效果最好。

5.3 水面反光导致误检

这是水面场景特有的问题。阳光反射、浪花高光在图像上表现为亮斑,和白色泡沫垃圾很像。缓解办法:训练时加入模拟反光的增强样本,让模型学会区分;推理时如果误检集中在特定光照条件,可以针对性地补充这类负样本(没有垃圾但有反光的图)进训练集。负样本的加入对降低误检非常有效,我通常会在训练集里掺入5%到10%的纯背景图。

5.4 常见问题速查表

问题现象可能原因排查与解决
loss不降学习率过大、路径错误、标注越界降lr、检查yaml路径、校验标注范围
验证mAP虚高训练验证集场景重叠按飞行架次重新划分
小目标漏检输入分辨率不足提高imgsz或加P2头
反光误检负样本不足补充纯背景图、加反光增强
推理速度慢模型过大、输入尺寸过大换n/s模型、降imgsz、导出ONNX/TensorRT
框偏移VOC转YOLO坐标错误可视化验证转换结果

5.5 我踩过的几个真实坑

第一个坑:图像和标签文件名不匹配。YOLO读取标签时是按文件名对应的,img001.jpg对应img001.txt。如果转换时文件名带了多余后缀或者大小写不一致,标签就读不到,模型会把这些图当成纯背景训练。我现在的习惯是转换后写个脚本,检查images和labels目录下的文件名集合是否完全一致。

第二个坑:测试集泄露。有一次我图省事,测试集直接从训练集里随机抽的,结果测试mAP高得离谱,实际部署一塌糊涂。后来严格按场景划分,测试mAP降了但真实表现反而更可信。

第三个坑:忽略图像EXIF方向。有些无人机或手机拍的图带EXIF旋转信息,用某些库读进来是正的,用另一些库读进来是躺倒的,导致标注框和图像对不上。统一用OpenCV读取并做EXIF校正能避免这个问题。

6. 部署侧的几个现实考量

数据集训出模型只是第一步,真正落地到无人机上还有几道坎。我说几个实际项目里绕不开的点。

模型体积和推理速度。无人机机载计算单元算力有限,YOLOv8s导出成ONNX再转TensorRT,在Jetson这类设备上能做到实时。如果算力更紧张,就得上YOLOv8n甚至更小的定制模型。导出时注意用half=True做FP16量化,速度能提升不少,精度损失通常在可接受范围。

输入尺寸和飞行高度的匹配。模型是在640或960的输入上训的,实际飞行时如果高度变了,垃圾在画面里的像素尺寸就变了,检测效果会波动。解决办法是固定飞行高度,或者训练时用多尺度增强让模型适应不同尺度。我一般建议客户把巡检高度固定在一个范围,比如离水面30到50米,这样模型表现最稳定。

后处理与业务逻辑。检测框出来之后,还要做去重(相邻帧的同一个垃圾)、坐标映射(像素坐标转经纬度)、告警分级(大块垃圾优先处理)。这些逻辑不在模型里,但决定了系统好不好用。我通常会把检测结果和无人机的GPS、IMU数据做时间对齐,再通过单应变换把像素坐标投到地面坐标系,这样输出的就是带地理位置的垃圾清单。

持续迭代。任何模型上线后都会遇到新的场景,比如不同季节的水质、不同海域的垃圾类型。我的做法是留一个反馈通道,把线上漏检和误检的样本定期回收,人工标注后加入训练集做增量训练。这个闭环建起来,模型才会越用越准。

7. 这个数据集还能怎么扩展

单类别水面垃圾检测是个很好的起点,但业务需求往往会往两个方向延伸。

一个是细分类。把garbage拆成塑料、泡沫、渔网、木质、其他这几类,模型能输出更具体的垃圾类型,便于后续处理决策。做法是在现有标注基础上做二次标注,然后微调模型。类别变多后,要注意类别不平衡问题,小类别样本要适当过采样。

另一个是多任务。除了检测框,还可以加分割掩码(精确勾勒垃圾轮廓,估算面积)、加密度估计(整片海域的垃圾密度热力图)。YOLOv8本身支持分割任务,如果你有分割标注,可以直接训一个分割模型。没有分割标注的话,可以用检测框做弱监督,效果会打折扣但也能用。

再往远了想,这个数据集可以和无人机的航线规划结合。检测到垃圾密集区域后,自动调整后续飞行航线去重点巡查,形成一个"检测—决策—再检测"的闭环。这就从单纯的视觉任务升级成了系统级的解决方案,也是我觉得这类数据集最有想象空间的地方。

我在实际项目里最大的体会是:数据集的质量和场景匹配度,比模型结构的选择重要得多。一个9627张、场景对口的单类别数据集,配合一个调好的YOLOv8s,能解决80%的实际需求。剩下的20%,靠的是你对业务场景的理解和持续的数据迭代。别一上来就追求花哨的架构,先把数据这条链路走通、走扎实,比什么都强。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询