【YOLO26 系列】基于YOLO26的垃圾分类检测系统【python源码+Pyqt5界面/WEB+数据集+训练代码】

【YOLO26 系列】基于YOLO26的垃圾分类检测系统【python源码+Pyqt5界面/WEB+数据集+训练代码】

导读

本文基于最新YOLO26模型,开发了一套用于垃圾分类目标检测的智能系统,项目同时提供PyQt GUI本地界面和Flask Web网页两种交互方式。本项目采用公开TACO垃圾分类数据集开展训练,数据集涵盖18类常见生活垃圾,包含数千张标注图像。系统支持单张图片检测、文件夹批量检测、视频检测、摄像头实时检测四种模式,同时支持检测结果自动保存,可应用于智能垃圾分类回收设备、城市环卫垃圾分类识别等场景,兼具高精度识别能力与良好的实时性。

一、软件功能演示

本项目提供两种可视化交互界面:本地GUI界面和Web网页端,核心功能包含图片检测、文件夹批量检测、视频检测、摄像头实时检测、结果保存五大模块。

【YOLO26 系列】基于YOLO26的垃圾分类检测系统

1.1 单张图片检测

操作流程:打开GUI/Web界面 → 点击【打开图片】按钮 → 选择待检测的单张垃圾分类图片 → 点击【开始检测】按钮,系统将自动识别图片中的垃圾类别并输出检测结果。

检测结果以结构化表格形式展示:

序号 图片名称 检测类型 垃圾类别 置信度 坐标位置(左上角-右下角)
1 0001.jpg 图片检测 Bottle 0.89 (32, 45)-(215, 320)
2 0001.jpg 图片检测 Can 0.82 (240, 120)-(410, 285)
3 0001.jpg 图片检测 Plastic bag - wrapper 0.76 (100, 250)-(340, 420)

界面同时会在原图上绘制检测框与类别置信度,直观呈现检测结果。

1.2 文件夹批量检测

操作流程:点击【打开文件夹】 → 选择包含多张待检测图片的文件夹 → 点击【开始检测】,系统将依次对文件夹内所有图片进行批量检测,并自动保存全部检测结果。

批量检测结果统计示例:

统计项 数值
总检测图片数 20
检测到垃圾目标总数 48
检出最多类别 Other plastic

1.3 视频检测

操作流程:点击【打开视频】 → 选择待检测的视频文件 → 点击【开始检测】,系统将对视频逐帧进行实时检测,并在界面上实时输出检测结果。

实时检测单帧结果示例:

序号 帧ID 检测类型 垃圾类别 置信度 坐标位置
1 120 视频检测 Carton 0.91 (180, 120)-(320, 240)
2 120 视频检测 Cigarette 0.85 (410, 210)-(480, 260)
3 120 视频检测 Styrofoam piece 0.78 (220, 300)-(400, 410)

1.4 摄像头实时检测

操作流程:点击【开启相机】按钮 → 系统自动调用电脑本地摄像头 → 点击【开始检测】后,对摄像头实时采集的画面进行目标检测,支持实时识别画面中的各类垃圾。

该功能可对接嵌入式摄像头设备,用于开发落地智能垃圾分类回收硬件。

1.5 保存检测结果

检测完成后,点击【保存结果】按钮即可保存两类检测结果:

  1. 检测图片 :自动将带有检测框和标注的结果图片保存至项目results/目录
  2. 检测信息:自动将所有检测结果的结构化信息(类别、置信度、坐标)保存为CSV文件,方便后续分析使用

二、环境搭建

本项目基于PyTorch框架开发,提供两种环境配置方式,可根据自身需求选择。

2.1 PyTorch手动安装

本项目不包含PyTorch安装包,需自行安装适配硬件的版本:

  • CUDA 11版本用户可参考以下命令安装:
bash 复制代码
pip3 install torch torchvision --extra-index-url https://download.pytorch.org/whl/cu118
  • CPU版本用户可参考以下命令安装:
