ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

番茄病害目标检测数据集构建实战指南

番茄病害目标检测数据集构建实战指南 简介本资源是一套专为农业智能识别场景设计的番茄病害目标检测数据集面向深度学习初学者、计算机视觉研究者及智慧农业项目开发者助力快速构建番茄斑萎病毒、早疫病、赤霉病与健康植株四类病害的自动化识别模型。数据集共2083张高质量田间采集图像已按YOLO与VOC双格式组织包含1999个txt标签文件对应YOLO格式边界框坐标、1个完整类别定义yaml配置文件以及配套xml标注训练/验证/测试集划分完备开箱即用于YOLOv5至YOLOv10、Faster R-CNN、SSD等主流检测框架。压缩包总计2000个文件大小139.11MB结构规整、标注一致、类别平衡显著降低数据预处理门槛。目前已有368人学习下载适合开展课程设计、科研实验或农业AI落地验证可直接支撑模型训练、评估与部署全流程。1. 番茄病害识别数据集目标检测不是拿来就能训的“标准图库”而是要亲手筛、标、验的农田黑匣子你下载了一个叫“番茄病害识别数据集目标检测”的压缩包解压后看到 train/val/test 三文件夹、images 和 labels 两目录、还有个 README.md ——恭喜你刚踩进农业视觉落地的第一个坑它根本不是开箱即用的 YOLO-ready 数据集而是一份原始田间影像的粗加工半成品。真实场景里同一张图常含多类病害早疫病叶霉病共存、病斑尺度跨度极大从像素级斑点到整片萎蔫叶片、光照不均导致青枯病斑在阴影区几乎不可见更别说遮挡、重叠、模糊、反光这些“农田玄学”。这个标题指向的不是某个特定公开数据集如 PlantVillage 的分类版而是一类面向实际部署的目标检测任务所必需的数据资产构建过程从田间采集、病害界定、框标注规范、到适配 YOLOv8/v10 或 RT-DETR 训练 pipeline 的全流程。适合正在做智慧农技系统开发、高校农业AI课题、或农企数字化团队中负责模型落地的工程师——你不需要从零写检测头但必须亲手把“番茄叶子上的病”变成模型能学懂的坐标类别置信度。2. 为什么必须自己构建/清洗番茄病害检测的三大数据硬伤2.1 病害定义模糊同一张图三个农艺师给出三种标注结果番茄常见病害早疫病、晚疫病、叶霉病、灰霉病、青枯病、病毒病在田间表现高度相似早疫病与叶霉病都呈褐色轮纹斑灰霉病在高湿下与叶霉病霉层混淆病毒病花叶症状易被误标为营养缺乏。公开数据集常依赖单一专家标注但实际部署时模型需应对跨区域农技员的判别差异。解决方案不是追求“绝对正确”而是建立可复现的标注SOP明确病害判定依据如早疫病斑边缘有黄色晕圈叶霉病背面有紫灰色绒毛状霉层要求标注员提供病害部位照片正/背/侧三视角对争议样本组织3人交叉标注仅当2人以上一致才保留。提示不要用 PlantVillage 分类数据集直接转目标检测——其图像多为实验室单叶拍摄无茎秆遮挡、无自然光照变化、无多病共存迁移到田间视频流时 mAP 直降 40%。2.2 框标注失真小病斑、粘连病斑、不规则病斑的“框不住”困境目标检测要求 bounding box 紧贴目标但番茄病斑天然不规则小病斑16×16 像素YOLOv8 默认 anchor 尺寸如 32×32无法有效回归易漏检粘连病斑如叶面密集褐斑人工框常合并为一个大框但模型需区分独立病灶以支持精准施药不规则病斑沿叶脉蔓延的青枯病矩形框覆盖大量健康组织引入强噪声。实操对策小病斑启用 YOLOv8 的mosaic: falsescale: 0.5预处理放大病斑区域粘连病斑强制拆分为多个最小外接矩形代码见 2.3不规则病斑接受“框不准但类别准”的妥协重点保证类别标签一致性后续用分割模型补位。2.3 光照与背景干扰大棚 vs 露地、晴天 vs 阴天的域偏移黑洞同一病害在不同光照下颜色差异巨大大棚内白炽灯下灰霉病霉层呈灰白色露地正午阳光下同一霉层泛黄绿色阴天散射光下早疫病斑对比度极低。更致命的是背景干扰藤蔓缠绕、土壤反光、水滴镜面反射、相邻植株遮挡——这些在 ImageNet 风格数据集中不存在却是田间检测失败主因。数据增强必须针对性设计使用albumentations替代默认augment.py添加RandomSunFlare模拟大棚顶膜反光、MotionBlur模拟手持拍摄抖动、HueSaturationValue±30 色相偏移覆盖光照变异背景替换用真实大棚/露地背景图非纯色合成训练图比例控制在 30% 样本内避免过拟合背景纹理。3. 从 raw 图像到 YOLOv8 可训格式四步清洗流水线3.1 图像预筛剔除无效帧的 bash 脚本田间采集的视频抽帧常含大量废片全黑夜间、全白镜头直对太阳、严重模糊对焦失败、纯土/纯茎无叶。手动筛选效率极低用 OpenCV 快速过滤#!/bin/bash # filter_invalid.sh for img in *.jpg; do # 计算图像亮度均值和方差 mean$(ffmpeg -i $img -vf crop100:100:100:100,avgblur2 -vstats -f null /dev/null 21 | \ grep mean: | awk {print $3} | sed s/,//) var$(ffmpeg -i $img -vf crop100:100:100:100,avgblur2 -vstats -f null /dev/null 21 | \ grep variance: | awk {print $3} | sed s/,//) # 亮度均值 15太暗或 230过曝或方差 5无纹理 if (( $(echo $mean 15 || $mean 230 || $var 5 | bc -l) )); then echo Removing $img (mean$mean, var$var) rm $img fi done逻辑说明crop100:100:100:100截取中心区域规避边缘畸变avgblur2减少噪点干扰统计vstats输出亮度统计bc -l支持浮点比较参数可调大棚环境可放宽mean 230限制反光强露地则收紧var 5需更多纹理。3.2 病斑拆框将粘连病斑分解为独立 bounding box 的 Python 脚本针对标注工具如 CVAT导出的合并框用 OpenCV 找连通域并生成最小外接矩形# split_adhesion_boxes.py import cv2 import numpy as np import json from pathlib import Path def split_connected_regions(mask_path: str, original_img: np.ndarray) - list: 输入二值掩膜输出多个最小外接矩形 [x,y,w,h] mask cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE) # 形态学闭运算连接微小断裂 kernel np.ones((3,3), np.uint8) mask cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 找连通域 num_labels, labels, stats, centroids cv2.connectedComponentsWithStats(mask, connectivity8) boxes [] for i in range(1, num_labels): # 跳过背景label 0 x, y, w, h, area stats[i] # 过滤小区域50像素和细长区域w/h 10 or h/w 10 if area 50 or w/h 10 or h/w 10: continue # 转换为 YOLO 格式中心点宽高归一化 h_img, w_img original_img.shape[:2] x_center (x w/2) / w_img y_center (y h/2) / h_img width_norm w / w_img height_norm h / h_img boxes.append([x_center, y_center, width_norm, height_norm]) return boxes # 示例处理单张图 img_path images/tomato_001.jpg mask_path masks/tomato_001.png # 需提前用标注工具生成病斑掩膜 img cv2.imread(img_path) boxes split_connected_regions(mask_path, img) # 写入 YOLO labels 文件 label_path Path(labels) / tomato_001.txt with open(label_path, w) as f: for box in boxes: # 假设所有病斑类别 ID0早疫病 f.write(f0 {box[0]:.6f} {box[1]:.6f} {box[2]:.6f} {box[3]:.6f}\n)参数说明area 50剔除噪点可根据相机分辨率调整1080p 下建议 30~100w/h 10过滤茎秆等细长干扰物morphologyEx(..., MORPH_CLOSE)修复病斑内部孔洞避免过分割关键教训此脚本需配合高质量掩膜——若原始标注框粗糙先用 SAM 模型生成初始掩膜再优化。3.3 标签映射与平衡按病害类型重采样避免“灰霉病统治一切”实际田间数据中灰霉病样本常占 60%而青枯病不足 5%。直接训练会导致模型对稀有病害完全失效。不推荐简单过采样引发过拟合而采用类别感知采样# balance_dataset.py from collections import Counter import random import shutil # 统计每类病害出现频次 label_files list(Path(labels).glob(*.txt)) class_counts Counter() for lf in label_files: with open(lf, r) as f: for line in f: cls_id int(line.split()[0]) class_counts[cls_id] 1 # 设定目标最小频次取第二少类别的 1.5 倍 min_target int(sorted(class_counts.values())[1] * 1.5) balanced_files [] for cls_id, count in class_counts.items(): if count min_target: # 足够的类随机选 min_target 个样本 cls_files [lf for lf in label_files if cls_id_in_file(lf, cls_id)] balanced_files.extend(random.sample(cls_files, min_target)) else: # 不足的类全量保留 复制增强加噪声/旋转 cls_files [lf for lf in label_files if cls_id_in_file(lf, cls_id)] balanced_files.extend(cls_files) # 复制增强示例水平翻转 for lf in cls_files[:min_target-count]: new_name lf.stem _flip lf.suffix shutil.copy(lf, Path(labels_balanced) / new_name) # 同步复制图像并翻转 img_path Path(images) / (lf.stem .jpg) img_flip cv2.flip(cv2.imread(str(img_path)), 1) cv2.imwrite(str(Path(images_balanced) / (lf.stem _flip.jpg)), img_flip) print(fBalanced dataset: {len(balanced_files)} files)逻辑说明cls_id_in_file()是自定义函数检查 txt 文件是否含指定类别复制增强仅用于最稀有类别如青枯病且仅限几何变换翻转/旋转禁用色彩扰动避免病征失真血泪经验平衡后务必验证验证集分布——若 val 集某类仍稀缺需从 test 集匀出部分样本补充 val。4. 避坑番茄病害检测数据集构建的 4 个致命翻车点4.1 现象训练 loss 降得快但 val mAP 停在 0.1 不动原因标注工具导出的.txt文件含空行或非数字字符如 CVAT 导出时插入的注释行YOLOv8 加载时静默跳过该样本导致训练集实际样本数远少于预期而验证集正常加载造成 train/val 分布严重失衡。解决在train.py前插入校验脚本# validate_labels.sh for f in labels/*.txt; do if [[ $(wc -l $f) -eq 0 ]] || [[ $(grep -v ^[0-9] $f | wc -l) -gt 0 ]]; then echo Invalid label: $f rm $f fi done4.2 现象模型在测试图上框出“健康叶片”为病害原因标注时未严格区分病害与生理性损伤如日灼斑、肥害斑而这些损伤在形态上与早疫病斑高度相似模型学到的是“褐色斑点病害”的错误先验。解决建立《番茄非病害斑鉴别手册》PDF包含日灼斑叶尖/叶缘规则圆形、肥害斑沿叶脉对称分布、机械损伤边缘锐利无晕圈的高清图例要求所有标注员考前通过 90 分测试。4.3 现象同一张图不同分辨率下检测结果差异巨大1080p 正常480p 全漏原因YOLOv8 默认输入尺寸 640×640但田间图常为 3840×21604K直接 resize 导致小病斑像素化消失而用 letterbox 缩放又使病斑在 padding 区域变形。解决改用--imgsz动态适配对 4K 图--imgsz 1280--rect矩形推理不 pad对手机拍摄图1920×1080--imgsz 960关键参数--rect必须开启否则小目标召回率断崖下跌。4.4 现象导出 ONNX 模型后C 推理结果与 Python 完全不同原因YOLOv8 导出 ONNX 时默认--dynamic开启但 OpenCV DNN 模块不支持动态轴导致输入 tensor shape 解析错误。解决导出时固定尺寸yolo export modelyolov8n.pt formatonnx imgsz640 dynamicFalse并在 C 中严格按1,3,640,640输入预处理必须与 Python 端完全一致BGR→RGB→归一化→CHW。5. 验证你的数据集是否“真可用”三阶质检法5.1 第一阶可视化质检肉眼可判的 3 个硬指标用ultralytics.utils.plotting.plot_images()批量渲染带框图像重点检查检查项合格标准不合格示例框紧贴性病斑边缘与框边界距离 ≤2 像素1080p 下框内含大片健康叶肉或框外漏病斑类别一致性同一病害在不同光照/角度下标签 ID 相同晴天标为 class 0早疫阴天标为 class 1叶霉遮挡处理被茎秆遮挡 50% 的病斑仍标注且框覆盖可见部分完全不标遮挡病斑或框强行拉伸覆盖遮挡物注意此阶段发现 10% 以上样本不合格必须返工重标——别指望模型能“学会”纠错。5.2 第二阶分布质检用代码揪出隐藏偏移运行以下脚本输出各类别在 train/val/test 中的占比及病斑尺寸分布# dataset_stats.py import numpy as np from pathlib import Path import matplotlib.pyplot as plt def analyze_distribution(label_dir: str, img_dir: str): sizes {0:[], 1:[], 2:[]} # 按 class id 存储宽高比 splits {train:0, val:0, test:0} for split in [train, val, test]: label_split Path(label_dir) / split img_split Path(img_dir) / split # 统计各类别数量 for lf in label_split.glob(*.txt): with open(lf, r) as f: for line in f: cls_id int(line.split()[0]) # 解析归一化宽高 _, _, w, h map(float, line.split()[1:]) # 转回像素尺寸需读取对应图像 img_path img_split / (lf.stem .jpg) if img_path.exists(): h_img, w_img cv2.imread(str(img_path)).shape[:2] sizes[cls_id].append((w*w_img) / (h*h_img)) # 宽高比 splits[split] len(list(label_split.glob(*.txt))) # 输出统计 print(Split distribution:, splits) for cls_id, ratios in sizes.items(): if ratios: print(fClass {cls_id} aspect ratio: mean{np.mean(ratios):.2f}, std{np.std(ratios):.2f}) analyze_distribution(datasets/tomato/labels, datasets/tomato/images)解读指南若Class 0早疫宽高比均值 1.8±0.3而Class 1灰霉为 0.6±0.1说明两类病斑形态差异显著模型易区分若train占比 70% 但val中Class 2青枯样本数为 0必须从train中匀出至少 20 张补val后悔药此脚本应在标注完成 20% 时就运行——早发现问题早止损。5.3 第三阶模型反向质检用轻量模型跑一次看它“学到了什么”不训练大模型只用yolov8n.pt在你的数据集上训 10 epoch观察results.csv中metrics/mAP50-95(B)是否 ≥0.3低于此值数据质量大概率有问题confusion_matrix.png中对角线是否明显亮于非对角线若Class 0大量误判为Class 1说明两类标注边界模糊PR_curve.png中Class 2稀有类曲线是否在 recall0.1 时 precision 已跌至 0.2若是证明该类样本质量差或数量不足。我的习惯每次新收一批田间图必跑这 10 epoch 快检——它比人工抽检 100 张更诚实。曾有一次快检 mAP 仅 0.12追查发现是新采购的摄像头自动开启“美颜模式”平滑了病斑纹理关掉后 mAP 拉升至 0.41。希望帮到你。本文还有配套的精品资源点击获取
返回列表