简介这份资源面向具备Python与PyTorch基础、希望上手番茄叶片病害目标检测的开发者与学习者提供从数据处理到模型训练再到可视化识别的完整代码链路。压缩包共1470个文件约40.55MB其中730张jpg为番茄叶片病害图像样本358个xml与363个txt分别对应标注文件与YOLO格式标签另有3个py脚本、3个pt权重、3个yaml配置及png、csv等训练日志与评估图表覆盖数据、训练、推理全流程。已有109人学习下载。资源核心价值在于开箱即用的工程结构01脚本负责将数据集转为YOLO格式并生成train.txt、val.txt与data.yaml02脚本用于模型训练03脚本提供PyQt可视化界面点击加载图片与检测按钮即可完成识别若仅调用已训练模型直接运行03pyqt.py即可适合快速验证与二次开发。1. 番茄叶片病害检测这套 Python 深度学习资源到底能省掉多少造轮子的时间去年帮一个做智慧农业的朋友看大棚巡检方案他手里攒了三千多张番茄叶片的手机照片想做个能自动框出病斑、区分早疫和晚疫的检测模型。他一开始打算从零标注、从零写训练脚本结果两周过去连数据格式都没统一。后来我给他扔了一套现成的番茄叶片病害目标检测资源包含数据集和代码他三天就跑通了第一版推理。这套资源解决的核心问题很具体把「番茄叶片 病害区域」这个垂直场景的数据集、标注格式、训练脚本和推理入口一次性配齐省掉的是数据清洗、格式转换和训练框架搭建这三块最耗时的脏活。它适合两类人一类是刚接触 Python 深度学习、想拿一个真实农业场景练手目标检测的入门者另一类是做农业物联网或植保巡检、需要快速验证检测方案可行性的从业者。关键词 python yolo 目标检测 在这里不是标签而是这套资源的技术底座——用 Python 写训练和推理用 YOLO 系列做检测头数据集直接对应番茄叶片病害。2. 数据集结构与 YOLO 标注格式先看懂再动手2.1 番茄叶片数据集的目录长什么样拿到一个含数据集和代码的压缩包第一件事不是急着跑 train.py而是把目录结构摸清楚。常见做法是数据集按 images 和 labels 分开放images 下再分 train、val、testlabels 下保持同名对应。番茄叶片病害这类资源图片格式多为 jpg 或 png标注文件是 YOLO 格式的 txt每行五个字段类别索引、归一化中心 x、归一化中心 y、归一化宽、归一化高。下面是我一般会先跑的目录扫描脚本用来确认文件数量和配对情况。import os from pathlib import Path # 数据集根目录按实际解压路径改 root Path(tomato_leaf_dataset) for split in [train, val, test]: img_dir root / images / split lbl_dir root / labels / split imgs list(img_dir.glob(*.jpg)) list(img_dir.glob(*.png)) lbls list(lbl_dir.glob(*.txt)) # 检查图片和标注是否一一对应 img_stems {p.stem for p in imgs} lbl_stems {p.stem for p in lbls} only_img img_stems - lbl_stems only_lbl lbl_stems - img_stems print(f{split}: 图片 {len(imgs)} 张, 标注 {len(lbls)} 个, 缺标注 {len(only_img)}, 缺图片 {len(only_lbl)})这段脚本的逻辑很直白分别统计每个 split 下的图片和标注数量再用集合差找出不配对的样本。参数上只需要改 root 指向解压后的数据集根目录。如果 only_img 不为零说明有图片没标注训练时要么剔除要么补标如果 only_lbl 不为零说明标注文件是孤儿直接删掉即可。这一步不做后面训练报「找不到标签」的错会浪费很多时间。2.2 类别索引和 data.yaml 的对应关系YOLO 训练依赖一个 data.yaml 文件里面写清楚 train、val 路径和类别名称列表。番茄叶片病害常见类别包括早疫病、晚疫病、叶霉病、健康叶片等具体以资源包里的 classes.txt 或 data.yaml 为准。这里有个容易翻车的地方标注 txt 里的类别索引是从 0 开始的整数而 data.yaml 里 names 列表的顺序必须和索引严格对应。我见过有人把 names 写成字典顺序结果模型把早疫病识别成健康叶片推理结果全乱。下面是一个标准的 data.yaml 写法。# data.yaml train: ./tomato_leaf_dataset/images/train val: ./tomato_leaf_dataset/images/val test: ./tomato_leaf_dataset/images/test nc: 4 # 类别数量按实际改 names: 0: 早疫病 1: 晚疫病 2: 叶霉病 3: 健康叶片参数说明nc 是类别数必须和 names 长度一致train/val/test 路径可以是相对路径也可以是绝对路径相对路径以训练脚本执行目录为基准。如果资源包里已经带了 data.yaml先打开核对一遍别直接信。类别名用中文还是英文不影响训练但推理后处理时要注意编码一致避免显示乱码。2.3 标注质量快速抽检别让脏数据毁掉训练数据集再大标注质量不行也是白搭。我一般会抽 20 张图做可视化检查看框是否贴合病斑、有没有漏标、有没有把整片叶子框成一个大框。下面这段代码用 OpenCV 把标注画回原图存到临时目录肉眼过一遍。import cv2 from pathlib import Path root Path(tomato_leaf_dataset) img_dir root / images / train lbl_dir root / labels / train out_dir Path(check_vis) out_dir.mkdir(exist_okTrue) # 只抽前20张避免全量可视化太慢 for img_path in sorted(img_dir.glob(*.jpg))[:20]: img cv2.imread(str(img_path)) h, w img.shape[:2] lbl_path lbl_dir / (img_path.stem .txt) if not lbl_path.exists(): continue with open(lbl_path) as f: for line in f: cls, cx, cy, bw, bh map(float, line.split()) # YOLO 归一化坐标转像素坐标 x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cls)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(str(out_dir / img_path.name), img) print(可视化结果已存到 check_vis 目录)逻辑说明读取每张图的标注文件把归一化坐标还原成像素坐标画框并标类别号。参数上只改 root 和抽样数量。重点看三种情况框明显偏大或偏小、同一病斑被重复标注、健康叶片被误标成病害。发现超过 10% 的样本有问题建议先清洗再训练否则模型学到的就是错误边界。3. 训练脚本拆解从 train.py 到超参数怎么调3.1 训练入口和关键参数含义资源包里的训练脚本通常基于 ultralytics 的 YOLO 接口常见写法是 from ultralytics import YOLO然后 model.train()。但直接跑默认参数在番茄叶片这种小目标密集场景下效果往往一般需要针对性调几个参数。下面是一个我常用的训练配置基于 YOLOv8 风格接口YOLOv5 或更新版本思路类似。from ultralytics import YOLO # 加载预训练权重没有预训练权重就从 yaml 初始化 model YOLO(yolov8n.pt) model.train( datadata.yaml, # 数据集配置文件 epochs100, # 训练轮数小数据集可适当增加 imgsz640, # 输入尺寸病斑小可提到 800 batch16, # 批大小显存不够就降到 8 lr00.01, # 初始学习率 lrf0.01, # 最终学习率系数 patience20, # 早停耐心值20轮没提升就停 device0, # 用 GPU 就写 0CPU 写 cpu workers4, # 数据加载线程数 projectruns/train, # 训练结果保存目录 nametomato_exp1 # 实验名 )参数逐个说epochs 不是越大越好番茄叶片数据集通常几千张100 轮足够再大容易过拟合imgsz 默认 640如果病斑在图中占比很小提到 800 或 1024 能提升小目标召回但显存占用会明显上升batch 根据显存调16 是 8G 显存的保守值lr0 初始学习率 0.01 是 YOLO 系列常用值如果 loss 震荡厉害可以降到 0.001patience 是早停防止无效训练。device 写 0 表示第一块 GPU多卡用 0,1。workers 在 Windows 下建议设 0 或 2设大了容易报共享内存错误。3.2 训练过程看什么指标训练启动后控制台会输出每轮的 box_loss、cls_loss、dfl_loss 和 mAP。box_loss 是边界框回归损失cls_loss 是分类损失dfl_loss 是分布焦点损失。这三个 loss 整体趋势应该是下降的如果某个 loss 一直不降或者反弹说明对应部分有问题。mAP50 和 mAP50-95 是评估指标mAP50 表示 IoU 阈值 0.5 时的平均精度番茄叶片病害检测一般能到 0.85 以上算不错。我一般会重点看 mAP50-95它更严格能反映框的精准度。如果 mAP50 高但 mAP50-95 低说明框大致位置对但不够贴合可以检查标注质量或调整 imgsz。训练结束后runs/train/tomato_exp1 目录下会有 weights 文件夹里面 best.pt 是验证集上表现最好的权重last.pt 是最后一轮权重。推理优先用 best.pt。results.csv 记录了每轮指标可以用 pandas 画曲线看趋势。confusion_matrix.png 能直观看到哪些类别容易混淆比如早疫病和晚疫病如果互相误判多说明这两类病斑特征接近需要更多样本或更强 backbone。3.3 推理脚本和结果后处理训练完拿到 best.pt下一步是写推理脚本对单张图或整个文件夹做检测。下面这段代码支持单图和批量推理并把结果保存下来。from ultralytics import YOLO from pathlib import Path model YOLO(runs/train/tomato_exp1/weights/best.pt) # 单张推理 results model.predict( sourcetest_leaf.jpg, conf0.25, # 置信度阈值低于此值的框丢弃 iou0.45, # NMS IoU 阈值控制重叠框合并 imgsz640, saveTrue, # 保存带框图片 save_txtTrue # 保存检测结果 txt ) # 批量推理整个文件夹 model.predict( sourcetomato_leaf_dataset/images/test, conf0.25, iou0.45, saveTrue, projectruns/predict, namebatch_test )参数说明conf 是置信度阈值调低会检出更多框但误检增加调高则漏检增加番茄叶片病害建议从 0.25 起步试iou 是 NMS 的 IoU 阈值病斑密集时适当调低到 0.4 能减少框重叠save_txt 会输出每个框的类别和坐标方便后续统计病害面积占比。推理结果默认存在 runs/detect 下批量推理会按文件名逐个保存。后处理阶段我一般会统计每张图的病害类别分布和病斑总面积占比作为大棚巡检的量化指标。比如某张图检出三个早疫病框总面积占叶片区域 15%就可以触发预警。这部分逻辑用 OpenCV 读原图和检测 txt 就能算不复杂但很实用。4. 避坑与排查番茄叶片检测最容易翻车的五个地方4.1 训练 loss 不降反升现象训练前几轮 loss 正常下降后面突然飙升或者震荡剧烈。原因通常是学习率过大或者数据集中有大量错误标注导致梯度方向混乱。解决先把 lr0 从 0.01 降到 0.001 试一轮如果还不行用 2.3 节的可视化脚本抽检标注重点看有没有框到背景或框错类别的样本。另外检查 batch 是否过大小数据集用大 batch 容易导致泛化差。4.2 推理时类别名显示乱码现象推理结果图上类别标签显示成方框或问号。原因是 OpenCV 的 putText 不支持中文而 data.yaml 里 names 写的是中文。解决要么把 names 改成英文要么在推理后处理时用 PIL 的 ImageDraw 配合中文字体渲染。我一般建议数据集标注阶段就用英文类别名显示层再做中文映射避免训练和推理编码不一致。4.3 显存不足报 CUDA out of memory现象训练启动几秒后报显存溢出。原因可能是 imgsz 设太大、batch 设太大或者 workers 过多导致数据加载占用显存。解决按 imgsz、batch、workers 的顺序逐个降。640 降到 512batch 16 降到 8workers 4 降到 2。如果还不行检查是不是同时跑了多个训练任务。另外 YOLO 的 AMP 混合精度默认开启如果显卡不支持可以手动关掉。4.4 验证集 mAP 很高但实际推理效果差现象训练日志里 mAP50 到 0.9但拿新拍的叶片照片推理漏检严重。原因是验证集和训练集同分布而实际照片的光照、角度、背景和数据集差异大。解决从实际场景补拍一批图标注后加入训练集重新训练或者在推理前做图像增强比如直方图均衡化、白平衡校正缩小域差距。这个问题在农业场景特别常见因为大棚光照变化大。4.5 标注文件坐标越界现象训练时提示坐标超出 0-1 范围或者可视化时框跑到图外。原因是标注时用了绝对坐标没归一化或者归一化时除错了尺寸。解决写个校验脚本遍历所有标注文件检查每个字段是否在 0 到 1 之间宽高是否大于 0。发现越界的样本要么重新标注要么直接剔除。这个检查放在训练前做比训练中途报错再回头查省事得多。5. 进阶技巧用检测结果做病害面积占比统计训练和推理跑通之后这套资源真正的价值在于把检测框转成可量化的植保指标。我一般会加一步后处理读原图和检测 txt算病斑总面积占叶片区域的比例再按阈值分级预警。下面这段代码演示怎么从推理结果算占比。import cv2 from pathlib import Path img_path Path(test_leaf.jpg) txt_path Path(runs/detect/predict/labels/test_leaf.txt) img cv2.imread(str(img_path)) h, w img.shape[:2] leaf_area h * w # 简化处理实际可用分割模型抠出叶片区域 disease_area 0 with open(txt_path) as f: for line in f: cls, cx, cy, bw, bh map(float, line.split()) # 框面积换算成像素面积 box_area (bw * w) * (bh * h) disease_area box_area ratio disease_area / leaf_area print(f病斑面积占比: {ratio:.2%}) if ratio 0.15: print(预警病害面积超过 15%建议处理) elif ratio 0.05: print(关注病害面积超过 5%持续观察) else: print(正常病害面积较低)逻辑说明读取检测 txt 里每个框的归一化宽高乘以图像宽高得到像素面积累加后除以叶片区域面积。参数上 leaf_area 这里用整图面积简化更准的做法是用分割模型或颜色阈值抠出叶片实际区域。阈值 15% 和 5% 是我在几个大棚项目里用的经验值具体按作物品种和病害类型调整。这段代码可以批量跑整个测试集输出每张图的占比和预警等级直接对接巡检报表。从那以后我每次拿到新的检测数据集都强制先跑一遍标注可视化抽检和坐标越界校验再开始训练。这两步花不了十分钟但能省掉后面几小时的排查。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?