bash 复制代码
pip3 install torch torchvision --extra-index-url https://download.pytorch.org/whl/cpu

官方下载地址:torchtorchvision

详细安装教程视频:torch 环境配置 从零开始安装

2.2 项目依赖安装

克隆项目到本地后,进入项目根目录,执行以下pip命令安装剩余依赖:

bash 复制代码
pip install -r requirements.txt

若使用Conda环境,可通过以下命令创建并激活环境:

bash 复制代码
# 若提供environment.yml文件
conda env create -f environment.yml
conda activate yolo26-garbage
界面启动方式
  • 启动本地GUI界面:
bash 复制代码
cd UI
python GUI.py
  • 启动Web网页端:
bash 复制代码
cd UI
python web.py

启动后,在浏览器打开控制台输出的本地地址即可访问网页端界面。


三、模型训练、评估、预测

3.1 数据集上传说明

3.1.1 数据集格式要求

本项目使用标准YOLO格式数据集,目录结构如下:

复制代码
dataset/
├── train/
│   ├── images/  # 训练集图片
│   │   ├── img1.jpg
│   │   ├── img2.jpg
│   │   └── ...
│   └── labels/  # 训练集标签
│       ├── img1.txt
│       ├── img2.txt
│       └── ...
├── val/
│   ├── images/  # 验证集图片
│   └── labels/  # 验证集标签
└── test/
    ├── images/  # 测试集图片
    └── labels/  # 测试集标签

本项目使用公开TACO垃圾分类数据集,可通过百度网盘下载:

链接: https://pan.baidu.com/s/19lJ5VmLC2la1Voe866g79A 提取码: ntha

下载后将数据集解压放入VOCData/文件夹即可。

3.1.2 YOLO格式标签说明

YOLO格式标签为每张图片对应一个同名.txt文件,每行对应一个目标,格式为:

复制代码
<class_id> <x_center> <y_center> <width> <height>

所有坐标均为归一化坐标(取值范围0~1),各参数说明:

参数 说明
class_id 垃圾类别的ID,从0开始编号
x_center 检测框中心点X坐标除以图片宽度
y_center 检测框中心点Y坐标除以图片高度
width 检测框宽度除以图片宽度
height 检测框高度除以图片高度

示例0 0.45 0.32 0.21 0.41 表示类别ID为0的垃圾,中心点位于图片45%宽度、32%高度位置,检测框宽度占图片总宽度21%,高度占图片总高度41%。

3.1.3 从VOC格式转换(XML转YOLO TXT)

若你的数据集为VOC标注格式(XML标注文件),可使用以下脚本将XML转换为YOLO TXT格式:

python 复制代码
import os
import xml.etree.ElementTree as ET

# 定义垃圾分类类别顺序,需与yaml配置保持一致
categories = [
    'Aluminium foil', 'Bottle cap', 'Bottle', 'Broken glass', 'Can', 
    'Carton', 'Cigarette', 'Cup', 'Lid', 'Other litter', 
    'Other plastic', 'Paper', 'Plastic bag - wrapper', 'Plastic container', 
    'Pop tab', 'Straw', 'Styrofoam piece', 'Unlabeled litter'
]
category_to_index = {category: index for index, category in enumerate(categories)}

# 替换为自己的XML文件夹路径和输出TXT路径
input_folder = r'./VOCData/Annotations'
output_folder = r'./VOCData/labels'

# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)

