简介:本资源是一套基于YOLOv8的轻量化垃圾分类目标检测实战方案,面向深度学习初学者、计算机视觉课程设计者及本科毕业设计学生,解决真实场景下垃圾图像多类别识别与定位难题。压缩包共4个文件(2个Python脚本、1个YOLOv8格式数据集ZIP、1份说明文档),总大小12.29MB;其中train_yolov8m.py支持端到端模型训练,predict_image.py提供开箱即用的单图检测推理功能,配套数据集已按YOLOv8标准格式组织并完成类别标注,README.md详述环境配置、训练与预测流程。目前已有53人学习下载,资源结构简洁聚焦,无需额外数据预处理即可运行训练与推理,附带参数调优建议与嵌入式部署适配说明,特别适合快速复现、二次开发或课程项目交付。

1. 项目概述:当YOLOv8遇上垃圾分类

最近在整理社区项目时,翻出了一个挺有意思的实战案例——“基于YOLOv8的垃圾分类目标检测”。这项目听起来像是把当下最火的实时目标检测框架,用在了我们每天都会接触的垃圾分类场景里。我最初接触这个想法,是因为看到不少社区、校园或者智能回收箱项目,都想引入视觉识别来替代或辅助人工分拣,但要么卡在识别速度上,要么困在模型精度和部署成本里。YOLOv8的出现,恰好给这类应用场景提供了一个非常平衡的解决方案:它够快,能在普通算力设备上实时运行;它够准,对于瓶罐、纸箱、电池这类特征相对明显的垃圾物品,识别效果相当可靠。

这个项目的核心目标很明确:训练一个能准确识别并定位图像或视频流中常见垃圾类别的YOLOv8模型。它要解决的痛点,远不止是“识别出这是个瓶子”那么简单。在实际部署中,模型需要区分“透明塑料瓶”和“有色塑料瓶”(因为回收处理方式可能不同),需要把“碎纸屑”和“完整纸箱”分开,甚至要能判断“干电池”和“纽扣电池”。这背后是对模型特征提取能力和鲁棒性的综合考验。对于开发者、环保科技公司、或是智慧城市项目的工程师来说,掌握这套从数据准备、模型训练到优化部署的全流程,意味着你能将一个前沿的AI点子,快速落地成一个可演示、可测试甚至可商用的原型系统。

我之所以花时间把这个项目重新梳理并分享出来,是因为整个过程踩了不少坑,也积累了一些在官方文档里不会细说的经验。比如,垃圾数据集标注有哪些特别要注意的细节?用GTX 1660 Ti这种“平民显卡”训练YOLOv8,怎么调参才能最大化利用显存?训练过程中损失曲线震荡怎么办?模型训练好后,如何转换成各种格式部署到不同的硬件平台?这些实操层面的问题,才是项目成败的关键。接下来,我就把自己趟过的路,拆解成一步步可复现的细节,分享给大家。

2. 项目核心思路与方案选型

2.1 为什么选择YOLOv8?

在目标检测领域,框架选择很多,从老牌的Faster R-CNN、SSD,到YOLO系列的各代版本。最终锁定YOLOv8,是经过一番权衡的。对于垃圾分类这个场景,我们需要在速度、精度、易用性和社区生态之间找到最佳平衡点。

首先, 实时性要求是硬指标 。无论是部署在回收站的摄像头进行流水线分拣,还是在移动设备上开发拍照分类App,都需要模型能快速响应。YOLOv8延续了该系列“单次前向传播即可预测”的优良传统,其速度在同等精度模型中是第一梯队的。经过实测,在GTX 1660 Ti上,YOLOv8s模型推理一张640x640的图片仅需约6-8毫秒,完全满足实时视频流处理的需求。

其次, 精度与泛化能力 。垃圾分类的物体虽然类别不算极多(通常10-30类),但类内差异大(比如“塑料瓶”有各种颜色、形状、挤压状态),且存在大量遮挡、重叠和复杂背景。YOLOv8采用了新的骨干网络和特征融合策略,在小目标检测和复杂场景下的鲁棒性上有不错的表现。它的Anchor-Free设计也简化了训练流程,不再需要繁琐的Anchor Box聚类,对新手更友好。

