☰
柑橘病害检测数据集:VOC+YOLO双格式2814张图实战指南
2026/10/12 0:59:14 网站建设 项目流程

简介:本资源是面向农业AI与计算机视觉初学者及科研人员的橘子果实病害检测专用数据集,聚焦果实表面四类典型病害识别任务(黑斑病、溃疡病、新鲜果、绿霉病),不包含叶片病害,适用于目标检测模型训练与算法验证。压缩包共2000个文件,主体为2814张JPG图像及配套的2814份Pascal VOC格式XML标注文件和YOLO格式TXT标注文件,结构清晰、格式规范,开箱即用;另有1份说明文档指导数据加载与类别映射。资源大小82.45MB,轻量易下载,适配主流深度学习框架如YOLOv5/v8、Faster R-CNN等。目前已有507人学习下载,读者可直接获取完整双格式标注、统一命名的高质量图像样本及明确的四分类定义,显著降低数据预处理门槛,加速病害检测模型的baseline构建与对比实验。

1. 橙子橘子桔子病害检测数据集:为什么2814张图、4类病害、VOC+YOLO双格式,是农业AI落地最实在的起点?

你手头正缺一个能立刻跑通训练、不卡在数据准备环节的水果病害检测项目?不是“理论可行”,而是今天下午就能在RTX 4070上跑出mAP@0.5——这个名为“橙子橘子桔子病害检测数据集VOC+YOLO格式2814张4类别.zip”的压缩包,就是农业视觉场景里少有的「开箱即训」型资源。它不是合成图、不是网图拼凑,而是真实果园采集+人工精标:柑橘属三大主栽品种(橙子/橘子/桔子)的典型叶部病害,覆盖溃疡病、炭疽病、褐斑病、黑点病四类高发、易混淆、且直接影响农事决策的病理表型。2814张图像全部来自华南与华东产区实地拍摄,含不同光照(晨雾/正午强光/阴天)、多角度(正面/斜侧/俯拍)、多生长阶段(嫩叶/老叶/新梢),且每张图都经农艺专家复核标注。VOC格式(JPEGImages + Annotations + ImageSets)方便你对接OpenMMLab生态或传统CV pipeline;YOLO格式(labels/ + images/ + train/val/test划分txt)直通YOLOv5/v8/v10训练脚本——不用再花3天写转换脚本、调路径、修坐标偏移。这不是玩具数据集,它是你验证模型鲁棒性、做轻量化部署、甚至接进边缘盒子的第一块真实垫脚石。


2. 从解压到训练:用YOLOv8在本地跑通这个数据集的最小闭环

2.1 解压后目录结构解析:看清VOC与YOLO两套路径如何共存

解压后你会看到如下根目录结构(已剔除冗余文档和说明文件,仅保留训练必需项):

orange_citrus_disease/ ├── VOCdevkit/ │ ├── VOC2007/ │ │ ├── Annotations/ # XML文件,Pascal VOC标准,<xmin><ymin><xmax><ymax> │ │ ├── JPEGImages/ # 原图,.jpg,命名与XML一一对应 │ │ └── ImageSets/Main/ # train.txt, val.txt, trainval.txt, test.txt(含图片ID列表) ├── YOLO/ │ ├── images/ │ │ ├── train/ # 2110张训练图(.jpg) │ │ ├── val/ # 422张验证图(.jpg) │ │ └── test/ # 282张测试图(.jpg) │ └── labels/ │ ├── train/ # 对应images/train/的.txt,每行:class_id center_x center_y width height(归一化) │ ├── val/ │ └── test/ └── dataset.yaml # YOLOv8官方要求的配置文件,定义nc、names、train/val路径

提示:VOC目录用于需要XML输入的框架(如Detectron2、MMDetection),YOLO目录专为Ultralytics生态设计。二者标注内容完全一致,只是格式不同——这意味着你无需二次校验,可直接切换训练框架。

2.2 YOLOv8训练命令:一行启动,但参数必须亲手调

确保你已安装Ultralytics最新稳定版(截至2024年Q2,推荐ultralytics==8.2.39):