# 遍历所有XML文件
for filename in os.listdir(input_folder):
    if filename.endswith('.xml'):
        xml_path = os.path.join(input_folder, filename)
        # 解析XML
        tree = ET.parse(xml_path)
        root = tree.getroot()
        
        # 获取图片宽高
        size = root.find('size')
        width = int(size.find('width').text)
        height = int(size.find('height').text)
        
        objects = []
        # 遍历每个标注目标
        for obj in root.findall('object'):
            name = obj.find('name').text
            if name not in category_to_index:
                continue
            category_index = category_to_index[name]
            
            # 获取原始坐标
            bndbox = obj.find('bndbox')
            xmin = int(bndbox.find('xmin').text)
            ymin = int(bndbox.find('ymin').text)
            xmax = int(bndbox.find('xmax').text)
            ymax = int(bndbox.find('ymax').text)
            
            # 转换为归一化中心点宽高
            x_center = (xmin + xmax) / 2.0 / width
            y_center = (ymin + ymax) / 2.0 / height
            w = (xmax - xmin) / width
            h = (ymax - ymin) / height
            
            objects.append(f"{category_index} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}")
        
        # 保存为TXT文件
        txt_filename = os.path.splitext(filename)[0] + '.txt'
        txt_path = os.path.join(output_folder, txt_filename)
        with open(txt_path, 'w') as f:
            for obj in objects:
                f.write(obj + '\n')

print("VOC XML转YOLO TXT完成!")

也可运行项目自带的VOCData/xml2txt.py脚本,修改路径后使用。

3.1.4 数据集划分脚本

格式转换完成后,使用以下脚本按照8:1:1比例划分训练集、验证集、测试集:

python 复制代码
import os
import shutil
import random

# 开启固定随机种子保证结果可复现
# random.seed(42)

def split_data(file_path, label_path, new_file_path, train_rate, val_rate, test_rate):
    # 获取所有图片和标签
    images = os.listdir(file_path)
    labels = os.listdir(label_path)
    # 匹配图片和标签,保证一一对应
    images_no_ext = {os.path.splitext(image)[0]: image for image in images}
    labels_no_ext = {os.path.splitext(label)[0]: label for label in labels}
    matched_data = [(img, images_no_ext[img], labels_no_ext[img]) for img in images_no_ext if img in labels_no_ext]
    
    # 输出未匹配的文件,方便检查
    unmatched_images = [img for img in images_no_ext if img not in labels_no_ext]
    unmatched_labels = [label for label in labels_no_ext if label not in images_no_ext]
    if unmatched_images:
        print("未匹配的图片文件:")
        for img in unmatched_images:
            print(images_no_ext[img])
    if unmatched_labels:
        print("未匹配的标签文件:")
        for label in unmatched_labels:
            print(labels_no_ext[label])
    
    # 打乱数据,按比例划分
    random.shuffle(matched_data)
    total = len(matched_data)
    train_data = matched_data[:int(train_rate * total)]
    val_data = matched_data[int(train_rate * total):int((train_rate + val_rate) * total)]
    test_data = matched_data[int((train_rate + val_rate) * total):]
    
    # 处理训练集
    for img_name, img_file, label_file in train_data:
        old_img_path = os.path.join(file_path, img_file)
        old_label_path = os.path.join(label_path, label_file)
        new_img_dir = os.path.join(new_file_path, 'train', 'images')
        new_label_dir = os.path.join(new_file_path, 'train', 'labels')
        os.makedirs(new_img_dir, exist_ok=True)
        os.makedirs(new_label_dir, exist_ok=True)
        shutil.copy(old_img_path, os.path.join(new_img_dir, img_file))
        shutil.copy(old_label_path, os.path.join(new_label_dir, label_file))
    
    # 处理验证集
    for img_name, img_file, label_file in val_data:
        old_img_path = os.path.join(file_path, img_file)
        old_label_path = os.path.join(label_path, label_file)
        new_img_dir = os.path.join(new_file_path, 'val', 'images')
        new_label_dir = os.path.join(new_file_path, 'val', 'labels')
        os.makedirs(new_img_dir, exist_ok=True)
        os.makedirs(new_label_dir, exist_ok=True)
        shutil.copy(old_img_path, os.path.join(new_img_dir, img_file))
        shutil.copy(old_label_path, os.path.join(new_label_dir, label_file))
    
    # 处理测试集
    for img_name, img_file, label_file in test_data:
        old_img_path = os.path.join(file_path, img_file)
        old_label_path = os.path.join(label_path, label_file)
        new_img_dir = os.path.join(new_file_path, 'test', 'images')
        new_label_dir = os.path.join(new_file_path, 'test', 'labels')
        os.makedirs(new_img_dir, exist_ok=True)
        os.makedirs(new_label_dir, exist_ok=True)
        shutil.copy(old_img_path, os.path.join(new_img_dir, img_file))
        shutil.copy(old_label_path, os.path.join(new_label_dir, label_file))
    
    print(f"数据集划分完成!总样本数:{total},训练集:{len(train_data)},验证集:{len(val_data)},测试集:{len(test_data)}")