再者, 完善的工具链与生态 。Ultralytics官方维护的YOLOv8,提供了从安装、训练、验证到导出一条龙的Python接口和命令行工具。其模型格式(.pt)可以轻松转换为ONNX、TensorRT、OpenVINO、CoreML等格式,这对于后续部署到嵌入式设备(如RK3588开发板)、移动端或边缘计算盒子至关重要。社区活跃,遇到问题容易找到解决方案。

最后, 从YOLOv5的平滑过渡 。如果你之前接触过YOLOv5,那么上手YOLOv8几乎零成本,两者的数据格式(YOLO格式)、配置文件结构非常相似。但YOLOv8在模型结构、训练策略上做了优化,通常能获得更好的性能。

注意 :选择模型尺寸时需权衡。YOLOv8提供了n/s/m/l/x五个尺度。对于垃圾分类,如果部署资源受限(如Jetson Nano), YOLOv8n 或 YOLOv8s 是首选;如果追求更高精度且算力充足(如服务器或高性能边缘设备),可以考虑 YOLOv8m 。不建议一开始就使用 l 或 x 版本,它们对数据量和算力要求高,容易过拟合。

2.2 垃圾分类数据集的特有挑战与应对

和通用目标检测数据集(如COCO)相比,构建一个高质量的垃圾分类数据集,有几个独特的挑战,必须在项目开始时就规划好应对策略。

挑战一:类间相似与类内差异 。

  • 问题 :“易拉罐”(金属)和“金属罐头”(金属)外观相似;“报纸”(纸类)和“纸箱”(纸类)材质相同但形态迥异;“厨余垃圾”可能呈现各种形态,没有固定形状。
  • 应对 :标注规则必须极其严格且具体。需要在标注规范文档中明确定义:1)以物品的主要构成材料为第一分类依据;2)对于复合物品(如带塑料盖的玻璃瓶),标注主要部分或按可拆分部分分别标注;3)为“厨余垃圾”这类无固定形态的类别,收集尽可能多样的样本(完整食物、残渣、汤汁等)。

挑战二:遮挡、堆积与变形 。

  • 问题 :垃圾桶内的垃圾通常是相互堆叠、遮挡的。一个被压扁的纸盒,其边界框很难界定。
  • 应对 :1)数据采集时,应有意识地拍摄单个、少量堆积和大量堆积的不同场景。2)标注时,即使物体被部分遮挡,只要可见部分超过一定比例(如30%),且能明确判断类别,就应标注其完整包围盒。对于严重变形物体,标注其当前状态下的最小外接矩形。

挑战三:背景复杂与光照变化 。

  • 问题 :垃圾可能出现在室内地板、室外草坪、水泥地、回收桶内等复杂背景中,光照条件也从昏暗到强光不等。
  • 应对 :数据增强是关键。在YOLOv8的训练配置中,必须充分利用其内置的增强功能,如 mosaic (马赛克增强)、 mixup 、 hsv_h/s/v 调整(模拟光照变化)、 translate / scale (模拟位置大小变化)。这能极大地提升模型在复杂真实环境中的泛化能力。

挑战四:数据标注的长期维护 。

  • 问题 :垃圾分类标准可能因地而异,且不断有新型包装材料出现。
  • 应对 :采用可扩展的标注体系。例如,使用层次化标签:“可回收物-塑料- PET瓶”。在数据集的 data.yaml 文件中,清晰地记录类别索引与名称的对应关系,并预留空位以备将来增加新类别。

基于这些考量,我们的数据准备工作就不能是简单地收集图片然后打标,而需要一套更系统的流程。

3. 数据准备与标注实战详解

3.1 数据采集与预处理规范

