多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

基于YOLO的海洋垃圾识别分类:从数据增强到模型调优的毕设实战指南

基于YOLO的海洋垃圾识别分类:从数据增强到模型调优的毕设实战指南 简介这份资源是面向计算机相关专业学生与项目实战学习者的毕业设计完整方案主题为基于卷积神经网络的海洋垃圾识别分类可直接用于毕设、课程设计或期末大作业。压缩包共101个文件约74.62MB涵盖20个Python源码、7个H5模型权重、9个XML标注、6个CSV数据集、7份Markdown说明文档及若干图片与配置脚本覆盖模型构建、数据处理、界面设计与训练记录等环节。项目围绕CNN自动提取图像特征对海洋垃圾进行识别与分类帮助理解从数据集训练到模型优化的完整流程。已有180人学习关注。读者可获得可运行的源码、项目说明文档与调试经验既能降低毕设开发工作量也能借此掌握深度学习图像分类的实战方法。1. 海洋垃圾识别为什么成了毕业设计里的“硬骨头”每年到了毕设选题季总有一批同学盯着“深度学习环保”这个方向。海洋垃圾识别分类听起来既贴合热点又有实际价值但真正动手才发现公开数据集少得可怜水下图像偏色严重类别还极度不均衡。我见过太多人卡在第一步——数据从哪来、怎么标、模型选哪个、训完为什么精度上不去。这个项目的核心是用卷积神经网络对海洋环境中的垃圾做自动识别与分类。它解决的不是“能不能识别”的问题而是“在浑浊、偏色、遮挡的真实水下画面里怎么把塑料瓶、塑料袋、渔网、金属罐这些目标稳定区分开”。适合两类人一是正在找毕设题目的本科生需要一套能跑通、能写进论文的完整方案二是刚转深度学习方向的工程师想拿一个中等规模的项目练手把数据增强、迁移学习、类别不平衡处理这些环节走一遍。我自己的经验是这类项目最大的坑不在模型结构而在数据管线和评估方式。下面按“数据怎么准备→模型怎么搭→训练怎么调→坑在哪→怎么验证”的顺序把整套流程拆开讲。2. 数据从哪来、怎么标、怎么增强2.1 公开数据集的获取与筛选海洋垃圾识别没有像 COCO 那样现成的大一统数据集常见做法是组合几个来源。我一般会从以下几个方向找水下垃圾检测数据集部分学术机构会公开标注好的水下图像类别通常包括塑料、金属、玻璃、渔具等。通用垃圾数据集陆地上的垃圾分类数据集可以迁移一部分类别但要注意水下和陆地的域差异。自采集补充如果条件允许用防水相机在近岸浅水区拍摄哪怕只有几百张也能显著提升模型对本地场景的适应。筛选时有个硬标准图像必须包含目标物体的完整或大部分轮廓。那些目标只露出一个角、或者被泥沙完全糊住的样本标了也是噪声。我一般会先过一遍把模糊到人眼都难分辨的图直接剔除。2.2 标注规范与格式转换标注用 LabelImg 或 CVAT 都行关键是统一规则。海洋垃圾的边界框容易画大因为水下目标边缘模糊。我的做法是框到目标可见轮廓的最外沿不脑补被遮挡的部分。标注完成后VOC 格式的 XML 需要转成 YOLO 或 COCO 格式。下面是一个 VOC 转 YOLO 的脚本import xml.etree.ElementTree as ET import os # 类别映射根据自己数据集修改 CLASS_MAP {plastic: 0, metal: 1, glass: 2, fishing_net: 3} 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.findall(object): cls_name obj.find(name).text if cls_name not in CLASS_MAP: continue 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) # YOLO 格式中心点归一化坐标 宽高归一化 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{CLASS_MAP[cls_name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))这段代码的逻辑很直接读 XML取边界框坐标做归一化。参数说明img_w和img_h必须和实际图像尺寸一致否则框会偏移。CLASS_MAP的索引要和后续模型输出的类别数对齐改类别时两边都要改。2.3 针对水下场景的数据增强通用增强翻转、旋转、缩放在水下场景不够用因为水下图像有独特的偏色和对比度衰减。我一般会加这几类增强颜色通道扰动模拟不同水深下的色偏蓝绿通道偏移是常态。对比度受限自适应直方图均衡化CLAHE提升局部对比度让模糊目标更清晰。随机雾化模拟水体浑浊用高斯噪声叠加低透明度层。用 Albumentations 实现import albumentations as A transform A.Compose([ A.HorizontalFlip(p0.5), A.RandomBrightnessContrast(p0.3), # 模拟水下蓝绿偏色 A.RGBShift(r_shift_limit20, g_shift_limit30, b_shift_limit40, p0.4), # CLAHE 提升局部对比度 A.CLAHE(clip_limit2.0, tile_grid_size(8, 8), p0.5), A.GaussNoise(var_limit(10.0, 50.0), p0.3), A.Resize(640, 640), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels]))参数说明RGBShift的偏移范围不要太大否则颜色失真到模型学不到真实特征。CLAHE的clip_limit超过 3.0 容易放大噪声。Resize统一到 640 是 YOLO 系列的常见输入尺寸用其他模型时按需调整。3. 模型选型与训练策略3.1 为什么选 YOLO 而不是两阶段检测器海洋垃圾识别本质是目标检测任务。Faster R-CNN 这类两阶段检测器精度高但推理速度慢而且对小目标——比如远处的塑料碎片——召回率并不占优。YOLO 系列在速度和精度之间平衡得更好尤其是 YOLOv5/v8 这种有成熟工程实现的版本改起来方便。如果毕设要求偏学术可以在 YOLO 基础上加注意力模块或改进特征融合如果偏工程落地直接用预训练权重做迁移学习就够了。我一般会先跑通 YOLOv8n 或 YOLOv5s 作为基线再根据精度决定要不要换大模型。3.2 迁移学习与冻结策略水下数据集通常只有几千张从头训练必然过拟合。标准做法是加载 COCO 预训练权重冻结主干网络前几层只训练检测头。训练几轮后再解冻全部层做微调。以 YOLOv8 为例# 第一阶段冻结主干只训练检测头 yolo detect train dataocean_trash.yaml modelyolov8s.pt epochs50 freeze10 imgsz640 batch16 # 第二阶段解冻全部层小学习率微调 yolo detect train dataocean_trash.yaml modelruns/detect/train/weights/best.pt epochs100 lr00.001 imgsz640 batch16freeze10表示冻结前 10 层具体层数要看模型结构。第二阶段的学习率要调小通常是第一阶段的十分之一否则预训练权重会被破坏。3.3 类别不平衡的处理海洋垃圾数据里塑料瓶和塑料袋的样本量往往远多于渔网和金属罐。直接训练会导致模型对少数类几乎不响应。我一般用三种手段组合过采样少数类在数据加载器里对少数类样本重复采样。Focal Loss降低易分类样本的权重让模型关注难样本。类别权重在损失函数里给少数类更高的权重系数。YOLOv8 默认用 BCE Loss可以换成 Focal Loss。如果不想改源码最简单的办法是在数据配置文件里设置copy_paste增强把少数类目标粘贴到其他图像上变相增加样本量。4. 训练过程中最容易翻车的几个地方4.1 损失不下降mAP 卡在 0.1 以下现象训练几十轮后box loss 和 cls loss 都在波动mAP 始终上不去。原因最常见的是标注格式错误。VOC 转 YOLO 时如果img_w和img_h取错归一化坐标会全部偏移。另一个原因是类别索引从 1 开始而不是 0导致模型学不到任何有效类别。解决用脚本可视化几张标注框确认框的位置和类别都对。YOLO 格式的类别索引必须从 0 开始且要和data.yaml里的names列表顺序一致。4.2 验证集精度远高于测试集现象验证集 mAP 0.7换一批新图测试只有 0.3。原因数据泄露。同一段视频抽帧得到的图像被随机分到了训练集和验证集模型实际上见过相似画面。解决按视频来源或拍摄批次划分数据集而不是按图像随机划分。如果数据来自多个来源确保每个来源的样本在训练集和验证集里都有分布。4.3 模型把背景当目标现象检测结果里出现大量误检框住了水面反光或海底礁石。原因负样本不足。训练集里全是含垃圾的图像模型没见过“没有垃圾”的画面。解决加入纯背景图像作为负样本比例控制在总样本的 10% 到 20%。这些图像不需要标注但要在训练时让模型学会抑制背景响应。4.4 训练到一半 loss 突然变成 NaN现象前几十轮正常突然 loss 爆炸。原因学习率过大或者某批数据里出现了异常值比如标注框宽高为 0。解决检查标注文件里有没有宽高为 0 的框直接删掉。学习率加 warmup前 3 到 5 轮从极小值线性增加到设定值。如果已经出现 NaN从最近的 checkpoint 恢复调小学习率继续。4.5 推理速度慢到无法接受现象模型精度还行但单张图推理超过 500ms。原因输入尺寸太大或者用了过大的模型。解决把输入从 1280 降到 640精度损失通常不到 2 个点速度翻倍。如果还慢换 YOLOv8n 或做 INT8 量化。毕设场景下推理速度不是核心指标但答辩演示时卡顿会很尴尬。5. 怎么验证模型真的学到了东西5.1 用混淆矩阵看类别混淆YOLO 训练完会自动生成混淆矩阵。重点看两件事一是少数类有没有被完全忽略那一行全空二是哪些类别之间互相误判。塑料瓶和玻璃瓶在水下图像里颜色接近容易混。如果混淆严重考虑合并类别或者加更多区分性样本。5.2 用 Grad-CAM 看模型关注区域Grad-CAM 能把模型决策时关注的区域热力图叠加到原图上。如果热力图集中在目标物体上说明模型学对了如果集中在背景或水面上说明模型走了捷径。下面是一个简单的 Grad-CAM 调用示例from pytorch_grad_cam import GradCAM from pytorch_grad_cam.utils.image import show_cam_on_image import numpy as np # model 为加载好的模型target_layers 选最后一个卷积层 cam GradCAM(modelmodel, target_layers[model.model[-2]]) grayscale_cam cam(input_tensorinput_tensor, targetsNone) # 叠加到原图 visualization show_cam_on_image(rgb_img / 255.0, grayscale_cam[0], use_rgbTrue)参数说明target_layers要选最后一个有空间信息的卷积层选太早热力图会太粗糙。targetsNone表示取最高置信度的类别也可以指定类别索引看特定类的关注区域。5.3 跨场景测试最可靠的验证是拿模型去没见过的场景跑。比如训练集全是近岸浅水测试集用深水或浑浊水域的图像。如果精度掉得厉害说明模型泛化不够需要补充多样化数据或加强域适应增强。我自己的习惯是每次训完模型先不看 mAP而是随机抽 20 张测试图肉眼过一遍。看漏检的目标长什么样、误检的框住了什么。这个过程比看指标更能发现问题。有次我发现模型把所有带蓝色反光的区域都当成了塑料后来加了负样本才纠正过来。希望帮到你。本文还有配套的精品资源点击获取
返回列表