ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLOv5水下垃圾检测实战:从数据标注到模型训练与推理

YOLOv5水下垃圾检测实战:从数据标注到模型训练与推理 简介这份资源面向计算机视觉学习者与水下垃圾检测方向的开发者提供一套可直接复现的YOLOv5水下垃圾检测方案解决从数据准备到模型训练、评估的完整流程问题。压缩包共147个文件约213.98MB包含31个Python脚本、42个yaml配置、3个pt权重文件以及jpg图片、xml标注、png曲线图、md说明文档等覆盖训练、推理与结果展示各环节。资源内含训练好的水下垃圾检测权重并附PR曲线、loss曲线等评估结果便于直接验证效果同时提供数千张真实场景水下垃圾图像经labelimg标注含VOC与YOLO两种格式类别涵盖metal、wood、plastic、rubber、cloth等场景丰富。目前已有1929人学习下载适合希望快速上手水下目标检测、开展课程设计或科研实验的读者参考使用。1. 水下垃圾检测为什么值得单独拆一个 YOLOv5 工程做水下机器人、海洋环保监测或者水产养殖巡检的团队几乎都会碰到同一个问题通用目标检测模型在水下图像上直接翻车。原因不复杂——水体对红光的吸收、悬浮颗粒的散射、人工光源造成的亮度不均让水下图像的色彩分布和陆上数据集完全不是一回事。拿 COCO 预训练权重直接推理塑料瓶和塑料袋经常被识别成运动器材或干脆漏检。这份资源解决的就是这个断层它提供了一套已经训练好的 YOLOv5 水下垃圾检测权重配套几千张用 labelImg 标注的真实场景图片标签同时给了 VOC 和 YOLO 两种格式类别覆盖 metal、wood、plastic、rubber、cloth 等常见海洋垃圾类型。仓库里还带了训练过程的 events 日志、results.csv、PR 曲线和 loss 曲线等于把数据—训练—评估整条链路都摊开了。适合两类人一类是想快速验证水下检测可行性、不想从零标数据的工程团队另一类是正在学 YOLOv5 训练自己数据集、需要一个真实非理想场景练手的开发者。下面按资源结构 → 环境与数据 → 训练与推理 → 避坑 → 进阶验证的顺序拆开讲。2. 资源结构与 YOLOv5 数据管线先搞清楚手里有什么2.1 仓库文件逐个说明拿到压缩包先别急着跑训练花五分钟把目录结构过一遍能省掉后面大量文件找不到的报错。这份资源的核心文件大致分四类文件/目录作用是否必须保留events.out.tfevents.*TensorBoard 训练日志记录 loss、mAP 等标量建议保留用于复现曲线results.csv每个 epoch 的指标表格含 box_loss、obj_loss、mAP_0.5必须保留评估基线train_batch1.jpg/train_batch2.jpg训练时数据增强后的批次可视化可选用于检查增强是否合理Dockerfile/.dockerignore容器化环境定义可选本地有环境可忽略yolov5-6.0.imlIDE 模块配置非代码文件可删.gitattributes/.gitignore版本控制配置保留避免误提交大文件results.csv是最容易被忽略但最有价值的文件。它记录了每个 epoch 的train/box_loss、train/obj_loss、metrics/mAP_0.5、metrics/mAP_0.5:0.95你可以直接用它判断这份权重是不是过拟合、训练了多少轮收敛。常见做法是用 pandas 读进来画一条曲线比看 TensorBoard 还快。2.2 VOC 与 YOLO 两种标签格式的差异资源里标签分两个文件夹存放这是很贴心的设计但很多人搞不清什么时候用哪个。VOC 格式是每张图对应一个 XML里面用bndbox记录xmin/ymin/xmax/ymax绝对像素坐标YOLO 格式是每张图对应一个 txt每行class_id x_center y_center width height全部归一化到 0~1。YOLOv5 训练只认 YOLO 格式所以 VOC 那套主要是给你做数据审查、转换或者喂给其他框架用的。转换逻辑不复杂但有两个坑一是坐标越界标注时框超出图像边界归一化后会出现大于 1 的值二是类别名和data.yaml里的names顺序必须严格对应否则训练出来的模型会把塑料识别成木头。import xml.etree.ElementTree as ET import os # VOC 类别顺序必须和 data.yaml 的 names 完全一致 classes [metal, wood, plastic, rubber, cloth] def voc_to_yolo(xml_path, img_w, img_h, out_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue # 跳过未定义类别避免索引错位 cls_id classes.index(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) # 裁剪到图像边界防止归一化后越界 xmin, xmax max(0, xmin), min(img_w, xmax) ymin, ymax max(0, ymin), min(img_h, ymax) xc (xmin xmax) / 2.0 / img_w yc (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))这段脚本的关键点在max(0, xmin)和min(img_w, xmax)这两行裁剪。水下图像标注时因为能见度低标注员经常把框画到画面边缘外不裁剪的话 YOLOv5 在数据加载阶段会直接抛non-normalized coordinates警告严重时该图被跳过。classes列表的顺序就是最终模型输出的类别索引改顺序等于改标签含义务必和data.yaml对齐。2.3 data.yaml 的写法与路径陷阱YOLOv5 靠一个 yaml 文件告诉训练器去哪找图、类别有几个。这份资源常见做法是写成下面这样# data/underwater.yaml train: ../datasets/underwater/images/train val: ../datasets/underwater/images/val nc: 5 names: [metal, wood, plastic, rubber, cloth]nc是类别数必须等于names长度写错了训练不报错但 mAP 会莫名其妙很低。train和val指向的是 images 目录YOLOv5 会自动把路径里的images替换成labels去找同名 txt。所以你的目录必须是images/train/xxx.jpg配labels/train/xxx.txt文件名不含扩展名一一对应。很多人把标签和图片放同一目录结果训练时提示找不到标签就是踩了这个约定。3. 环境配置与训练复现从 conda 到第一个 epoch3.1 环境搭建与依赖版本YOLOv5 6.0 这个版本对 PyTorch 和 CUDA 比较敏感用太新的 torch 会出现torch.load权重不兼容或者amp报错。稳妥的组合是 Python 3.8 PyTorch 1.10~1.12 CUDA 11.3。低显存机器比如 6G 显存的笔记本也能跑但要调 batch size 和图像尺寸。# 创建独立环境避免和系统里的 torch 冲突 conda create -n underwater python3.8 -y conda activate underwater # 安装匹配 CUDA 11.3 的 torch具体版本按自己驱动选 pip install torch1.12.1cu113 torchvision0.13.1cu113 \ --extra-index-url https://download.pytorch.org/whl/cu113 # 安装 yolov5 依赖 cd yolov5-6.0 pip install -r requirements.txt--extra-index-url那行是告诉 pip 去 PyTorch 官方源找带 CUDA 的包不加的话默认装 CPU 版训练速度会慢到怀疑人生。装完用python -c import torch; print(torch.cuda.is_available())验证返回 True 才算环境通了。requirements.txt 里会装matplotlib、opencv-python、tqdm这些如果公司内网 pip 慢提前配好镜像源。3.2 用预训练权重启动训练资源里已经带了训练好的权重但你要在自己的数据上微调或者复现还是得走一遍训练命令。YOLOv5 6.0 的入口是train.py最简命令如下python train.py \ --data data/underwater.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0 \ --project runs/train \ --name underwater_exp逐个参数说清楚--weights yolov5s.pt是官方在 COCO 上预训练的骨干用它初始化比从零训练收敛快得多水下场景也建议这么干--img 640是输入分辨率显存不够就降到 416 或 320但小目标比如远处的塑料碎片会掉点--batch 16在 8G 显存上比较稳6G 显存建议降到 8 并配合--img 512--device 0指定第一块 GPU多卡用0,1--name决定输出目录训练日志、权重、曲线都会存到runs/train/underwater_exp/下。训练启动后重点盯三个输出train/box_loss应该稳定下降如果震荡剧烈多半是学习率太大或标注噪声多metrics/mAP_0.5在前 10 个 epoch 涨得慢是正常的水下数据收敛本来就比 COCO 慢val/obj_loss如果开始上升而 train loss 还在降说明过拟合了该早停或者加数据增强。3.3 推理与结果验证训练完或者直接用资源里的权重推理命令是detect.pypython detect.py \ --weights runs/train/underwater_exp/weights/best.pt \ --source data/samples \ --img 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --project runs/detect \ --name underwater_test--conf-thres 0.25是置信度阈值水下图像噪声大调太高会漏检调太低会满屏误检0.25 是个常用起点--iou-thres 0.45控制 NMS 合并重叠框的力度同一堆垃圾挨得近时可以适当调高到 0.5 避免误合并--save-txt会把检测结果按 YOLO 格式存下来方便你后续做统计或者二次处理。结果图默认存到runs/detect/underwater_test/先拿几张典型场景浑浊水、强反光、密集垃圾肉眼过一遍比只看 mAP 数字靠谱。4. 水下场景训练避坑五条血泪经验4.1 现象mAP 卡在 0.3 上不去loss 也不降原因通常是类别不平衡。水下垃圾里 metal 和 plastic 样本多cloth 和 rubber 可能只有几十张模型倾向于预测多数类。解决方法是检查results.csv里每个类别的 AP如果某一类特别低要么补数据要么在data.yaml里给这类加过采样或者用--hyp指定带类别权重的超参文件。YOLOv5 默认的hyp.scratch-low.yaml对不平衡数据不友好可以手动调cls损失权重。4.2 现象训练报 No labels found 但标签明明存在九成是路径问题。YOLOv5 找标签的规则是把图片路径里的/images/替换成/labels/再把扩展名换成.txt。如果你的目录是images/train和labels/train没问题但如果是train/images和train/labels替换逻辑就对不上。解决方法是严格按datasets/underwater/images/train和datasets/underwater/labels/train组织或者用--data里写绝对路径排查。4.3 现象显存溢出 CUDA out of memory水下图像分辨率普遍偏高原始图可能 1920×1080直接喂进去显存瞬间爆。YOLOv5 会在 dataloader 里 resize 到--img指定尺寸但如果你的--img设成 1280 又用--batch 168G 卡必炸。解决方法是降--img到 640 或 512降--batch到 8或者开--multi-scale让尺寸动态变化但整体更省。实在不够就上--device cpu先跑通流程再换机器。4.4 现象检测框位置偏移框不住目标多半是标注格式转换时坐标系搞混了。VOC 用的是左上角和右下角绝对坐标YOLO 用的是中心点加宽高归一化。转换脚本里如果忘了除以图像宽高或者把xmax-xmin写成了xmax-xmin1框就会系统性偏移。解决方法是转换后随机抽 10 张图用labelImg或自己写脚本把 YOLO 标签画回图上肉眼比对一遍再开训。4.5 现象验证集 mAP 高但实际推理效果差这是典型的验证集和真实场景分布不一致。如果验证集图片和训练集来自同一批拍摄、同样的光照条件mAP 会虚高。解决方法是手动划出一批不同水域、不同深度的图片做测试集或者用detect.py跑真实视频抽帧看漏检和误检集中在哪类场景。水下检测里浑浊水和清澈水的表现能差 20 个点别被单一验证集骗了。5. 进阶用 results.csv 反推训练质量与权重选型拿到一份训练好的权重怎么判断它值不值得用别只看最终 mAPresults.csv里藏着更多信息。用下面这段脚本把关键曲线画出来比 TensorBoard 更灵活import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/underwater_exp/results.csv) df.columns df.columns.str.strip() # 列名可能带空格先清理 fig, axes plt.subplots(1, 3, figsize(15, 4)) axes[0].plot(df[epoch], df[train/box_loss], labelbox_loss) axes[0].plot(df[epoch], df[val/box_loss], labelval_box_loss) axes[0].legend(); axes[0].set_title(Box Loss) axes[1].plot(df[epoch], df[metrics/mAP_0.5], labelmAP0.5) axes[1].plot(df[epoch], df[metrics/mAP_0.5:0.95], labelmAP0.5:0.95) axes[1].legend(); axes[1].set_title(mAP) axes[2].plot(df[epoch], df[x/lr0], labellr0) axes[2].legend(); axes[2].set_title(Learning Rate) plt.savefig(training_curves.png, dpi150)看三条线就能判断权重质量。第一train/box_loss和val/box_loss的差距如果验证 loss 在某个 epoch 后持续上升说明过拟合应该取上升前的那个 epoch 的权重而不是最后一个。第二mAP_0.5的收敛点如果 50 个 epoch 就平了后面 50 个 epoch 基本是浪费说明数据量或学习率已经到瓶颈。第三学习率曲线YOLOv5 默认用余弦退火lr0应该平滑下降如果出现跳变可能是--cos-lr没开或者中断续训导致。选权重时我一般会同时导出best.pt和last.pt各跑一遍测试集best.pt是验证集 mAP 最高的但有时last.pt在真实场景反而更稳因为验证集本身可能有偏。资源里带的 PR 曲线也值得看如果某一类的曲线下面积明显小说明这类样本太少或者特征和别的类混淆比如 rubber 和 plastic 在浑浊水里颜色接近容易互相误判。还有一个容易被忽略的点events.out.tfevents文件可以用tensorboard --logdir runs/train直接打开里面除了 loss 还有每层的梯度分布和权重直方图。如果发现某些层梯度长期接近零说明这些层没学到东西可能是冻结策略不对或者学习率太小。我习惯在正式部署前把best.pt在至少三个不同来源的测试集上跑一遍只有三个都稳定才敢上线。从那以后我每次拿到新权重都强制先画一遍 results.csv 曲线再决定用哪个希望帮到你。本文还有配套的精品资源点击获取
返回列表