高质量的数据是模型成功的基石。对于垃圾分类项目,我建议按以下步骤进行:

  1. 定义类别清单 :首先,根据你的目标应用场景(如某城市的垃圾分类标准),确定一个具体的类别列表。例如: [‘plastic_bottle’, ‘can’, ‘paper_box’, ‘newspaper’, ‘glass_bottle’, ‘battery’, ‘food_waste’, ‘residual_waste’] 。类别名最好使用英文,避免后续路径问题。类别数建议在8-20个之间,太少应用价值有限,太多则对数据量和模型容量要求高。

  2. 多元化采集 :

    • 来源 :可以自己拍摄(手机、相机),也可以从公开数据集中筛选合并(如华为云垃圾分类数据集、TACO数据集等),注意版权。
    • 场景 :涵盖室内(厨房、办公室)、室外(小区垃圾桶、街道)、回收站等。
    • 角度与距离 :包含平视、俯拍、近距离特写、远距离全景。
    • 状态 :物体单独放置、少量堆积、大量混杂、被遮挡、被挤压变形。
    • 光照 :晴天、阴天、夜间(需补光)、室内灯光。
    • 设备 :尽量使用不同型号的手机、摄像头拍摄,增加传感器多样性。
  3. 图像预处理 :

    • 统一格式 :将所有图片转换为 .jpg 或 .png 格式。
    • 检查损坏 :运行一个简单的脚本,检查是否有损坏的图片文件。YOLOv8训练时遇到损坏图片会报错并跳过,但提前排查更好。可以使用Python的 PIL 或 OpenCV 进行尝试读取验证。
    • 重命名 :建议按序列重命名文件,如 garbage_000001.jpg ,便于管理。
    • 初步筛选 :删除过于模糊、完全无法辨认类别或重复度过高的图片。

3.2 使用Roboflow与LabelImg进行高效标注

标注工具的选择直接影响效率。对于团队协作或大型项目,我强烈推荐 Roboflow 。它不仅提供在线标注界面,还内置了强大的数据预处理、增强和版本管理功能。你可以直接上传图片,在线标注,然后一键导出为YOLOv8格式,并自动划分训练集、验证集和测试集。