if __name__ == '__main__':
    # 修改为自己的路径
    file_path = r"./VOCData/JPEGImages"  # 原始图片文件夹
    label_path = r'./VOCData/labels'      # 转换后的标签文件夹
    new_file_path = r"./VOCData/VOdevkit" # 划分后数据集存放位置
    # 按8:1:1划分,可自行调整比例
    split_data(file_path, label_path, new_file_path, train_rate=0.8, val_rate=0.1, test_rate=0.1)

运行项目自带的VOCData/SplitDataset.py脚本也可完成划分。

3.1.5 配置数据集yaml文件

数据集划分完成后,创建或修改dataset.yaml配置文件,本项目实际配置如下:

yaml 复制代码
train: ../train/images
val: ../valid/images
test: ../test/images

# 类别数量
nc: 18
# 类别名称,需与转换脚本中的顺序保持一致
names: ['Aluminium foil', 'Bottle cap', 'Bottle', 'Broken glass', 'Can', 'Carton', 'Cigarette', 'Cup', 'Lid', 'Other litter', 'Other plastic', 'Paper', 'Plastic bag - wrapper', 'Plastic container', 'Pop tab', 'Straw', 'Styrofoam piece', 'Unlabeled litter']

roboflow:
  workspace: divya-lzcld
  project: taco-mqclx
  version: 3
  license: CC BY 4.0
  url: https://universe.roboflow.com/divya-lzcld/taco-mqclx/dataset/3

将该文件放在VOCData/VOdevkit/目录下,训练时指定该路径即可。


3.2 模型训练

数据集准备完成后,执行项目根目录下的train.py脚本即可启动训练,核心训练代码如下:

python 复制代码
import warnings
warnings.filterwarnings('ignore')
from ultralytics import YOLO

if __name__ == '__main__':
    # 加载YOLO26n预训练权重
    model = YOLO('yolo26n.pt')
    # 启动训练
    results = model.train(
        data=r'..\VOCData\VOdevkit\dataset.yaml',  # 数据集配置文件路径
        epochs=100,  # 训练总轮次
        batch=16,    # 批次大小,根据显存调整
        imgsz=640,   # 训练输入图像尺寸
        workers=8,   # 数据加载线程数
        device=0,    # GPU设备号,CPU训练改为 'cpu'
        optimizer='SGD',  # 优化器,可选 auto, SGD, Adam, AdamW
        amp=False,   # 是否开启自动混合精度训练
        cache=False  # 是否在内存缓存数据集,大显存服务器推荐开启
    )

主要训练参数说明:

参数 说明 推荐值
epochs 训练总轮次 100~300
batch 批次大小 8/16/32(根据显存调整)
imgsz 输入图像尺寸 640(通用场景)
device 训练设备 0(第一张GPU),cpu表示使用CPU训练
optimizer 优化器 SGD 或 AdamW
amp 自动混合精度训练 开启可减少显存占用、加快训练速度
cache 数据集内存缓存 大内存服务器开启可加快训练速度

启动训练命令:

bash 复制代码
python train.py

3.3 训练结果评估

训练完成后,所有结果将保存至项目runs/detect/train/目录下,核心输出文件如下:

