简介本资源是一套面向深度学习初学者与课程设计/毕业设计学生的YOLOv8漂浮物检测实战项目聚焦水面环境下的目标识别问题适用于人工智能、计算机视觉方向的期末大作业或工程实践。压缩包共149个文件含68个Python脚本模型训练、推理与评估核心逻辑、28个YAML配置文件数据集定义、模型超参与训练调度、28个Markdown文档含README、CONTRIBUTING、CITATION等完整项目说明以及Dockerfile系列、C推理接口、.gitignore等工程化支持文件整体仅279KB轻量但结构完备。项目已提供从数据标注规范、YOLOv8微调策略、mAP等指标评估到CPU/Docker多平台部署的全流程实现代码注释清晰适配Jupyter实验与终端部署双场景。目前已有28人学习下载是理解目标检测落地逻辑、掌握工业级AI项目组织方式的优质入门范例。 打捞出水面漂浮物这事儿乍一听像是环保工程但放到技术侧就是一个非常标准的视觉目标检测问题相机架在河道巡检船或桥上实时回传画面算法要把水里的塑料瓶、泡沫板、枯枝、垃圾袋从复杂的水面背景里框出来。我最初接这个方向的时候第一反应就是直接拿yolov8来跑因为它的工程化成熟度、预训练模型生态和后续部署链路都太顺了。这篇就把我做基于yolov8的漂浮物检测整个流程翻出来讲透——从数据怎么搞、标注有哪些坑、训练参数怎么调到模型怎么落到嵌入式设备上一次性说完。不管你是学生做课题还是刚入职的算法工程师要快速出demo或者只是在做河道监控相关的业务探索这篇文章都是按“能直接复现”的标准来写的。涉及的环境配置、数据集处理、训练技巧和部署方案都是我实际踩过坑之后沉淀下来的方案不是网上那种贴个官方readme就完事儿的水文。1. 为什么选yolov8来识别水面垃圾选型不是拍脑袋1.1 漂浮物检测任务的难点到底在哪很多人觉得水面垃圾检测不就是个普通的目标检测吗拿个通用模型一训练就完事。实际跑起来才发现漂浮物检测在视觉层面有几个非常头疼的特点。首先是目标尺度问题。河道里的矿泉水瓶、塑料袋在1080p画面里往往只有几十个像素大小属于典型的小目标。而yolov8的下采样倍数较高小目标经过多层卷积后特征图分辨率已经很小容易丢信息。这是后面训练时要重点调优的点。其次是背景干扰极其严重。水面不是纯色有反光、有倒影、有波纹阳光强的时候整个画面亮得像一面镜子模型很容易把波光粼粼的水面误判成物体边缘。再加上漂浮物常常是半沉半浮的状态比如一个塑料瓶只有瓶口露出水面外形残缺不全这对模型的鲁棒性要求很高。还有一个常被忽略的点是类别模糊。一张水面图片里枯树叶和垃圾袋在颜色和纹理上可能非常接近塑料瓶和白色泡沫在远处看几乎一样。如果标注时类别划分不清晰模型学到的特征就会互相干扰导致训练半天mAP卡在60%上不去。1.2 yolov8相比其他方案的不可替代性我为什么最终锁定yolov8而不是用yolov5、RT-DETR或者传统的图像处理方案核心原因有三个。第一yolov8的anchor-free机制让检测头更简洁对不同尺度目标的适应能力更好。传统anchor-based方法需要针对目标尺寸聚类预设anchor box而漂浮物尺寸变化极大——从小小的瓶盖到巨大的水葫芦聚团都有anchor-free可以直接回归目标框省掉了调anchor的麻烦。第二ultralytics的工程化做得太完善了。数据加载、数据增强、训练日志、模型导出全都封装好了训练一个模型只需要写几行配置这对快速验证想法极其重要。而且它内置了丰富的预设模型尺寸n/s/m/l/x可以根据显存大小灵活选。第三部署链路完整。yolov8可以直接导出ONNX、TensorRT、RKNN等格式无论是在服务器上用GPU推理还是部署到RK3588嵌入式主板甚至导出到手机端都有成熟方案。这一点对实际落地非常关键因为漂浮物检测最终一定是装在巡检设备上的不可能一直在PC上跑demo。1.3 整体技术路线图在动手之前我把整个项目拆成了六个阶段数据采集、数据清洗与标注、环境配置、模型训练与评估、模型调优、部署验证。每个阶段都有明确的输入输出和验收标准。数据阶段的目标是拿到足够丰富的水面场景图片最好是涵盖不同光照晴天、阴天、逆光、不同水质清澈、浑浊、藻类爆发、不同天气雨天、雾天的样本。环境配置阶段要解决CUDA、PyTorch、ultralytics的版本匹配问题。训练阶段重点关注损失函数曲线和验证集指标。部署阶段则要根据目标设备的算力做模型压缩和格式转换。这个路线听起来简单但每一步都有很多细节下面逐个展开。2. 数据集才是决定结果上限的关键2.1 公开数据集与自采数据怎么搭配做这个项目的时候我第一步想的是找公开数据集。确实有一些开源的漂浮物检测数据集存在比如某些学术机构发布的水面垃圾数据集但是用起来总有几个问题场景太单一、类别定义和你的需求对不上、标注质量参差不齐。更重要的是实际部署的水域和你训练集里的水域往往长得很不一样。所以我的建议是公开数据集用来做预训练或者跑通流程但正式训练一定要加入自己采集的数据。特别是有条件的话用实际部署场景的相机去拍因为不同相机的色彩风格、安装高度、俯仰角度都会对检测效果产生很大影响。我实际的做法是搞了一块移动硬盘到目标水域周边蹲了好几天用手机和一台运动相机轮流拍。拍的时间覆盖早晨、中午、傍晚三个时段天气好的坏的都拍了一轮。拍完大概积累了两千多张原始图片去掉大量重复度过高的帧之后留下了约一千五百张可用图。2.2 标注实操工具选择与标注规范有了原始图片就该标注了。这里要特别强调一下标注这个环节很大程度上决定了模型的上限而训练只是在逼近这个上限。标注不规范后面再怎么调参都是白费。工具方面我推荐用LabelImg或者X-AnyLabeling。LabelImg是老牌工具操作简单、支持YOLO格式直接导出适合手工快速标注。X-AnyLabeling则内置了SAM等辅助标注能力可以先用模型自动预标注再人工修正效率能提高不少。我自己是先用X-AnyLabeling的预标注功能粗标一遍再逐个检查修正。标注规范是重中之重。结合漂浮物检测的实际情况我定了这么几条规矩类别只设四个塑料类瓶、袋、泡沫、木质类树枝、枯叶团、生活垃圾类鞋、织物、其他废弃物、水葫芦等植物类。类别尽量不要超过五个类别越多分类难度越大。只要物体露出水面超过1/3就标只有一点点露头的模糊目标不标避免引入过多噪声。严重遮挡的目标不标。比如塑料瓶被枯叶盖住一大半这种样本强行标了会让模型学到错误特征。小目标只要清晰可见就标不要因为小就放弃这是小目标检测效果能提升的关键操作。每张图的目标数量不做强制控制但要注意整个数据集里各尺度目标的比例避免全是超大目标或全是小目标。标注完所有图片之后一定要花时间做一次质量复查。我第二次检查时发现了个别框偏移了一个身位的情况还有两三个类别标错的这些如果混进训练集都会变成模型学习的干扰信号。2.3 数据增强与样本均衡策略漂浮物检测的训练集规模通常不大两三千张图就算不错了所以数据增强不能只是随便开一下官方默认。我的做法是针对水面场景做了几个特别增强。一是在线增强中把HSV色域增强的饱和度扰动调高模拟不同水质下的颜色漂移。水面反光是这个任务最大的干扰来源而颜色抖动可以让模型不过度依赖颜色特征。二是增加随机旋转和透视变换模拟不同安装角度下看到的画面。三是翻转变换水平翻转和垂直翻转都开这个简单但非常有效。样本均衡方面我发现四个类别里塑料类的样本量占了快一半木质类和水葫芦类偏少。于是我对少见类别的图片做了过采样复制同时对塑料类图片做了降采样通过datasets目录比例和augment参数配合调整。另一个非常重要的小技巧是把小目标比较多的图多复制几份喂给模型因为小目标在loss里天然占劣势这比单纯调cls_loss权重更直接。3. 环境配置与训练实操从GTX 1660 Ti到显存抠门学3.1 硬件起步入门显卡怎么把yolov8跑起来我的开发机显卡是一块GTX 1660 Ti6G显存在动不动就A100的今天听起来很寒酸但实际把yolov8n和yolov8s跑起来是完全没问题的。关键是版本和参数要匹配好。先说CUDA和PyTorch的版本。我踩过的坑是早期装了PyTorch 2.0然后发现和本机CUDA驱动版本不匹配训练时直接在第一个batch就报错。后来我直接用Anaconda建了独立环境CUDA Toolkit版本用11.8PyTorch用2.1.0配套的cu118版本ultralytics版本用8.1.0左右一次装好以后就没出过兼容性问题。conda create -n flot python3.9 conda activate flot pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics这里插一句很多新手会问PyTorch 2.1能不能支持yolov8这其实是个伪问题yolov8本质上就是一个基于PyTorch的模型实现它对PyTorch版本并不挑剔只要CUDA和cuDNN配套即可。真正影响兼容性的反而是Ultralytics版本和Python版本的搭配。3.2 组织YOLO格式数据集的标准姿势数据准备好之后目录结构要严格按YOLO格式组织不然yolo train命令直接罢工。我因为目录结构问题卡过两小时所以单独列出来强调一下。dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamltrain和val的比例我按8:2切分划分的时候注意同一条河段、同一天拍的连续帧别全部落在训练集或验证集里否则会出现很强的数据泄漏验证成绩虚高。一个常用的做法是按时间段切分或者对图片做哈希去重后随机划分。labels目录下每个txt文件名要和图片文件名一一对应。txt里的内容格式是class_id x_center y_center width height注意这里存储的是归一化后的坐标也就是每个数值都在0到1之间。第一次用LabelImg导出时我忘了设置YOLO格式默认导出了Pascal VOC的XML文件转格式转了半天。所以标注前先把保存格式选好后面能省大量时间。data.yaml文件内容path: /home/user/floating_waste_dataset train: images/train val: images/val nc: 4 names: [plastic, wood, garbage, plant]3.3 训练参数设置的实战经验训练命令我用的是一行yolo train但参数都做了针对性设置。这里把我最终使用的一组参数列出来并解释一下为什么这么设。yolo train datafloating.yaml modelyolov8s.pt epochs200 imgsz640 batch8 workers8 patience30 optimizerAdamW lr00.001 lrf0.01model我选的是yolov8s而非yolov8n。s模型比n模型mAP大概能高四到五个点而推理速度在1660 Ti上还是能跑到60FPS以上完全够用。m模型在6G显存下batch得降到2训练不稳定性价比不高。imgsz漂浮物有很多小目标我试过imgsz960小目标检测确实有提升但显存占用直线上升训练时长翻倍。640是一个速度与精度的平衡点先跑通后面再用更大的输入尺寸做精度回归测试。batch6G显存跑yolov8sbatch最多也就8到10再大就OOM了。我们可以用batch-1让ultralytics自动检测能放下的最大batch但我更推荐手动设一个固定值保证训练过程可复现。优化器用AdamW效果比默认SGD更稳特别是数据量不大时收敛更快。lr0设0.001lrf设0.01配合余弦退火曲线后期可以更细腻地收敛。对了还有一个隐藏参数很多人不知道close_mosaic10。ultralytics默认在最后10个epoch会关闭Mosaic增强这是为了让模型在接近真实的单图分布上做最后的拟合。如果训练曲线到了后期还在震荡可以先检查这个参数有没有生效。4. 训练过程监控与模型调优4.1 损失函数曲线怎么看训练启动之后最常干的事就是盯着终端或TensorBoard里的损失曲线发呆。yolov8的loss输出有三个方面box_loss、cls_loss和dfl_loss。看懂这三条曲线的正常形态能帮你快速判断训练状态。我这次训练过程中box_loss从初始的1.8左右逐步下降到0.9附近并趋于平缓cls_loss从2.3缓慢降到0.8dfl_loss则从2.5左右降到1.2。三条曲线在epoch 120到150之间基本没有剧烈波动说明模型收敛相对健康。不过需要注意如果你的box_loss一直降不动常见原因是数据集里有大量标注框不准确的样本或者小目标太多导致回归难度大。这时候不要急着堆训练时间应该回头检查标注质量。而cls_loss如果快速降到接近0同时验证集mAP却没有同步提升大概率是过拟合的先兆特别是训练集比较小且类别不平衡时。4.2 mAP评估与漂浮物场景的特殊指标训练结束后模型会输出一个验证结果一般看两组指标mAP50和mAP50-95。mAP50是IoU阈值为0.5时的平均精度漂浮物检测场景主要看这个mAP50-95是多个IoU阈值的平均对框的精准度更敏感适合用来做横向对比。我在这个项目上最终验证集mAP50到了82%左右mAP50-95是54%。看起来还行但实际部署到现场视频流里还是会出现两种典型误检一种是把水上浮萍的纹理识别成木质垃圾另一种是强逆光下把水面高光区域当成塑料瓶。这类错误在静态指标里不易反映出来所以必须做一段视频流实跑统计每个类别的precision和recall特别是recall——漏检在河道巡检里比误检更致命漏掉一个垃圾会被巡检人员认定系统失效。4.3 针对小目标的针对性改进注意力机制与网络结构调整如果你想让mAP再上一个台阶常规训练参数已经到瓶颈了自然就会想到改进网络结构。热搜词里的“yolov8 eca”“yolov8 adown”“将EMA注意力机制融入yolov8的C2F中”这些方向就是大家在干的事。我自己实验过在C2F模块里嵌入EMA注意力机制。EMAEfficient Multi-Scale Attention把通道分组后分别做空间注意力提取再融合参数增加不多但对小目标的特征响应有明显增强。加入EMA之后我在验证集上小目标类别的AP从原来的68%提到了74%整体mAP50涨了三个点左右。代价是每轮训练时长增加了大概15%推理速度从60FPS降到52FPS但这对河道巡检的实时性需求来说依然是够的。另一个方向是把检测头换成ADown下采样模块减少下采样过程中的信息丢失。这个改动对稀疏分布的小目标比如只漂着一个塑料瓶的画面比较友好但需要手动改ultralytics的模型源码适合有一定PyTorch基础、愿意折腾的人。# 在ultralytics/nn/modules/block.py中新增 class EMA(nn.Module): def __init__(self, channels, factor8): super().__init__() self.groups factor self.softmax nn.Softmax(dim-1) # ... 具体实现省略核心是分组注意力加权嵌入位置建议放在C2F的Bottleneck之前而不是直接替换整个C2F。这样改动小、回退方便实验对比也更可控。另外每次结构改动之后都要重新跑一个完整的训练流程至少先跑200个epoch收敛了再比数据半路看loss曲线下结论是不靠谱的。5. 从训练到部署把模型搬到嵌入式设备上的完整链路5.1 模型导出从PyTorch到ONNX再到目标格式训练完的模型不是拿来看的是要部署到实际设备上的。第一步就是导出。ultralytics官方提供了一键导出功能但直接导出往往不是最优解需要做一个精度对比后再决定导出格式。yolo export modelbest.pt formatonnx opset12 imgsz640导出ONNX之后我建议先用onnxruntime在PC上跑一遍同一批测试图对比PyTorch原模型和ONNX模型的输出框差异。正常情况下两者的mAP误差应该在1%以内。如果差异过大检查一下opset版本和imgsz是否和训练时一致。在漂浮物检测项目里部署目标如果确定是RK3588这类嵌入式平台导出链路建议是PyTorch模型 → ONNX → RKNN。RKNN-Toolkit2会把ONNX模型转换成RK3588的NPU能直接跑的格式。转换时要注意量化方式。我实测下来INT8量化后模型体积从原来的45MB压缩到10MB左右但mAP50会掉2%到3%。对于垃圾检测这种任务这个精度损失可以接受毕竟换来了实打实的性能提升和功耗下降。5.2 部署到RK3588和手机端的注意事项在RK3588上部署时有几个坑值得提前说出来。首先是RKNN的版本匹配问题不同版本的RKNN-Toolkit2和板子上的固件驱动要严格对应不然模型转换成功了也加载不了。建议直接用官方提供的Docker镜像环境做转换别在本地瞎折腾依赖。其次是预处理对齐。PyTorch训练时的预处理是resize到640然后做归一化除以255但RKNN模型默认的输入格式可能是NHWC布局且需要特定均值方差。如果预处理不一致板子上跑出来的推理结果会非常诡异——会出现大量置信度极低的框或者干脆不检。这个问题的排查方式是把同一张图分别用PC和板子推理打印中间层output做对比就能定位到是哪一层对不上。手机端部署的话ultralytics其实也支持导出TFLite或NCNN格式框架是开放的。不过手机端的算力比RK3588更有限建议用yolov8n这种轻量模型或者用剪枝蒸馏后的版本。我自己试过把yolov8n导出成NCNN在骁龙8系手机上跑720p输入能达到30FPS左右的实时率功耗也不高。如果你想在手机端做快速demo这条路是可行的。5.3 实际部署效果与性能记录最后说下实际部署情况。我把训练好的yolov8s-EMA版本导出为RKNN格式在RK3588上用NPU加速跑640x640输入实测推理延迟约18到22毫秒加上前后处理整链路能稳定跑到30FPS以上。这个速度在河道巡检船上是够用的因为船速慢30FPS已经能保证每帧都有重叠覆盖率。如果在更算力受限的设备上跑比如一些低端边缘盒子建议直接用yolov8n配合INT8量化。掉三四个点mAP换两倍以上的帧率在漂浮物巡检这个场景里是划算的——毕竟垃圾要漏检的窗口期很短能更快处理更多帧才是核心需求。回看整个项目我对yolov8在漂浮物检测上的结论是这一套方案完全可行但它的下限由数据决定上限由你对网络结构和部署链路的理解决定。不要指望装上yolov8随便丢点数据就能达到部署标准从数据集清洗、标注规范、训练参数调整到部署格式选型每一步都值得认真打磨。尤其是数据标注这一关这活儿枯燥但回报率极高相当于给模型编一本高质量的水面垃圾“词典”。后续想往深了做可以试试半监督学习用无标注视频自动产出伪标签或者叠一个跟踪器做视频流的时序过滤。这些我都还在继续尝试后面有结果了再分享。本文还有配套的精品资源点击获取