对于个人或小项目, LabelImg 是一个经典可靠的离线选择。这里详细说明用LabelImg标注的流程和避坑点:

  1. 安装与设置 :通过 pip install labelImg 安装。启动后,首先在 View 菜单中勾选 Auto Save mode 和 Display Labels 。在 File 菜单的 Change Save Dir 中,设置标签文件(.txt)的保存目录。 关键一步 :在 Edit 菜单点击 Predefined Classes ,预先输入你所有的垃圾类别名称。这能避免后续手动输入的错误,并大幅提升标注速度。

  2. 标注操作细节 :

    • 打开图片目录( Open Dir )。
    • 使用快捷键 w 拉取矩形框。框选时,务必紧贴物体边缘,但不必过于精确到像素级,适当留一点微小间隙是可以接受的。
    • 弹出对话框后,从预置类别中选择,或输入类别(如果没预置)。
    • 对于被遮挡物体, 标注其完整轮廓的估计位置 ,而不是仅标注可见部分。这对于模型学习物体的完整形状很重要。
    • 一张图片中的所有目标物体都应被标注,不要遗漏。
    • 标注完成后,按 Ctrl+S 保存,会自动生成同名的 .txt 文件。其内容格式为: <class_id> <x_center> <y_center> <width> <height> ,坐标和宽高都是相对于图片宽度和高度的归一化值(0-1之间)。
  3. 标注质量自查(至关重要) :

    • 类别一致性 :确保同类物体在所有图片中都被归为同一类别名,无拼写错误。
    • 框体质量 :检查是否有框体过大(包含太多背景)或过小(未覆盖完整物体)。检查是否有该标未标的目标。
    • 标签文件验证 :写一个简单的Python脚本,随机读取一些图片和对应的 .txt 文件,将标注框画在图片上显示,直观检查是否正确。可以使用OpenCV实现:
      import cv2, os
      img = cv2.imread(‘image.jpg’)
      h, w, _ = img.shape
      with open(‘image.txt’, ‘r’) as f:
          for line in f:
              cls_id, x_c, y_c, bw, bh = map(float, line.strip().split())
              # 转换回像素坐标
              x1 = int((x_c - bw/2) * w)
              y1 = int((y_c - bh/2) * h)
              x2 = int((x_c + bw/2) * w)
              y2 = int((y_c + bh/2) * h)
              cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 2)
              cv2.putText(img, str(int(cls_id)), (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1)
      cv2.imshow(‘check’, img)
      cv2.waitKey(0)
      

3.3 数据集组织与YAML配置

标注完成后,需要按照YOLOv8要求的目录结构组织数据,并创建关键的配置文件。

标准的目录结构如下 :

garbage_dataset/
├── images/
│   ├── train/       # 存放训练集图片
│   │   ├── garbage_000001.jpg
│   │   └── ...
│   └── val/         # 存放验证集图片
│       ├── garbage_010001.jpg
│       └── ...
└── labels/
    ├── train/       # 存放训练集标签文件 (.txt),与images/train/一一对应
    │   ├── garbage_000001.txt
    │   └── ...
    └── val/         # 存放验证集标签文件 (.txt)
        ├── garbage_010001.txt
        └── ...

通常按照8:1:1或7:2:1的比例随机划分训练集、验证集和测试集。测试集( test )可以单独分出来,用于最终评估,其目录结构与 train 和 val 相同。

创建 data.yaml 文件 : 这个文件是YOLOv8训练的数据集说明书,必须放在项目根目录下。

# data.yaml
path: /home/user/projects/garbage_detection  # 数据集的根目录绝对路径
train: images/train  # 训练集图片的相对路径(相对于path)
val: images/val      # 验证集图片的相对路径
test: images/test    # 测试集图片的相对路径(可选)

# 类别名称,顺序必须与标注时的class_id严格对应
names:
  0: plastic_bottle
  1: can
  2: paper_box
  3: newspaper
  4: glass_bottle
  5: battery
  6: food_waste
  7: residual_waste

# 可选:类别数量
nc: 8

实操心得 : path 字段强烈建议使用 绝对路径 。使用相对路径在训练时容易因当前工作目录不同而导致找不到文件的错误。你可以用Python的 os.path.abspath() 来获取绝对路径。

4. YOLOv8环境配置与模型训练

4.1 从零开始配置训练环境

训练环境的核心是Python、PyTorch和Ultralytics YOLO包。以下步骤在Ubuntu 20.04/Windows 10+上均测试通过。

  1. 创建并激活虚拟环境(推荐) :

    # 使用conda
    conda create -n yolov8 python=3.8
    conda activate yolov8
    
    # 或使用venv
    python -m venv yolov8_env
    # Windows
    yolov8_env\Scripts\activate
    # Linux/Mac
    source yolov8_env/bin/activate
    
  2. 安装PyTorch : 前往 PyTorch官网 根据你的CUDA版本(通过 nvidia-smi 查看)选择安装命令。例如,对于CUDA 11.8:

    pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
    

    如果没有NVIDIA GPU或CUDA,则安装CPU版本:

    pip install torch torchvision torchaudio
    
  3. 安装Ultralytics YOLOv8 :

    pip install ultralytics
    

    这个命令会安装YOLOv8核心库以及所有常用依赖(如opencv-python, pandas, matplotlib等)。

  4. 验证安装 :

    import torch
    print(torch.__version__)
    print(torch.cuda.is_available())  # 应返回True(如果安装了CUDA版本)
    
    from ultralytics import YOLO
    print(YOLO)  # 无报错即成功
    

4.2 模型训练与关键参数调优

环境就绪后,就可以开始训练了。YOLOv8提供了极其简洁的API。

基础训练命令 :

from ultralytics import YOLO

# 加载一个预训练模型(推荐从预训练模型开始,以加速收敛)
model = YOLO(‘yolov8s.pt’)  # 使用YOLOv8 small版本,平衡速度与精度

# 开始训练
results = model.train(
    data=‘./data.yaml’,      # 数据集配置文件路径
    epochs=100,               # 训练轮数
    imgsz=640,               # 输入图像尺寸
    batch=16,                # 批次大小(根据GPU显存调整)
    workers=4,               # 数据加载线程数
    device=‘0’,               # 使用GPU 0,如果是CPU则设为‘cpu’
    project=‘garbage_detection’, # 项目名称
    name=‘exp1’,              # 实验名称
    resume=False,             # 是否从上次检查点恢复
    amp=True                  # 启用自动混合精度训练,节省显存并加速
)

运行后,所有训练日志、模型权重、评估结果都会保存在 runs/detect/exp1 目录下。

关键参数深度解析与调优建议 :

  1. imgsz (图像尺寸) :默认640。增大尺寸(如1280)可以提升小目标检测精度,但会显著增加显存消耗和训练时间。对于垃圾分类,640通常足够。如果你的数据集中有很多非常小的垃圾碎片,可以考虑增大到960。

  2. batch (批次大小) :这是 最影响显存 的参数。在GTX 1660 Ti(6GB显存)上, imgsz=640 时, batch=16 可能已经接近极限。如果遇到CUDA out of memory错误,首先降低 batch (如设为8或4)。也可以尝试启用 amp=True (混合精度),它能在几乎不影响精度的情况下减少约30%的显存占用。

  3. workers (数据加载线程) :用于并行加载数据的进程数。建议设置为CPU核心数的2-4倍。设置过高可能导致内存不足,过低则可能使GPU等待数据,利用率上不去。Windows下有时设置 workers>0 会出错,可先设为0。

  4. epochs (训练轮数) :100是一个常见的起始值。 务必观察验证集损失( val/box_loss , val/cls_loss ) 。当验证损失在连续10-20个epoch内不再显著下降(甚至开始上升),就说明模型已经收敛或开始过拟合,可以提前终止训练。YOLOv8支持 patience 参数,可以设置早停。

  5. lr0 (初始学习率) :默认0.01。如果训练初期损失剧烈震荡或变为NaN,可以尝试降低学习率(如设为0.001)。如果损失下降非常缓慢,可以适当增大。

  6. cos_lr (余弦退火学习率调度) :建议启用。它会让学习率随着训练过程从初始值缓慢下降到最终值,有助于模型在训练后期更精细地收敛。

针对GTX 1660 Ti的优化配置示例 :

results = model.train(
    data=‘./data.yaml’,
    epochs=120,
    imgsz=640,
    batch=8,  # 1660Ti显存有限,batch设小一点
    workers=2,
    device=‘0’,
    amp=True,  # 必须开启,节省显存
    cos_lr=True,  # 启用余弦退火
    lr0=0.01,
    patience=30,  # 早停耐心值,30轮验证指标无改善则停止
    save_period=10,  # 每10个epoch保存一次检查点
    pretrained=True,  # 使用预训练权重(默认就是True)
)

4.3 训练过程监控与评估

训练启动后,Ultralytics会在控制台打印进度条,并在后台启动一个本地Web服务器,默认地址是 http://localhost:3000 (如果端口被占用,会顺延)。在浏览器中打开这个地址,就能看到一个非常直观的 训练看板 ,里面包含了:

  • 损失曲线 :包括训练和验证的边界框损失(box_loss)、分类损失(cls_loss)、目标存在损失(dfl_loss)。这是判断模型是否正常学习的核心指标。健康的曲线应该是训练损失和验证损失都平稳下降,且两者差距不大。如果验证损失上升,说明过拟合。
  • 性能指标 :如mAP@0.5, mAP@0.5:0.95等。mAP是衡量检测精度的核心指标,值越高越好。
  • 学习率曲线 :如果启用了 cos_lr ,可以看到学习率随epoch变化的曲线。
  • 验证集预测样例 :实时展示当前模型在验证集图片上的预测效果,非常直观。

训练完成后 ,最佳模型会自动保存在 runs/detect/exp1/weights/best.pt 。你可以使用这个模型进行验证和预测。

模型验证 :

model = YOLO(‘runs/detect/exp1/weights/best.pt’)
metrics = model.val()  # 在验证集上评估,默认使用训练时的data配置
print(metrics.box.map)   # 打印mAP50
print(metrics.box.map50) # 打印mAP50-95

model.val() 会生成详细的评估报告,包括每个类别的精确度(Precision)、召回率(Recall)、mAP,并保存一个包含预测框的验证集图片结果在 runs/detect/exp2 (新的实验目录)中。

5. 模型优化、部署与实战应用

5.1 模型性能分析与优化技巧

拿到一个训练好的模型,不要急于部署,先进行深入分析,找到提升空间。

  1. 混淆矩阵分析 :训练完成后,在 runs/detect/exp1 目录下会生成一个 confusion_matrix.png 。这张图能清晰揭示模型在哪些类别上容易混淆。例如,如果“塑料瓶”和“玻璃瓶”的混淆值很高,说明模型未能很好地区分这两者的视觉特征。解决方案是:1)增加这两类物体的差异化数据(如更多带标签的塑料瓶和玻璃瓶图片);2)检查标注是否有误;3)可以考虑在模型结构上增加对透明/反光材质感知的能力(但这属于高级优化)。

  2. F1-置信度曲线 : F1_curve.png 展示了在不同置信度阈值下的F1分数。F1是精确度和召回率的调和平均。你可以找到一个使F1分数最大化的置信度阈值。 默认的预测置信度阈值是0.25 ,你可以根据此曲线进行调整。例如,如果曲线显示在置信度0.4时F1最高,那么在部署推理时,可以将阈值设为0.4,以在精确度和召回率间取得更好平衡。

    results = model.predict(‘test.jpg’, conf=0.4)  # 设置置信度阈值为0.4
    
  3. PR曲线与mAP : PR_curve.png 展示了每个类别的精确度-召回率曲线,曲线下面积即为AP(Average Precision)。 results.png 中会汇总所有类别的mAP。关注那些AP值较低的类别,它们是模型当前的弱点,需要针对性补充数据或进行数据增强。

  4. 错误案例分析 :手动查看验证集预测结果(保存在 runs/detect/exp2 中的图片)。重点关注:

    • 漏检(False Negative) :模型没检测到的物体。是物体太小?太模糊?还是与背景颜色太接近?
    • 误检(False Positive) :模型把背景或其他物体误认为目标。是某类背景与目标物体相似?
    • 定位不准 :框的位置或大小偏差大。 根据这些具体案例,回头优化你的数据集。