文件/目录 说明
weights/best.pt 最优模型权重,推荐推理时使用
weights/last.pt 最后一轮训练的权重
weights/epoch*.pt 每N轮保存的阶段性权重
args.yaml 本次训练的参数配置记录
results.csv 每轮训练的指标记录
results.png 训练损失、指标变化曲线图
confusion_matrix.png 混淆矩阵可视化图
confusion_matrix_normalized.png 归一化混淆矩阵可视化图
BoxPR_curve.png PR曲线(精确率-召回率曲线)
BoxF1_curve.png F1曲线(F1值-置信度曲线)
labels.jpg 数据集标签分布可视化图

使用val.py可对训练好的最优模型进行评估,输出详细评估指标:

python 复制代码
from ultralytics import YOLO
import numpy as np
from datetime import datetime

# 加载训练完成的最优权重
model = YOLO(r"..\runs\detect\train\weights\best.pt")

# 在验证集上执行评估
metrics = model.val(data=r"..\VOCData\VOdevkit\dataset.yaml")

# 计算平均精确率(Precision)、平均召回率(Recall)
mean_p = np.mean(metrics.box.p)
mean_r = np.mean(metrics.box.r)

# 整理输出内容
content = []
content.append("="*60)
content.append(f"验证时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
content.append("="*60)
content.append(f"整体 mAP50:        {metrics.box.map50:.4f}")
content.append(f"整体 mAP50-95:     {metrics.box.map:.4f}")
content.append(f"平均 Precision:    {mean_p:.4f}")
content.append(f"平均 Recall:       {mean_r:.4f}")
content.append("-"*60)
content.append(f"{'类别':<12}{'Precision':<12}{'Recall':<12}{'AP50':<12}")
content.append("-"*60)

for i, class_name in enumerate(metrics.names):
    ap50 = metrics.box.ap50[i]
    p = metrics.box.p[i]
    r = metrics.box.r[i]
    content.append(f"{class_name:<12}{p:.4f}{r:<12}{ap50:.4f}")

# 保存评估结果到文件
with open("val_result.txt", "w", encoding="utf-8") as f:
    f.write("\n".join(content))

# 在控制台打印评估结果
print("\n".join(content))

运行验证命令:

bash 复制代码
python val.py

3.4 模型预测

训练完成后,可使用predict.py对单张图片、文件夹、视频、摄像头进行推理预测,核心代码如下:

python 复制代码
from ultralytics import YOLO
import os

# 加载训练好的模型,修改为自己的权重路径
root = os.getcwd()
model = YOLO(rf'{root}/runs/detect/train/weights/best.pt')

# 修改为自己的预测源:支持图片路径、文件夹路径、视频路径、摄像头ID(0为默认摄像头)
source = r'./img_video/test_imgs/test1.jpg'

# 运行推理,save=True表示自动保存结果
results = model.predict(source, save=True)

# 弹窗显示检测结果
results[0].show()

# 自定义保存结果路径
results[0].save(filename=r"./results/detected_result.jpg")

运行预测命令:

bash 复制代码
python predict.py

结果默认保存至项目results/目录。


四、项目目录结构

复制代码
基于YOLO26的垃圾分类检测系统/
├── 📄 README.md                    # 项目说明文档
├── 📄 requirements.txt             # Python依赖列表
├── 📄 yolo26n.pt                   # YOLO26n预训练权重
├── 🐍 train.py                     # 模型训练入口脚本
├── 🐍 predict.py                   # 模型预测推理入口脚本
├── 🐍 val.py                       # 模型验证评估脚本
├── 📂 UI/                          # 界面相关代码
│   ├── 🐍 web.py                   # Flask Web后端程序
│   ├── 🐍 GUI.py                   # 本地GUI界面程序
│   ├── 📄 config.yaml              # UI配置文件
│   ├── 📄 user.txt                 # 用户信息文件
│   ├── 📂 templates/               # Web前端页面模板
│   │   ├── 📄 index.html           # Web端主页面
│   │   └── 📄 login.html           # Web端登录页面
│   └── 📂 models/
│       └── 📦 best.pt              # UI使用的最优模型权重
├── 📂 img_video/                   # 测试素材目录
│   ├── 📂 test_imgs/               # 测试图片集
│   └── 🎬 test_MP4.mp4             # 测试视频文件
├── 📂 results/                     # 预测结果输出目录
├── 📂 runs/                        # 训练运行结果目录
│   └── 📂 detect/train/
│       ├── 📄 args.yaml            # 训练参数配置记录
│       ├── 📄 results.csv          # 训练指标记录文件
│       ├── 📊 results.png          # 训练结果曲线图
│       ├── 📊 confusion_matrix.png # 混淆矩阵可视化图
│       ├── 📊 BoxPR_curve.png      # PR曲线图
│       ├── 📊 labels.jpg           # 标签分布可视化图
│       └── 📂 weights/
│           ├── 📦 best.pt          # 最优模型权重
│           ├── 📦 last.pt          # 最后一轮训练权重
│           └── ...                 # 各轮次阶段性权重
├── 📂 VOCData/                     # 数据集处理工具目录
│   ├── 🐍 SplitDataset.py          # 数据集划分脚本
│   ├── 🐍 ViewCategory.py          # 类别统计脚本
│   ├── 🐍 xml2txt.py               # VOC XML转YOLO TXT脚本
│   ├── 🐍 pic to mp4.py            # 图片转视频脚本
│   └── 📂 VOdevkit/
│       ├── 📄 dataset.yaml         # 数据集配置文件
│       └── 📄 数据集单独下载.txt    # 数据集下载说明文件
└── 📂 ultralytics/                 # YOLO框架核心源码目录
    ├── 📂 cfg/                     # 模型和数据集配置目录
    ├── 📂 data/                    # 数据加载和增强模块
    ├── 📂 engine/                  # 训练/预测引擎模块
    └── ...                         # 其他框架功能模块

五、项目README摘要

本项目是基于最新YOLO26目标检测模型开发的垃圾分类检测系统,主要特性如下:

  1. 支持18类常见生活垃圾的检测识别,采用公开TACO标注数据集,数据质量有保障
  2. 提供本地GUI和Web网页两种交互界面,满足不同场景的使用需求
  3. 支持单张图片、文件夹批量、视频文件、摄像头实时四种检测模式
  4. 支持检测结果自动保存,结构化输出检测信息,便于后续分析
  5. 提供完整的数据处理、训练、评估、预测全流程代码,可直接用于二次开发

项目使用流程:环境搭建 → 数据集准备 → 模型训练 → 评估推理 → 界面部署,各流程步骤清晰,代码注释完整,既适合深度学习初学者学习,也可直接用于实际项目落地。


文末互动区

如果您觉得本项目有帮助,欢迎点击【分享】【推荐】支持我们!

如需获取完整项目代码与数据集, 回复**「基于YOLO26的垃圾分类」**获取。

相关推荐
滴滴滴嘟嘟嘟.1 小时前
强化学习消融实验-batch_size / clip_range / gae_lambda / lr
python·机器学习
2601_963932981 小时前
怀孕四个月能做流产吗?中期妊娠终止方式与子宫修护科普指南
python
zhr_math_king1 小时前
LangGraph-快速入门-第一个例子
python·langchain
爱吃苹果的梨叔2 小时前
2026年指挥中心分布式坐席怎么选?清虹创智让多系统、多坐席和大屏真正协同
python
起予者汝也2 小时前
Python 数据结构
开发语言·数据结构·python
LadenKiller2 小时前
2026年量化工具增量,放回回测模拟实盘阶段判断
人工智能·python
石一峰6993 小时前
驱动:私有数据为什么要在三个地方各挂一遍?
数据库·python·算法
2601_956319883 小时前
最新量化软件怎么选,先按能力短板匹配工具类型
人工智能·python
Tbisnic3 小时前
26.AI大模型:RNN、LSTM、GRU
人工智能·python·rnn·gru·大模型·llm·lstm