基于YOLO与Trash-ICRA19的海洋垃圾检测实战指南
简介本资源为面向计算机、电子信息工程、数学等专业学生的YOLO目标检测实战数据集基于Trash-ICRA19海洋垃圾检测场景构建可直接用于课程设计、期末大作业与毕业设计。压缩包共2288个文件包含1144张jpg图像与1144个一一对应的xml标注文件标注格式可直接接入YOLO训练流程整体约26.21MB图像与标注配对完整省去自行采集与标注的时间成本。内容覆盖bio、obj等多类海洋目标样本适合训练与验证海洋垃圾检测模型。目前已有259人学习下载可作为目标检测入门到进阶的练手素材。读者可借此快速搭建数据加载、模型训练与评估链路理解标注解析、类别映射与数据增强等关键环节并在此基础上替换网络结构或调整参数开展对比实验形成完整的检测方案与实验记录。1. 海洋垃圾检测为什么值得用 YOLO 加 Trash-ICRA19 跑一遍如果你手上正好有一批海洋场景的监控图像想快速验证「能不能自动把漂浮垃圾框出来」那 YOLO 目标检测加 Trash-ICRA19 数据集这条路线是当前门槛最低、反馈最快的一种组合。Trash-ICRA19 是一个面向海洋垃圾检测的公开标注数据集图像来自水下与水面场景标注文件已经按检测任务整理好拿到手就能直接喂给 YOLO 系列模型训练不需要自己从零标注。1144 张图像听起来不多但对于验证一个检测思路、跑通训练到推理的完整链路这个量级刚好够用——既不会让你等太久也能暴露出小目标、遮挡、水下色偏这些真实问题。这篇文章面向的是想动手的从业者你可能是做环保监测的工程师也可能是想找一个真实场景练手检测模型的学生或开发者。接下来我会把数据怎么接、YOLO 怎么配、参数怎么调、坑在哪一层层拆开讲清楚。2. 先搞清楚 Trash-ICRA19 的数据结构和 YOLO 的对接方式2.1 数据集里到底有什么为什么它适合直接上手Trash-ICRA19 的核心价值在于「已标注」三个字。它通常包含图像文件夹和对应的标注文件标注格式多为 XML 或 TXT记录每张图里垃圾目标的类别和边界框坐标。海洋垃圾检测的难点在于目标往往很小、颜色和水体接近、还有水流造成的形变这个数据集把这些真实困难都保留了下来所以拿它训练出来的模型迁移到实际监控场景时不会出现「实验室里很准、下水就翻车」的落差。从类别设计上看它一般会区分几类常见海洋垃圾比如塑料制品、金属、橡胶等具体类别数以你拿到的标注文件为准。这里要提醒一句不同来源的标注文件类别命名和编号可能不一致训练前必须自己核对一遍否则模型学出来的类别索引和你的预期会对不上。我一般会先写个小脚本统计所有标注文件里出现过的类别名确认没有拼写差异或多余空格这一步花五分钟能省掉后面几小时的排查。2.2 把标注转成 YOLO 格式转换脚本与四个边界坑YOLO 需要的标注格式是每张图对应一个 TXT 文件每行是「类别编号 中心x 中心y 宽 高」坐标全部归一化到 0 到 1 之间。而 Trash-ICRA19 原始标注如果是 XML 格式坐标是左上角和右下角的绝对像素值必须做转换。下面这个脚本是我常用的转换逻辑假设原始标注是 XML图像尺寸从 XML 里读取。import os import xml.etree.ElementTree as ET # 类别映射表必须和你的标注文件里的类别名完全一致 class_map { plastic: 0, metal: 1, rubber: 2, other: 3 } def convert_annotation(xml_path, img_w, img_h, out_txt_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text.strip() 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) # 归一化并转成中心点加宽高 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 边界裁剪防止坐标越界导致训练异常 cx min(max(cx, 0.0), 1.0) cy min(max(cy, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines)) # 批量处理示例 img_dir images xml_dir annotations out_dir labels os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue xml_path os.path.join(xml_dir, xml_file) # 这里假设图像尺寸固定实际应从对应图像读取 img_w, img_h 640, 480 out_txt os.path.join(out_dir, xml_file.replace(.xml, .txt)) convert_annotation(xml_path, img_w, img_h, out_txt)这段代码里有四个容易踩的边界坑。第一类别映射表必须和标注文件里的名称逐字匹配大小写和空格都算否则目标会被静默跳过。第二归一化前要确认图像真实宽高不能硬编码不同来源的图像尺寸可能不一样。第三坐标要裁剪到 0 到 1有些标注框会略微超出图像边界不裁剪会导致训练时损失计算出 NaN。第四空标注文件也要生成YOLO 训练时如果某张图没有对应 TXT会被当成背景图处理但如果你希望它参与负样本学习保留空文件更稳妥。2.3 划分训练集和验证集别让同一场景的图像同时出现在两边数据划分看起来简单但在海洋检测里有个隐蔽问题同一段视频抽出来的帧或者同一位置连续拍摄的图像如果随机划分训练集和验证集会高度相似验证指标虚高实际部署时性能掉得厉害。我的做法是按图像来源或拍摄批次分组同一组的图像只进训练集或只进验证集。如果数据集没有提供来源信息至少按文件名前缀或时间戳做粗略分组。# 按 8:2 划分先打乱再取但打乱前按前缀分组 ls images | shuf all.txt head -n 915 all.txt train.txt tail -n 229 all.txt val.txt这里 1144 张按 8:2 分训练集 915 张验证集 229 张。数量不大所以验证集不要太小否则指标波动会很大。如果发现验证集指标忽高忽低先检查是不是划分时把相似图像分到了两边。3. 用 YOLO 训练海洋垃圾检测模型配置、参数与训练过程3.1 选 YOLOv5 还是 YOLOv8小数据集上差别在哪面对 1144 张图像这个量级YOLOv5 和 YOLOv8 都能跑但选择上有实际差异。YOLOv5 的生态更成熟配置文件直观社区里针对小数据集的调参经验多出问题容易搜到答案。YOLOv8 的默认增强策略更强对小数据集更友好但配置文件结构变化较大第一次上手需要适应。我一般会先用 YOLOv5s 跑一个基线确认数据管道没问题再换 YOLOv8n 对比。两个模型都很轻单卡训练几小时就能出结果。选型时还要看你的部署目标。如果最终要跑到边缘设备上YOLOv5n 或 YOLOv8n 这种 nano 级别更合适参数量小推理快。如果只在服务器上跑可以用 s 或 m 级别精度会好一些。海洋垃圾检测里小目标多输入分辨率不要低于 640否则小目标在特征图上几乎消失。3.2 训练命令与关键参数从 data.yaml 到超参数YOLO 训练的核心是 data.yaml 文件它告诉模型去哪里找图像、类别数是多少、类别名是什么。下面是一个针对 Trash-ICRA19 的配置示例。# data.yaml train: ./train.txt val: ./val.txt nc: 4 names: [plastic, metal, rubber, other]train 和 val 指向图像路径列表文件nc 是类别数names 要和转换脚本里的 class_map 顺序一致。配置好后用命令行启动训练。# YOLOv5 训练示例 python train.py --data data.yaml --weights yolov5s.pt --img 640 --epochs 100 --batch 16 --device 0参数逐个说--img 640 是输入分辨率海洋小目标建议不低于 640--epochs 100 对 1144 张图来说够用如果验证集指标还在涨可以加到 150--batch 16 取决于显存显存不够就降到 8--device 0 指定第一块 GPU。训练过程中重点看验证集的 mAP0.5 和 mAP0.5:0.95前者反映能不能框到后者反映框得准不准。海洋垃圾检测里 mAP0.5 通常能到 0.6 以上但 mAP0.5:0.95 会低不少因为水下目标边界模糊框的精度天然受限。3.3 数据增强怎么开海洋场景下哪些增强有用哪些有害YOLO 默认开启的增强包括 HSV 色调饱和度调整、随机翻转、缩放和平移。海洋场景下HSV 增强很有用因为水下图像色偏严重模型需要对颜色变化鲁棒。随机翻转也可以但要注意如果图像里有方向性目标比如某些有朝向的垃圾翻转可能引入不合理样本。缩放和平移对小目标检测有帮助但缩放幅度不要太大否则小目标变得更小。有一个增强要谨慎使用马赛克增强。它把四张图拼成一张能增加小目标数量但在海洋场景下拼接后的图像会出现不自然的边界模型可能学到拼接伪影而不是真实特征。我的经验是前期开启马赛克后期最后 10 到 20 个 epoch 关掉让模型在真实分布上微调。YOLOv5 里可以用 --mosaic 0 在最后阶段关闭或者用 close_mosaic 参数控制。4. 海洋检测场景下的避坑与排查记录4.1 验证集 mAP 很高但实际推理框不住先查标注坐标是否归一化错误现象训练日志里 mAP0.5 到了 0.8但拿几张训练集里的图做推理框的位置明显偏移甚至框到了图像外面。原因标注转换时归一化用错了图像尺寸比如用了一个固定值而不是每张图的真实宽高导致坐标系统性偏移。解决写一个校验脚本随机抽 20 张图把 YOLO 格式的标注还原成像素坐标画到图上肉眼确认框是否贴合目标。这个步骤我每次转换完都会做花十分钟能拦住大部分标注问题。4.2 训练损失正常但验证损失震荡检查验证集里是否有空标注图像现象训练损失稳步下降验证损失忽高忽低mAP 波动超过 0.1。原因验证集里混入了没有标注目标的图像或者标注文件为空但图像里有目标。YOLO 对空标注的处理是当作背景但如果验证集里背景图比例过高指标会不稳定。解决统计验证集里每个 TXT 文件的行数行数为 0 的比例不要超过 10%。如果超过要么补充标注要么把这些图移到训练集当负样本。4.3 小目标漏检严重别急着换模型先看输入分辨率和锚框现象大块垃圾能框到小片塑料漏检。原因输入分辨率太低小目标在 32 倍下采样后只剩几个像素或者默认锚框尺寸不适合海洋垃圾的尺度分布。解决先把 --img 从 640 提到 800 或 960看漏检是否改善。如果改善明显说明是分辨率问题。如果改善有限用 k-means 重新聚类锚框用你数据集的真实框尺寸跑一遍替换默认锚框。YOLOv5 里可以用 --anchor 指定自定义锚框文件。4.4 推理时类别置信度普遍偏低检查类别不平衡和置信度阈值现象模型能框到目标但置信度大多在 0.3 到 0.5 之间调高阈值就漏检调低就误检。原因类别不平衡某些类别样本太少模型对它们的学习不充分。解决先统计每个类别的标注框数量如果最少类别和最多类别差 5 倍以上考虑对少样本类别过采样或者用 focal loss 这类对不平衡更鲁棒的损失。推理时置信度阈值不要一刀切可以按类别分别设少样本类别适当降低阈值。4.5 训练到一半显存溢出排查图像尺寸不一致和 batch 设置现象训练前几个 epoch 正常突然报显存不足。原因数据集中混入了尺寸特别大的图像或者某些图像通道数不是 3。解决训练前统一检查所有图像的尺寸和通道数把异常图像挑出来。YOLO 默认会 resize但如果原图极大resize 前的内存占用也会很高。另外如果开了多尺度训练每轮图像尺寸随机变化显存占用会波动batch 要留足余量。5. 把模型用起来推理、验证与一个提升小目标召回的具体技巧训练完之后真正要验证的是模型在没见过的海洋图像上能不能用。推理命令很简单但有几个参数直接影响你看到的结果。python detect.py --weights runs/train/exp/weights/best.pt --source test_images --img 800 --conf 0.25 --iou 0.45--img 800 是推理分辨率可以和训练时不同适当提高对小目标有利。--conf 0.25 是置信度阈值低于这个值的框不显示。--iou 0.45 是 NMS 的 IoU 阈值控制重叠框的合并程度。海洋场景里目标密集时IoU 可以调到 0.5 到 0.6避免把相邻目标误合并。验证模型是否值得投入不能只看 mAP。我一般会做三件事。第一按类别看召回率确认没有某个类别完全漏检。第二按目标尺寸分段统计小目标召回率如果低于 0.3说明模型对小目标还不够敏感。第三拿一批完全没参与训练的图像跑一遍人工数一下漏检和误检算一个实际可用率。这个数字比 mAP 更能反映落地价值。最后分享一个提升小目标召回的具体技巧在推理阶段用切片推理。把一张大图切成有重叠的小块分别检测再把结果合并。这样小目标在每一块里的相对尺寸变大更容易被检测到。代价是推理时间增加但召回率通常能提升 10 到 20 个百分点。实现上可以写一个简单的滑动窗口脚本窗口大小设为 640重叠 128 像素每块单独推理后按坐标映射回原图再用 NMS 合并。这个技巧在海洋监测里特别实用因为监控图像往往视野大、目标小直接整图推理很容易漏掉远处的垃圾。我自己在这个方向上踩过最深的坑是早期太相信验证集指标没做按尺寸分段的召回统计结果模型在验证集上看着不错实际部署到一段新视频上小片塑料几乎全漏。后来养成了习惯每次训练完先跑一遍分尺寸召回再决定要不要继续调。希望帮到你。本文还有配套的精品资源点击获取