5.2 模型导出与多平台部署

YOLOv8训练出的 .pt 文件是PyTorch格式,要部署到生产环境(尤其是嵌入式设备),通常需要转换成更高效的格式。

1. 导出为ONNX格式 : ONNX是一种开放的模型交换格式,被众多推理引擎支持。

model.export(format=‘onnx’, imgsz=[640, 640], simplify=True)
  • imgsz : 指定导出的模型输入尺寸。
  • simplify=True : 对ONNX模型进行简化,优化结构,有时能减少推理时间。 导出后得到 best.onnx 文件。你可以使用 Netron 工具打开它,可视化模型结构。

2. 导出为TensorRT格式(针对NVIDIA GPU) : TensorRT是NVIDIA的高性能深度学习推理SDK,能极大提升在NVIDIA GPU上的推理速度。

model.export(format=‘engine’, imgsz=[640, 640])

这需要你的环境已安装TensorRT。导出后会生成 best.engine 文件。在Jetson系列或带有NVIDIA GPU的服务器上部署时,直接加载这个engine文件进行推理,速度可比原生PyTorch快数倍。

3. 导出为OpenVINO格式(针对Intel CPU/GPU) : OpenVINO是Intel推出的工具套件,用于优化在Intel硬件上的AI推理。

model.export(format=‘openvino’, imgsz=[640, 640])