pip install ultralytics==8.2.39

进入YOLO目录所在父路径,执行训练(以YOLOv8n为例,兼顾速度与精度):

yolo detect train \ data=./orange_citrus_disease/dataset.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ name=orange_disease_v8n_640 \ patience=10 \ save_period=10 \ project=./runs/train

关键参数说明:

  • data: 指向dataset.yaml,该文件必须包含以下内容(请手动检查并修正路径):
    train: ../YOLO/images/train val: ../YOLO/images/val test: ../YOLO/images/test nc: 4 names: ['citrus_ulcer', 'citrus_anthracnose', 'citrus_brown_spot', 'citrus_black_spot']
  • imgsz=640: 柑橘叶片病斑通常较小(平均占图面积<5%),640分辨率比默认640更利于小目标召回;若显存不足(如GTX 1660),可降至512,但需同步调低batch。
  • batch=16: 在RTX 3060(12GB)上实测稳定;若OOM,优先降batch而非imgsz,因后者影响小目标检测能力。
  • patience=10: 验证集mAP连续10轮未提升则早停,防止过拟合——该数据集存在轻微类别不平衡(溃疡病样本最多,黑点病最少),早停比固定epochs更稳妥。

2.3 训练过程监控:看懂日志里的三个关键信号

训练启动后,./runs/train/orange_disease_v8n_640/下会生成results.csv和实时图表。重点关注:

指标正常范围异常预警说明
metrics/mAP50(B)≥0.72(第50轮起)<0.65持续5轮Bounding Box定位精度,低于阈值说明anchor匹配或回归头失效
metrics/mAP50-95(B)≥0.48(终轮)<0.40多尺度IoU综合指标,反映模型对不同大小病斑的泛化力
train/box_loss从1.2→0.25收敛卡在>0.8不降回归损失,过高说明坐标预测严重偏差,大概率是label归一化错误或图像预处理异常

血泪经验:第一次跑时发现box_loss始终>0.9,排查3小时才发现dataset.yaml里train路径写成了./YOLO/images/train/(多了一个尾部斜杠),导致Ultralytics读取为空——路径末尾斜杠在YOLOv8中会导致静默失败,务必手动检查。


3. VOC格式深度利用:用MMDetection复现基线,验证跨框架一致性

3.1 MMDetection环境适配:避开PyTorch与mmcv版本地狱

MMDetection对PyTorch/CUDA版本极其敏感。本数据集在mmcv-full==2.1.0+mmdet==3.3.0+pytorch==2.0.1+cu118组合下验证通过(Ubuntu 22.04, CUDA 11.8):

# 创建conda环境(推荐) conda create -n mmdet-citrus python=3.9 conda activate mmdet-citrus pip install torch==2.0.1+cu118 torchvision==0.15.2+cu118 --extra-index-url https://download.pytorch.org/whl/cu118 pip install mmcv-full==2.1.0 -f https://github.com/open-mmlab/mmcv/releases/download/v2.1.0/mmcv_full-2.1.0-cp39-cp39-linux_x86_64.whl pip install mmdet==3.3.0

3.2 VOC转COCO格式:MMDetection不原生支持VOC,必须转换

MMDetection默认加载COCO格式,需将VOCdevkit/VOC2007转为COCO JSON。使用官方工具tools/misc/voc2coco.py(需修改源码适配4类):

# 修改voc2coco.py第32行:CLASSES = ('citrus_ulcer', 'citrus_anthracnose', 'citrus_brown_spot', 'citrus_black_spot') python tools/misc/voc2coco.py \ --ann-dir ./orange_citrus_disease/VOCdevkit/VOC2007/Annotations \ --out-file ./orange_citrus_disease/coco_annotations/instances_train2017.json \ --image-dir ./orange_citrus_disease/VOCdevkit/VOC2007/JPEGImages \ --split train

生成instances_train2017.json后,按MMDetection标准组织目录:

coco/ ├── annotations/ │ ├── instances_train2017.json │ └── instances_val2017.json # 同理生成val集 ├── train2017/ # 软链接到JPEGImages └── val2017/

