【YOLO26 系列】基于YOLO26葡萄叶病害检测系统【python源码+Pyqt5界面/WEB+数据集+训练代码】
基于YOLO26的葡萄叶病害检测系统
导读
本文基于YOLO26目标检测模型,开发了一套葡萄叶病害自动检测系统,可精准识别葡萄叶片4类常见病害状态。项目包含PyQt5 GUI桌面端与Flask Web网页端双实现,支持单张图片检测、文件夹批量检测、视频检测、实时摄像头检测及结果保存五大核心功能,帮助农业种植人员快速识别葡萄叶病害,提升病害防治效率。本项目提供完整训练代码、预训练权重、UI源码和数据集配置说明,可直接部署使用,也可基于该项目二次开发,扩展至其他农业病害检测场景。
一、软件功能演示
本系统提供PyQt5 GUI桌面端和Flask Web网页端两种使用方式,核心功能包含以下5类:
演示视频
1. 单张图片检测
操作流程:点击📁 模型选择加载训练好的YOLO权重文件 → 点击🖼️ 图片检测选择本地葡萄叶图片 → 系统自动完成推理并绘制检测框,同步显示类别与置信度。
检测完成后,系统会自动统计检测结果并生成明细表格:
| 序号 | 病害类别 | 置信度 | 检测框坐标 (xmin, ymin, xmax, ymax) |
|---|---|---|---|
| 1 | Grape__BlackRot | 0.89 | (42, 61, 328, 297) |
| 2 | Grape__BlackRot | 0.76 | (152, 120, 389, 315) |
| 3 | Grape__Healthy | 0.96 | (25, 15, 410, 425) |
检测结果统计:
- 总检测数:3
- 检测类别数:2
- 主要病害:Grape__BlackRot
2. 文件夹批量检测
操作流程:将待检测的多张图片放入同一文件夹 → 点击📂 文件夹检测选择目标文件夹 → 系统批量推理所有图片,自动将检测结果保存至输出目录,并生成汇总检测报告。
批量检测适合对大量田间采集的葡萄叶样本进行统一分析,可大幅节省人工逐个检测的时间成本。
3. 视频检测
操作流程:点击🎬 视频检测选择本地葡萄叶病害采集视频 → 系统逐帧进行推理,实时在界面显示检测结果并绘制检测框与类别信息,支持暂停、停止检测操作。
4. 实时摄像头检测
操作流程:连接本地摄像头后,点击📹 实时摄像头 → 系统实时读取摄像头画面并逐帧检测,可对田间葡萄叶进行实地实时病害检测,点击⏹️ 停止检测即可结束任务。
5. 结果保存
所有检测结果均支持保存:
- 图片检测:点击
💾 保存结果,可将带检测框的结果图片保存至输出目录 - 视频/摄像头检测:系统自动将检测后的视频保存为MP4文件至输出目录
- 批量检测:自动导出包含所有检测结果的CSV报告文件
二、环境搭建
本项目基于PyTorch框架开发,提供两种环境搭建方式:
1. pip安装方式
首先手动安装PyTorch和torchvision,可从官方下载对应版本的whl包:
- torch下载地址:https://download.pytorch.org/whl/torch/
- torchvision下载地址:https://download.pytorch.org/whl/torchvision/
安装完成PyTorch后,切换至项目根目录,执行以下命令安装其余依赖:
pip install -r requirements.txt
项目依赖包清单如下:
aiohttp==3.14.1
albumentations==2.0.8
ax==0.52.0
clip==0.2.0
comet_ml==3.58.3
ConfigSpace==1.2.2
coremltools==9.0
dvclive==3.49.1
dx_com==2.3.0
faster_coco_eval==1.7.2
Flask==3.1.3
hub_sdk==0.0.24
ipython==8.12.3
lap==0.5.13
matplotlib==3.11.0
mct_quantizers==1.7.0
MNN==3.6.0
mobileclip==0.0.1
model_compression_toolkit==2.6.0
moviepy==2.2.1
2. Conda安装方式
若使用Anaconda管理环境,可通过以下步骤创建并配置环境:
# 创建新的Python环境
conda create -n grape_disease python=3.10
conda activate grape_disease
# 安装PyTorch(以CUDA 11.8为例)
conda install pytorch torchvision pytorch-cuda=11.8 -c pytorch -c nvidia
# 安装其余依赖
pip install -r requirements.txt
三、模型训练、评估、预测
数据集上传说明
1. 数据集格式要求
本项目采用标准YOLO数据集格式,目录结构如下:
grape_disease_dataset/
├── images/
│ ├── train/ # 训练集图片
│ │ ├── img1.jpg
│ │ ├── img2.jpg
│ │ └── ...
│ ├── val/ # 验证集图片
│ │ ├── img3.jpg
│ │ └── ...
│ └── test/ # 测试集图片(可选)
│ ├── img4.jpg
│ └── ...
└── labels/
├── train/ # 训练集标签
│ ├── img1.txt
│ ├── img2.txt
│ └── ...
├── val/ # 验证集标签
│ ├── img3.txt
│ └── ...
└── test/ # 测试集标签(可选)
├── img4.txt
└── ...
2. YOLO格式标签说明
YOLO格式标签为每张图片对应一个同名TXT文件,每一行表示一个目标标注,格式为:
<class_id> <x_center> <y_center> <width> <height>
所有坐标均为归一化坐标(取值范围0~1),示例:
0 0.428 0.357 0.512 0.468
2 0.125 0.214 0.236 0.389
转换公式:
x_center = (xmin + xmax) / (2 * image_width)y_center = (ymin + ymax) / (2 * image_height)width = (xmax - xmin) / image_widthheight = (ymax - ymin) / image_height
3. 从VOC格式转换(XML转YOLO TXT)
若数据集标注为VOC格式(XML文件),可使用项目提供的xml2txt.py脚本完成格式转换,完整代码如下:
import os
import xml.etree.ElementTree as ET
# 定义类别顺序,对应本项目葡萄叶病害类别
categories = ['Grape__BlackRot', 'Grape__Esca', 'Grape__Healthy', 'Grape__LeafBlight']
category_to_index = {category: index for index, category in enumerate(categories)}
# 定义输入文件夹和输出文件夹,替换为实际路径
input_folder = r'./VOCData/Annotations' # XML文件夹路径
output_folder = r'./dataset/labels' # 输出TXT文件夹路径
# 确保输出文件夹存在
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)
# 存储标签内容
label_lines = []
# 遍历XML中的object标签
for obj in root.findall('object'):
name = obj.find('name').text
if name in category_to_index:
category_index = category_to_index[name]
else:
continue # 若name不在指定类别中,跳过该object
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
label_lines.append(f"{category_index} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}")
# 保存标签文件
txt_name = os.path.splitext(filename)[0] + '.txt'
txt_path = os.path.join(output_folder, txt_name)
with open(txt_path, 'w') as f:
f.write('\n'.join(label_lines))
print("格式转换完成!所有标签已保存到输出目录。")
4. 数据集划分脚本
格式转换完成后,使用SplitDataset.py将数据集划分为训练集、验证集和测试集,默认比例为8:1:1,完整代码如下:
import os
import shutil
import random
# 设置随机种子保证划分可复现
random.seed(42)
def split_data(image_root, label_root, output_root, train_rate=0.8, val_rate=0.1, test_rate=0.1):
# 获取所有图片和标签文件名
images = os.listdir(image_root)
labels = os.listdir(label_root)
# 匹配图片和标签(通过文件名前缀匹配)
images_no_ext = {os.path.splitext(img)[0]: img for img in images}
labels_no_ext = {os.path.splitext(lbl)[0]: lbl for lbl in labels}
# 只保留同时有图片和标签的数据
matched_data = [
(img_id, images_no_ext[img_id], labels_no_ext[img_id])
for img_id in images_no_ext if img_id in labels_no_ext
]
# 输出未匹配提示
unmatched_images = [img for img in images_no_ext if img not in labels_no_ext]
unmatched_labels = [lbl for lbl in labels_no_ext if lbl not in images_no_ext]
if unmatched_images:
print("未匹配标签的图片:")
for img in unmatched_images:
print(f" {images_no_ext[img]}")
if unmatched_labels:
print("未匹配图片的标签:")
for lbl in unmatched_labels:
print(f" {labels_no_ext[lbl]}")
# 打乱数据顺序
random.shuffle(matched_data)
total = len(matched_data)
# 划分数据集
train_end = int(train_rate * total)
val_end = train_end + int(val_rate * total)
train_data = matched_data[:train_end]
val_data = matched_data[train_end:val_end]
test_data = matched_data[val_end:]
# 处理训练集
for img_id, img_file, label_file in train_data:
old_img_path = os.path.join(image_root, img_file)
old_label_path = os.path.join(label_root, label_file)
new_img_dir = os.path.join(output_root, 'train', 'images')
new_label_dir = os.path.join(output_root, '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_id, img_file, label_file in val_data:
old_img_path = os.path.join(image_root, img_file)
old_label_path = os.path.join(label_root, label_file)
new_img_dir = os.path.join(output_root, 'val', 'images')
new_label_dir = os.path.join(output_root, '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_id, img_file, label_file in test_data:
old_img_path = os.path.join(image_root, img_file)
old_label_path = os.path.join(label_root, label_file)
new_img_dir = os.path.join(output_root, 'test', 'images')
new_label_dir = os.path.join(output_root, '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__':
# 修改为实际路径
image_root = r'./VOCData/JPEGImages'
label_root = r'./VOCData/labels'
output_root = r'./VOCData/VOdevkit'
split_data(image_root, label_root, output_root)
5. 配置数据集yaml文件
划分完成后,创建数据集配置yaml文件(本项目为dataset.yaml),内容如下:
# 数据集根路径
path: ./VOCData/VOdevkit # 替换为你的数据集实际根目录
# 训练/验证/测试集相对路径
train: train/images # 训练集图片路径
val: val/images # 验证集图片路径
test: test/images # 测试集图片路径(可选)
# 类别数量
nc: 4
# 类别名称
names:
0: Grape__BlackRot
1: Grape__Esca
2: Grape__Healthy
3: Grape__LeafBlight
模型训练
数据集准备完成后,执行训练脚本train.py,核心代码如下:
from ultralytics import YOLO
if __name__ == '__main__':
# 加载YOLO26n预训练模型,追求更高精度可更换为yolo26s.pt
model = YOLO('yolo26n.pt')
# 开始训练
results = model.train(
data=r'./VOCData/VOdevkit/dataset.yaml',
epochs=50, # 最大训练轮数,配合早停自动终止
patience=10, # 连续10轮验证集指标无提升则触发早停
batch=24, # 批次大小:12G显存建议设为24,8G显存建议改为16
imgsz=512, # 输入图片尺寸
workers=4, # 数据加载线程数:Windows建议4,Linux建议8
device=0, # GPU设备编号,CPU训练可改为device='cpu'
optimizer='SGD', # 优化器选择,SGD泛化性更优
amp=True, # 开启自动混合精度训练,减少显存占用
cache='disk', # 启用磁盘缓存数据,避免内存溢出
save_period=11, # 每11轮保存一次权重文件
scale=0.3, # 多尺度训练增强,提升模型鲁棒性
rect=False, # 关闭矩形训练,配合多尺度训练使用
mosaic=1.0, # 开启Mosaic数据增强
)
关键训练参数说明:
| 参数 | 说明 | 推荐值 |
|---|---|---|
| epochs | 最大训练轮数 | 50 |
| patience | 早停触发阈值(连续N轮验证集指标无提升则终止训练) | 10 |
| batch | 批次大小(需根据显存容量调整) | 16~24 |
| imgsz | 输入图片统一尺寸 | 512 |
| device | 训练设备(GPU编号或CPU) | 0(GPU)/ ‘cpu’(CPU) |
| amp | 是否开启自动混合精度训练(可减少显存占用) | True |
| cache | 数据集缓存方式(disk为磁盘缓存,可避免内存不足) | ‘disk’ |
执行训练命令:
python train.py
模型评估
训练完成后,使用val.py对最优权重进行评估,核心代码如下:
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")
# 计算平均精确率和召回率
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"{'类别':<16}{'Precision':<12}{'Recall':<12}{'AP50':<12}")
content.append("-"*60)
class_names = ['Grape__BlackRot', 'Grape__Esca', 'Grape__Healthy', 'Grape__LeafBlight']
for i, name in enumerate(class_names):
ap50 = metrics.box.ap50[i]
p = metrics.box.p[i]
r = metrics.box.r[i]
content.append(f"{name:<16}{p:.4f}{'':<4}{r:.4f}{'':<4}{ap50:.4f}")
# 保存评估结果至文件
with open("val_result.txt", "w", encoding="utf-8") as f:
f.write("\n".join(content))
# 打印评估结果
print("\n".join(content))
训练结果默认保存在runs/detect/train/目录下,核心输出文件说明:
| 文件/目录 | 说明 |
|---|---|
weights/best.pt |
验证集表现最优的权重文件 |
weights/last.pt |
最后一轮训练的权重文件 |
weights/epoch*.pt |
指定训练轮次的权重文件 |
args.yaml |
训练参数配置记录 |
results.csv |
每轮训练的指标数据记录 |
results.png |
训练损失曲线、指标变化曲线图 |
confusion_matrix.png |
混淆矩阵可视化图 |
confusion_matrix_normalized.png |
归一化混淆矩阵可视化图 |
BoxPR_curve.png |
精确率-召回率(PR)曲线图 |
BoxF1_curve.png |
F1值变化曲线图 |
labels.jpg |
训练集标签分布可视化图 |
train_batch*.jpg |
训练批次样本数据增强效果可视化图 |
val_batch*_labels.jpg |
验证集标注数据可视化图 |
val_batch*_pred.jpg |
验证集预测结果与标注对比可视化图 |




执行评估命令:
python val.py
模型预测
本项目支持多种预测方式,单张图片预测核心代码如下:
from ultralytics import YOLO
import os
# 加载训练好的最优模型
root = os.getcwd()
model = YOLO(rf'{root}/runs/detect/train/weights/best.pt')
# 设置待检测图片路径
source = r'./img_video/test_imgs/test_grape.jpg'
# 执行推理
results = model.predict(source, save=True, conf=0.45, iou=0.25)
# 弹窗展示检测结果
results[0].show()
# 保存检测结果到指定路径
results[0].save(filename=r"./results/test_result.jpg")
执行预测命令:
python predict.py
除单张图片预测外,系统还支持文件夹批量预测、视频预测、摄像头实时预测,所有功能已集成至UI界面,可直接通过界面操作使用。
四、项目目录结构
基于YOLO26葡萄叶病害检测系统/
├── README.md # 项目说明文档
├── requirements.txt # Python依赖列表
├── yolo26n.pt # YOLO26n预训练权重
├── train.py # 模型训练入口脚本
├── predict.py # 模型推理预测脚本
├── val.py # 模型验证评估脚本
├── UI/ # 界面相关代码
│ ├── web.py # Flask Web后端主程序
│ ├── GUI.py # PyQt5 GUI界面逻辑
│ ├── config.yaml # UI全局配置文件
│ ├── user.txt # 用户登录信息存储文件
│ ├── templates/
│ │ ├── 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 # VOC标注类别统计脚本
│ ├── xml2txt.py # VOC XML转YOLO TXT格式脚本
│ ├── pic to mp4.py # 图片转视频脚本
│ └── VOdevkit/
│ ├── dataset.yaml # 数据集配置文件
│ └── 数据集单独下载.txt # 数据集下载说明文件
└── ultralytics/ # YOLO框架核心源码目录
├── cfg/ # 模型和数据集配置文件
├── data/ # 数据加载与增强模块
├── engine/ # 训练/预测/验证引擎模块
└── models/ # 模型定义模块
五、项目README摘要
本项目是基于YOLO26目标检测模型开发的葡萄叶病害检测系统,核心特性如下:
- 支持4类葡萄叶病害识别:Black Rot、Esca、Healthy、Leaf Blight
- 提供PyQt5 GUI桌面端和Flask Web网页端双界面实现
- 支持5种检测模式:单张图片检测、文件夹批量检测、视频检测、实时摄像头检测、结果保存导出
- 提供完整的数据处理脚本、训练代码、评估代码,支持用户基于自有数据集重新训练
- 所有UI文字、参数均可通过
config.yaml全局配置,无需修改代码即可自定义系统
项目启动方式:
- 启动GUI桌面端:
cd UI && python GUI.py - 启动Web网页端:
cd UI && python web.py
文末互动区
如果您觉得本项目有帮助,欢迎点击【分享】【推荐】支持我们!
如需获取完整项目代码与数据集, 回复**「基于YOLO26葡萄叶病害」**获取。
更多推荐




所有评论(0)