导出后得到一个包含 .xml 和 .bin 文件的文件夹。使用OpenVINO的Runtime API加载,可以在Intel CPU、集成显卡或独立显卡上获得加速。

4. 导出为CoreML格式(针对Apple设备) :

model.export(format=‘coreml’, imgsz=[640, 640])

导出后得到 best.mlmodel 文件,可以集成到iOS或macOS应用中。

5. 部署到RK3588等嵌入式开发板 : 以瑞芯微RK3588为例,部署流程通常为:

  • 步骤一 :将模型导出为ONNX。
  • 步骤二 :使用RKNN-Toolkit2工具链,将ONNX模型转换和量化成RKNN格式。量化(如INT8)可以大幅减少模型体积和提升推理速度,但可能会带来轻微精度损失,需要仔细评估。
  • 步骤三 :在RK3588开发板上,使用C++或Python调用RKNN SDK加载RKNN模型进行推理。 这个过程涉及交叉编译和环境配置,是嵌入式AI部署的常见路径。

5.3 实战应用:构建一个简单的垃圾分类检测系统

最后,我们来搭建一个最简单的端到端应用,演示如何使用训练好的模型。

Python实时摄像头检测脚本 :

import cv2
from ultralytics import YOLO
import time

# 加载训练好的模型
model = YOLO(‘runs/detect/exp1/weights/best.pt’)