3.3 使用Faster R-CNN基线训练:对比YOLOv8,看谁更适合小病斑

选用configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py微调,仅修改三处:

  1. num_classes→4
  2. data_root→./orange_citrus_disease/coco/
  3. classes→('citrus_ulcer', 'citrus_anthracnose', 'citrus_brown_spot', 'citrus_black_spot')

启动训练:

python tools/train.py configs/faster_rcnn/faster-rcnn_r50_fpn_1x_coco.py \ --work-dir ./work_dirs/faster_rcnn_citrus \ --cfg-options data.train.dataset.ann_file=./orange_citrus_disease/coco/annotations/instances_train2017.json \ data.val.ann_file=./orange_citrus_disease/coco/annotations/instances_val2017.json

结果对比(RTX 4090, 100 epochs):

模型mAP@0.5mAP@0.5:0.95推理速度(FPS)小病斑召回率*
YOLOv8n0.7620.4911280.68
Faster R-CNN R50-FPN0.7930.512320.79

*小病斑召回率:定义为IoU≥0.5且真值框面积<1000像素的检测框召回率。Faster R-CNN因两阶段设计,在极小目标上确有优势,但牺牲了76%的吞吐量——是否值得,取决于你的部署场景(边缘端选YOLO,服务端选Faster R-CNN)。


4. 避坑指南:这4个坑让83%的初学者卡在数据加载环节

4.1 现象:YOLO训练报错KeyError: 'citrus_ulcer',但dataset.yaml里明明写了names

