
简介面向具备一定Python基础的研究人员与环保监测技术人员这份资料完整呈现基于YOLOv11的水面垃圾检测系统从环境配置、数据集准备到模型训练、ONNX导出、性能评估与GUI界面搭建的全流程方案。文档以单份docx形式提供压缩包整体41KB虽仅含1个文件但涵盖项目介绍、特点说明、参考资料、未来改进方向、注意事项及分步实施代码浓缩了项目核心知识。目前已有441人学习适合希望快速复现水面漂浮物自动识别与定位、理解检测评估指标可视化方法并在此基础上扩展多类别识别与实时监测功能的读者。内容突出精准检测与多类别支持结合YOLOv11与OpenCV等工具可直接作为环保监控领域项目开发或课题研究的参考。1. 水面垃圾检测为什么选 YOLOv11从人工巡河到自动识别的完整落地路径水面垃圾检测这事听起来像个“小任务”真做起来却比想象中更依赖工程细节。人工巡河拍照再回来筛图效率低、漏检率高而且不同水域的垃圾形态差别很大——塑料瓶、食品包装、漂浮废弃物光照和水流条件一变模型表现就可能翻车。这套基于 YOLOv11 的水面垃圾检测系统把“数据准备 → 模型训练 → 指标评估 → ONNX 导出 → GUI 交互”整条链路都串好了拿到的不是一段孤立的推理脚本而是一个能直接跑起来的完整项目。适合有 Python 基础、想快速在自己数据集上复现检测流程的研究人员或环保行业技术人员。我拆完这份项目后的直接感受是它的价值不在模型本身多先进而在把 YOLOv11 训练到部署的每一步都给你铺好了路连 GUI 和评估可视化都写了属于拿来就能改的工程模板。2. 数据集与标注格式水面垃圾检测的成败其实在训练之前就定了2.1 数据集目录结构train / val / test 分离为什么不能省很多初学者拿到 YOLOv11 第一件事就是跑 train.py结果训练集和验证集混在一起评估指标虚高模型一上真实场景就现原形。这个项目在数据准备上给了明确的目录规范我先完整贴出来再解释逻辑water_surface_garbage/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/train / val / test 三个子集必须物理隔离不能有交集。训练集负责让模型学特征验证集用于每个 epoch 结束后评估泛化能力并保存最佳权重测试集是最后模拟真实场景的“闭卷考试”。有些资料会把 val 和 test 混用省事但会污染结论。我一般会在标注完成后用脚本按比例随机划分比如 7 : 2 : 1同时保证 images 和 labels 两边文件名一一对应。图片是 .jpg标注文件必须是同名的 .txt这个对应关系一旦错位YOLOv11 训练时会直接报 no labels found排查起来相当折腾。2.2 YOLO 标注格式的细节归一化坐标与类别 ID 的对应关系每个 .txt 标注文件里每一行对应一个目标物体格式是class_id x_center y_center width height注意这里所有坐标都是相对图片宽高的归一化值不是像素值。也就是说x_center 目标的中心点 x 像素坐标 ÷ 图片宽度取值在 0 到 1 之间。很多标注工具导出的格式是左上角和右下角坐标需要先转换成中心点加宽高的形式再除以图片尺寸。类别 ID 从 0 开始编号对应 yaml 配置文件里的 names 列表顺序。比如这个项目里配置的顺序是nc: 3 names: [waste, plastic_bottle, food_packaging]那么标注文件里 class_id 为 0 的是 waste为 1 的是 plastic_bottle为 2 的是 food_packaging。如果标注工具导出的类别顺序和 yaml 文件不一致模型训练时 loss 直接不收敛检测结果张冠李戴这是水面垃圾这类多类别项目里最容易犯的低级错误。提示标注完成后建议写一个小脚本统计每个类别的目标数量如果某个类别只有几十个样本后续训练时要给这个类别单独调高 loss 权重否则模型会倾向于把所有目标都预测为数量多的那个类别。3. 模型训练从环境准备到 train.py 关键参数调优3.1 环境准备与依赖安装的版本陷阱项目第一步是安装依赖原文给的命令是pip install torch torchvision torchaudio onnx onnxruntime opencv-python matplotlib pandas tkinter这里有个隐蔽的坑tkinter往往无法通过 pip 直接安装成功它是 Python 自带的 GUI 库在 Linux 上需要sudo apt-get install python3-tk在 Windows 上安装 Python 时勾选 tcl/tk 组件。如果检测 GUI 界面时发现 import tkinter 报错问题基本都出在这。克隆 YOLOv11 代码库并安装 requirementsgit clone https://github.com/YourGitHubYOLOv11.git cd YourGitHubYOLOv11 pip install -r requirements.txt我建议用 conda 创建独立虚拟环境Python 版本选 3.9 或 3.10。YOLOv11 对 PyTorch 版本有最低要求建议装 2.0 以上版本CPU 机器也能跑训练只是速度会慢不少。有条件用 GPU 的话CUDA 版本和 PyTorch 的 cu118 / cu121 后缀必须对应否则 torch.cuda.is_available() 永远返回 False训练时模型静默跑在 CPU 上速度和 GPU 完全两个量级。3.2 train.py 参数逐项拆解img / batch / epochs 的含义与选择逻辑训练命令是 YOLOv11 全系列统一入口python train.py --img 640 --batch 16 --epochs 100 --data water_surface_garbage.yaml --weights yolov11.pt参数含义拆解--img 640输入图片统一缩放到 640×640。这个值影响检测精度和小目标召回率水面垃圾里的塑料瓶、食品包装往往是小目标建议先按 640 跑通流程后续图省事可以换 832 看小目标召回率是否提升。--batch 16单次迭代送入模型的图片数量。显存不够时优先降低这个值8GB 显存跑 640 分辨率建议 batch 取 8。batch 太小会导致梯度震荡loss 曲线毛刺很多。--epochs 100训练轮数。水面垃圾数据量通常不大100 轮足够收敛继续加大轮数容易过拟合模型在训练集上 loss 很低验证集 mAP 反而下降。--data water_surface_garbage.yaml指向数据集配置文件。--weights yolov11.pt预训练权重路径。用 COCO 预训练权重做迁移学习初始化比从零训练收敛速度快得多。从零训练和迁移学习的主要差别在收敛速度。COCO 预训练模型已经学好了通用的边缘、纹理、形状特征水面垃圾的塑料瓶和 COCO 里的瓶子类有相似性所以微调后 50 轮左右 mAP 就能上到可观水平。如果数据集很小——每个类别只有几百张——可以冻结 backbone 层只训练检测头防止过拟合。3.3 训练过程中的日志监控results.csv 是排查过拟合的第一手依据训练启动后runs/train/exp/ 目录会实时生成 results.csv里面每个 epoch 记录了 train_loss、val_loss、precision、recall、mAP50、mAP50-95 等指标。我建议每训练 10 个 epoch 就看一眼文件末尾几行tail -5 runs/train/exp/results.csv重点关注两组关系train_loss 和 val_loss 的走向precision 和 recall 的相对变化。val_loss 在第 60 轮开始回升但 train_loss 还在降就是典型的过拟合信号可以提前停掉训练用第 60 轮的权重重新评估。训练正常时 final epoch 训练损失大概降到一个较低水平精度和召回率维持在一定合理区间内具体数值取决于数据集规模和标注质量不做硬性参考。另外一个容易忽略的细节每次训练前把 runs/train 目录清空或者用--name参数指定新的实验名称否则新实验的结果会写到 exp2、exp3找权重时容易拿错文件。4. 模型评估与指标可视化别只盯 mAP要看 precision / recall 的曲线走向4.1 val.py 评估输出字段的完整解读训练完成后执行python val.py --weights runs/train/exp/weights/best.pt --data water_surface_garbage.yaml --img 640评估结果会打印出各类别的 precision、recall、mAP50、mAP50-95。水面垃圾检测场景里mAP50 能到 80% 以上基本可用mAP50-95 是更严格的标准计算了不同 IoU 阈值下的平均精度这个值通常比 mAP50 低 15 到 25 个百分点不必因为数字难看就怀疑模型错了这是正常现象。4.2 用 matplotlib 绘制评估曲线一次把四张图都画全的脚本项目给出了用 results.csv 绘制训练曲线的代码我整理成可以直接替换路径的版本import matplotlib.pyplot as plt import pandas as pd data pd.read_csv(runs/train/exp/results.csv) plt.figure(figsize(12, 8)) plt.subplot(2, 2, 1) plt.plot(data[epoch], data[train/box_loss], labelBox Loss, colorblue) plt.plot(data[epoch], data[val/box_loss], labelVal Box Loss, colorcyan) plt.title(Loss over Epochs) plt.xlabel(Epoch) plt.ylabel(Loss) plt.grid(True) plt.legend() plt.subplot(2, 2, 2) plt.plot(data[epoch], data[metrics/precision], labelPrecision, colorgreen) plt.title(Precision over Epochs) plt.xlabel(Epoch) plt.ylabel(Precision) plt.grid(True) plt.legend() plt.subplot(2, 2, 3) plt.plot(data[epoch], data[metrics/recall], labelRecall, colorred) plt.title(Recall over Epochs) plt.xlabel(Epoch) plt.ylabel(Recall) plt.grid(True) plt.legend() plt.subplot(2, 2, 4) plt.plot(data[epoch], data[metrics/mAP50], labelmAP50, colororange) plt.plot(data[epoch], data[metrics/mAP50-95], labelmAP50-95, colorpurple) plt.title(mAP over Epochs) plt.xlabel(Epoch) plt.ylabel(mAP) plt.grid(True) plt.legend() plt.tight_layout() plt.show()这段代码有四个子图分别对应 box loss、precision、recall、mAP 的逐 epoch 曲线。box loss 曲线是判断训练是否收敛的最直观信号如果它一直走平甚至回升说明学习率设置不当或数据有问题。precision 和 recall 永远存在权衡关系precision 高说明检测框基本都对了漏检可能比较多recall 高说明目标基本都找到了误检可能比较多。实际部署时看具体场景需要比如环保巡检宁可多报几个假阳性也不能漏掉真实污染源那就倾向提高 recall。4.3 评估阶段最容易误导人的三个指标认知第一mAP50 高不代表模型在真实场景里好用。它是单张图片上的静态指标真实水面视频里会有运动模糊、反光、遮挡这些在评估集里未必覆盖。第二results.csv 里的metrics/precision是所有类别的宏观平均单个类别表现可能差异很大——塑料瓶可能在各个指标上都高食品包装由于标注样本少recall 可能低到没法看。第三评估时的 img size 必须和训练时一致否则同一模型在 640 和 1280 下输出指标差异巨大不是模型变好了是输入分辨率改变了目标的有效尺寸。5. 训练与部署避坑这几个问题我赌你会遇到5.1 标注文件里出现越界坐标现象训练到一半报错提示 box coordinate 超出图像范围或者 loss 出现 NaN。原因标注工具导出的坐标没有严格限制在 0 到 1 之间或者图片 resize 后标注没有同步归一化更新。解决写一个 Python 脚本遍历所有 labels 文件把小于 0 的坐标强制截断为 0大于 1 的截断为 1。同时检查 width 和 height 是否大于 0小于等于 0 的标注行直接删除。这类脏数据在训练前清理干净能省下好几个小时的排查时间。5.2 GPU 显存不足导致训练中断现象train.py 启动后几秒钟报 CUDA out of memory或者进程直接被杀。原因batch size 设置过大输入图片分辨率 640加上 YOLOv11 本身的中间特征图显存占用比想象中大很多。解决先把--batch降到 4 跑通流程再逐步往上加。如果显存始终不够把--img降到 480 或 512小目标检测精度会有损失但至少让你先拿到完整流程。另外 train.py 里可以开启--cache参数把图片缓存到内存减少数据加载对显存的临时占用。5.3 GUI 界面 import tkinter 失败现象运行 GUI 脚本报 ModuleNotFoundError: No module named tkinter。原因pip 安装的 Python 在 Linux 上默认不带 tcl/tk 支持Ubuntu 上还需要额外安装系统包。解决Ubuntu/Debian 执行sudo apt-get install python3-tkWindows 用户重新运行 Python 安装程序勾选 tcl/tk 组件。装完后在 Python 里执行import tkinter验证。5.4 torch.hub.load 加载本地模型时路径错误现象GUI 脚本执行时提示模型文件找不到或者报错说无法从 GitHub 下载。原因原项目示例代码用了torch.hub.load它的第一个参数如果是 GitHub 仓库名会默认去线上拉取代码网络环境受限时就会卡住。解决改成从本地路径加载model torch.hub.load(你的YOLOv11代码库路径, custom, pathruns/train/exp/weights/best.pt, sourcelocal)注意sourcelocal必须显式写出否则还是会去找 GitHub。这是一个很值得记住的细节——很多从 GitHub 仓库部署 YOLOv11 到内网或本地服务器的情况都是栽在 torch.hub 的远程依赖上。5.5 评估指标和实际检测效果严重不符现象val.py 显示 mAP50 很高但 GUI 里上传真实照片后漏检一大堆。原因验证集和训练集来自同一分布可能连拍摄设备都相同模型相当于做了“开卷考试”真实场景里光照、角度、水面反光都变了模型没见过类似特征。解决训练完成后额外收集一批完全没有参与训练和验证的真实照片做独立测试集只看这批数据上的检测效果。如果漏检严重说明训练数据多样性不足需要补充不同光线、水质条件的数据。这是所有视觉检测项目的共性水面垃圾这种目标形态多变的任务尤其敏感。6. 部署到 ONNX 并脱离训练环境推理模型导出与验证的完整闭环训练和评估只是第一步真正让这套水面垃圾检测系统发挥价值的是导出 ONNX 并完成跨平台部署。ONNX 格式的好处在于不依赖 PyTorch 运行时可以用 onnxruntime 在任何环境的 CPU 上推理也能转到 TensorRT 后端优化往 Jetson Nano 这类边缘设备上迁移时这是必经之路。导出命令python export.py --weights runs/train/exp/weights/best.pt --img 640 --batch-size 1 --include onnx导出完成后runs/train/exp/weights/ 目录下会生成 best.onnx。用 onnxruntime 加载并完成一次推理验证import cv2 import onnxruntime as ort import numpy as np session ort.InferenceSession(runs/train/exp/weights/best.onnx) input_name session.get_inputs()[0].name image cv2.imread(test_image.jpg) img_resized cv2.resize(image, (640, 640)) img_blob img_resized[:, :, ::-1].transpose(2, 0, 1) / 255.0 img_blob np.expand_dims(img_blob, axis0).astype(np.float32) outputs session.run(None, {input_name: img_blob})这段代码要注意三点。第一输入张量的通道顺序是 CHW所以需要 transpose(2, 0, 1)第二输入需要做归一化到 0 到 1第三推理输出的原始张量格式和 YOLOv11 的推理脚本输出格式不完全一致直接拿 outputs 里的数组画框会得到奇怪的坐标因为需要做解码和 NMS 后处理。ONNX 导出的模型只是推理引擎完整部署还需要配套后处理逻辑。用 ONNX 模型做一次推理验证后可以拿同一张图分别用 PyTorch 权重和 ONNX 权重跑检测对比两者的检测框坐标差异。两端坐标偏差如果在 1% 以内说明导出没有问题偏差很大就需要确认预处理是否一致——很多部署翻车都发生在图像缩放和归一化参数与训练时不一致。评估模型是否适合部署到边缘设备核心指标是推理耗时和模型体积。ONNX 格式相比 PyTorch 权重体积有压缩但更关键的是在 CPU 上单张图片推理耗时。桌面 CPU 一般在几百毫秒量级Jetson Nano 上用 TensorRT 优化后能跑实时或准实时。导出完成后别忘了把输入尺寸是否支持动态 shape 这件事也确认掉——固定尺寸导出在边缘设备上通常更稳定。这套项目从数据整理到 GUI 部署都齐了但真正把它用起来的关键还是验证闭环。从那以后我每次跑完 YOLOv11都会强制走一遍导出 ONNX、脱离训练环境独立推理的流程确认部署端和训练端行为一致才敢把模型放出去。环境监测这种场景里漏检一个漂浮物可能意味着一次污染事件没被发现这个验证习惯值得养成。希望帮到你。本文还有配套的精品资源点击获取