# 打开摄像头(0为默认摄像头)
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print(“无法打开摄像头”)
    exit()

# 定义类别颜色(为不同类别的框分配不同颜色)
colors = [(0, 255, 0), (255, 0, 0), (0, 0, 255), (255, 255, 0), (0, 255, 255), (255, 0, 255), (128, 128, 0), (0, 128, 128)]

print(“开始实时检测,按 ‘q’ 键退出...”)
while True:
    ret, frame = cap.read()
    if not ret:
        print(“无法获取帧”)
        break

    # 记录推理开始时间
    start_time = time.time()

    # 进行推理, conf设置置信度阈值
    results = model(frame, conf=0.5, imgsz=640)

    # 计算FPS
    fps = 1 / (time.time() - start_time)

    # 获取第一个结果的预测框
    boxes = results[0].boxes
    if boxes is not None:
        for box, cls, conf in zip(boxes.xyxy, boxes.cls, boxes.conf):
            # 转换为整数坐标
            x1, y1, x2, y2 = map(int, box[:4])
            class_id = int(cls)
            confidence = float(conf)

            # 获取类别名和颜色
            class_name = model.names[class_id]
            color = colors[class_id % len(colors)]

            # 在帧上绘制边界框和标签
            cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
            label = f‘{class_name} {confidence:.2f}’
            # 计算文本背景大小
            (text_width, text_height), baseline = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)
            cv2.rectangle(frame, (x1, y1 - text_height - baseline), (x1 + text_width, y1), color, -1)
            cv2.putText(frame, label, (x1, y1 - baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

    # 在左上角显示FPS
    cv2.putText(frame, f‘FPS: {fps:.1f}’, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

    # 显示结果
    cv2.imshow(‘Garbage Detection’, frame)

    # 按‘q’退出
    if cv2.waitKey(1) & 0xFF == ord(‘q’):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

这个脚本会打开你的电脑摄像头,实时检测画面中的垃圾,并用不同颜色的框和标签标识出来,同时显示实时帧率(FPS)。你可以将其修改为处理视频文件或网络流。

6. 常见问题排查与经验实录

在实战中,你几乎一定会遇到下面这些问题。这里是我和同事们踩过坑后总结的解决方案。

问题1:训练时出现 ignoring corrupt image/label: ... 警告。

  • 原因 :YOLOv8在加载数据时发现某些图片或标签文件损坏、无法读取或格式不对。
  • 排查 :
    1. 检查警告中提到的具体文件路径,如 E:\yolov8\images\val\00010752.png 。
    2. 用图片查看器或 PIL.Image.open() 尝试打开该图片,确认是否损坏。
    3. 检查对应的标签文件( .txt )是否存在,格式是否正确(每行5个用空格分隔的数字)。
  • 解决 :
    • 如果是图片损坏,从数据集中删除该图片及其标签文件。
    • 如果是标签文件格式错误,手动修正或重新标注。
    • 可以在训练前运行一个数据清洗脚本,主动过滤掉所有问题文件。

问题2:训练损失(loss)不下降,或者震荡非常厉害。

  • 原因 :
    1. 学习率(lr0)设置不当 :过高会导致震荡,过低会导致下降缓慢。
    2. 数据质量差 :标注错误太多,或者图片质量太差(模糊、过暗)。
    3. 数据量太少 :模型学不到有效规律。
    4. 模型复杂度与数据不匹配 :数据简单但模型太大(如用YOLOv8x训练几百张图),容易过拟合;数据复杂但模型太小(如用YOLOv8n),欠拟合。
  • 解决 :
    1. 尝试降低学习率(如从0.01调到0.001),或启用 cos_lr 。
    2. 仔细检查并清洗数据,确保标注准确。
    3. 增加数据量,或使用更强大的数据增强(在 data.yaml 中调整增强参数,或使用Roboflow进行离线增强)。
    4. 更换模型尺寸。数据量少时用 n 或 s ,数据量大且复杂时用 m 或 l 。

问题3:模型在训练集上表现很好,但在验证集或新图片上效果很差(过拟合)。

  • 现象 :训练损失很低,验证损失很高;训练集mAP高,验证集mAP低。
  • 原因 :模型“死记硬背”了训练集,没有学会泛化特征。
  • 解决 :
    1. 增加数据多样性 :这是最根本的方法。收集更多不同场景、光照、背景下的图片。
    2. 加强数据增强 :启用并调高YOLOv8的马赛克增强( mosaic=1.0 )、混合增强( mixup=0.5 )等强度。
    3. 使用正则化 :在训练参数中增加 dropout (如果模型支持)或权重衰减( weight_decay )。
    4. 早停(Early Stopping) :设置 patience 参数,当验证指标不再提升时自动停止训练,保留验证集上最好的模型。
    5. 减少模型复杂度 :换用更小的模型(如从 YOLOv8m 换到 YOLOv8s )。

问题4:推理速度慢,FPS达不到实时要求。

  • 原因 :
    1. 模型太大(如使用了 YOLOv8x )。
    2. 输入图片尺寸( imgsz )太大。
    3. 部署环境硬件性能不足(如使用CPU推理)。
    4. 推理代码存在效率瓶颈(如循环处理)。
  • 解决 :
    1. 换用更小的模型( n 或 s )。
    2. 减小推理时的图片尺寸(如从640降到320)。注意,这可能会降低小目标检测精度。
    3. 如果使用GPU,确保已安装对应版本的CUDA和cuDNN,并使用TensorRT等加速引擎。
    4. 优化推理代码,例如使用批处理(batch inference)而不是单张图片推理。

问题5:如何画出训练过程中的损失函数曲线图? YOLOv8训练时自动生成的日志已经包含了所有损失和指标数据,并保存在 runs/detect/exp1/results.csv 文件中。你可以用Python轻松绘制:

import pandas as pd
import matplotlib.pyplot as plt

results = pd.read_csv(‘runs/detect/exp1/results.csv’)

plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.plot(results[‘epoch’], results[‘train/box_loss’], label=‘Train Box Loss’)
plt.plot(results[‘epoch’], results[‘val/box_loss’], label=‘Val Box Loss’)
plt.legend()
plt.grid()
plt.title(‘Box Loss’)

plt.subplot(2, 2, 2)
plt.plot(results[‘epoch’], results[‘train/cls_loss’], label=‘Train Cls Loss’)
plt.plot(results[‘epoch’], results[‘val/cls_loss’], label=‘Val Cls Loss’)
plt.legend()
plt.grid()
plt.title(‘Classification Loss’)

plt.subplot(2, 2, 3)
plt.plot(results[‘epoch’], results[‘metrics/mAP50(B)’], label=‘mAP50’)
plt.legend()
plt.grid()
plt.title(‘mAP50’)

plt.subplot(2, 2, 4)
plt.plot(results[‘epoch’], results[‘metrics/mAP50-95(B)’], label=‘mAP50-95’)
plt.legend()
plt.grid()
plt.title(‘mAP50-95’)

plt.tight_layout()
plt.savefig(‘training_curves.png’, dpi=300)
plt.show()

通过分析这些曲线,你可以清晰地掌握模型训练的动态过程,为调参提供直接依据。

整个项目从数据准备到部署上线的闭环走下来,最大的体会是:在AI落地项目中,算法模型只占一部分,甚至不是最耗时的部分。数据的质量、标注的规范性、对业务场景(垃圾分类规则)的深度理解,以及根据实际问题(如过拟合、速度慢)进行迭代调优的能力,往往更能决定项目的成败。YOLOv8作为一个优秀的工具,极大地降低了技术门槛,但如何用好它,依然需要我们带着解决问题的思维,一步步去实践、观察和调整。希望这份超详细的拆解,能帮你绕过我们曾经踩过的那些坑,更顺畅地完成你自己的垃圾分类检测项目。如果在实操中遇到新的问题,不妨回头看看数据和分析训练曲线,答案往往就藏在里面。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

Logo

聚焦RDK与具身智能,汇集机器人开发教程、开源案例和技术交流

更多推荐