【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的垃圾分类」**获取。

相关推荐
青 春 记 忆4 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO34 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO6 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白6 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
Littlehero_1217 小时前
QT自定义控件之内嵌报表(4)(源码开源)
开发语言·qt
荷蒲8 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)9 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机9 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69210 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy11 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源