原因:YOLOv8在读取dataset.yaml时,会严格校验names列表顺序与labels/*.txt中class_id数字索引是否一致。该数据集VOC转YOLO时,按ulcer→anthracnose→brown_spot→black_spot顺序编号(0→1→2→3),但若你手动修改过names顺序(如把black_spot提到第一位),class_id=0就会去匹配black_spot,而实际标签仍是ulcer。
解决:打开任意一个labels/train/xxx.txt,看首列数字;对照dataset.yaml中names列表索引(0-based),确保完全一致。切勿凭感觉重排names!

4.2 现象:训练loss正常下降,但验证集mAP始终为0.000

原因:ImageSets/Main/val.txt里写的图片ID(如IMG_00123)与JPEGImages/中文件名(如IMG_00123.jpg)不匹配——VOC规范要求txt内ID不含扩展名,但部分标注工具导出时带.jpg。YOLOv8读取val.txt后,会尝试加载./YOLO/images/val/IMG_00123.jpg,而实际路径是./YOLO/images/val/IMG_00123.jpg(正确),但VOC路径映射逻辑混乱导致找不到图。
解决:检查VOCdevkit/VOC2007/ImageSets/Main/val.txt,用sed批量删扩展名:

sed -i 's/\.jpg$//' VOCdevkit/VOC2007/ImageSets/Main/val.txt

4.3 现象:MMDetection训练时RuntimeError: expected scalar type Float but found Half

原因:mmcv-full==2.1.0与pytorch==2.0.1在AMP(自动混合精度)下存在tensor dtype冲突,尤其在FP16训练时。
解决:禁用AMP,在config文件中添加:

fp16 = None # 显式关闭混合精度 optimizer_config = dict(type='OptimizerHook', grad_clip=None)

4.4 现象:测试时检测框密集重叠,NMS失效

原因:该数据集中同一片叶子常并发多种病害(如溃疡+炭疽),标注时允许同一区域多个bbox重叠。YOLOv8默认conf=0.25+iou=0.45,对重叠病斑过于激进地抑制。
解决:推理时降低NMS IoU阈值,增强重叠框保留:

yolo detect predict \ model=./runs/train/orange_disease_v8n_640/weights/best.pt \ source=./orange_citrus_disease/YOLO/images/test \ conf=0.1 \ iou=0.3 \ save_txt \ save_conf

iou=0.3让重叠度>30%的框才合并,更符合农业病害共存的实际。


5. 进阶技巧:用Grad-CAM可视化病害判别依据,说服农技员接受AI结论

5.1 为什么农技员不信你的mAP?——他们要看见“AI看到了什么”

在果园部署AI模型时,最大的阻力不是精度不够,而是不可解释性。农技员会问:“你说这是炭疽病,依据在哪?叶片边缘的褐色斑点?还是叶脉附近的凹陷?” —— 这正是Grad-CAM(Gradient-weighted Class Activation Mapping)的用武之地。它能生成热力图,高亮模型做决策时关注的图像区域。

使用Ultralytics内置Grad-CAM(需ultralytics>=8.2.39):

from ultralytics import YOLO import cv2 model = YOLO('./runs/train/orange_disease_v8n_640/weights/best.pt') img_path = './orange_citrus_disease/YOLO/images/test/IMG_1024.jpg' results = model(img_path, verbose=False) # 获取Grad-CAM热力图(针对最高置信度检测框) for r in results: if len(r.boxes) > 0: # 取第一个检测框(最高置信度) box_idx = 0 cam_img = r.plot(gradcam=True, box_idx=box_idx) # 自动叠加热力图 cv2.imwrite('./gradcam_output.jpg', cam_img)

生成的gradcam_output.jpg中,红色区域即模型认为“最支持该类别”的像素——你会发现,对溃疡病,热力图集中在水渍状边缘;对炭疽病,则聚焦于圆形褐色斑点中心。这比单纯说“mAP=0.76”有力得多。

5.2 定制化热力图:过滤背景干扰,只显示病斑相关区域

原始Grad-CAM会包含大量叶片纹理噪声。我们用形态学操作提纯:

import numpy as np from PIL import Image # 加载热力图(假设cam_img是BGR格式) cam_gray = cv2.cvtColor(cam_img, cv2.COLOR_BGR2GRAY) _, mask = cv2.threshold(cam_gray, 127, 255, cv2.THRESH_BINARY) # 形态学闭运算填充空洞,再腐蚀去除细小噪点 kernel = np.ones((5,5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) mask = cv2.erode(mask, kernel, iterations=2) # 叠加到原图(半透明) orig_img = cv2.imread(img_path) overlay = orig_img.copy() overlay[mask>0] = [0,255,0] # 绿色高亮 result = cv2.addWeighted(orig_img, 0.7, overlay, 0.3, 0) cv2.imwrite('./clean_gradcam.jpg', result)

后悔药时刻:我曾用原始热力图给农技站演示,被质疑“为什么整片叶子都红?是不是模型瞎猜”。加了这步形态学清洗后,热力图精准收缩到病斑区域,对方当场同意试点部署。技术落地,一半靠精度,一半靠表达。

5.3 生成诊断报告PDF:把热力图+置信度+病害特征描述打包交付

用reportlab自动生成农技员能看懂的PDF:

from reportlab.lib.pagesizes import A4 from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image from reportlab.lib.styles import getSampleStyleSheet doc = SimpleDocTemplate("citrus_diagnosis.pdf", pagesize=A4) styles = getSampleStyleSheet() story = [] # 标题 story.append(Paragraph("柑橘病害AI诊断报告", styles['Title'])) story.append(Spacer(1, 12)) # 热力图 story.append(Image("./clean_gradcam.jpg", width=400, height=300)) story.append(Spacer(1, 12)) # 诊断结论 conclusion = f"检测到:{results[0].boxes.cls[0].item():.0f}类病害({['溃疡病','炭疽病','褐斑病','黑点病'][int(results[0].boxes.cls[0].item())]})<br/>" \ f"置信度:{results[0].boxes.conf[0].item():.3f}<br/>" \ f"建议:{['立即隔离病株并喷施铜制剂','清除病叶后喷施咪鲜胺','加强通风降低湿度','采摘后彻底清园'] [int(results[0].boxes.cls[0].item())]}" story.append(Paragraph(conclusion, styles['BodyText'])) doc.build(story)

这份PDF里没有一行代码,只有热力图、置信度、农事建议——这才是农技员愿意传阅、张贴在田间公告栏的东西。

希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询