☰
玉米黄曲霉素识别数据集:YOLOv8人工标注与93.8%准确率实战
2026/10/8 1:11:07 网站建设 项目流程

简介:这份玉米黄曲霉素识别数据集面向从事农业病害检测、粮食安全质检及计算机视觉方向的学习者与开发者,用于训练和验证玉米穗腐病等霉变类别的目标检测模型。数据均基于原始图片经YOLOv8人工标注,验证准确率可达93.8%以上,可直接用于模型训练、迁移学习或算法对比实验。压缩包共865个文件,包含432张jpg原始图像、432个同名txt标注文件及1个yaml数据配置文件,整体约27.58MB,标注与图像一一对应,yaml文件便于快速接入YOLO系列训练流程。图像覆盖镰刀菌穗腐、赤霉穗腐等多种病害类别,样本命名规范,适合作为分类与检测任务的基准数据。目前已有372人学习下载,可为农业AI项目提供开箱即用的标注数据,帮助读者省去繁琐的采集与标注环节,快速验证模型效果并迭代优化。

1. 玉米黄曲霉素识别数据集:从原始图片到 YOLOv8 人工标注的落地路径

玉米穗腐病里最难缠的一类,是黄曲霉素和镰刀菌、赤霉菌混发的情况。这三种病害在果穗上的早期症状高度相似,肉眼区分依赖籽粒颜色、霉层颜色和穗轴腐烂位置,但田间光照一变、拍摄角度一偏,人眼判断的准确率就往下掉。这份玉米黄曲霉素识别数据集,走的是 YOLOv8 目标检测路线,所有图片都是原始拍摄图,没有经过合成增强或风格迁移,标注全部由人工完成,验证集准确率可以做到 93.8% 以上。它适合两类人:一类是想做农作物病害检测但手里没有干净标注数据的算法工程师,另一类是已经跑通 YOLOv8 通用流程、想换一个真实农业场景验证模型泛化能力的从业者。数据集里包含 fusarium-ear-rot、gibberella-ear-rot、fusarium-diseases 等多个类别,文件名保留了原始采集编号,方便追溯每张图的来源和标注一致性。

2. 数据集结构与标注格式:先看清目录再动手

2.1 图片命名规则与类别映射

拿到压缩包后,第一件事不是急着解压训练,而是先看文件名。这份数据集的图片命名格式是「类别名+编号_jpeg.rf.哈希值.jpg」,比如fusarium-ear-rot5_jpeg.rf.74cba18136688a9a886ae2c38c8dd0b9.jpg和gibberella-ear-rot27_jpeg.rf.21c6ba8255d297251374e342a24e62e0.jpg。类别名直接写在文件名前缀里,fusarium-ear-rot 对应镰刀菌穗腐,gibberella-ear-rot 对应赤霉菌穗腐,fusarium-diseases 是镰刀菌属相关病害的统称。哈希值那一段是采集平台生成的唯一标识,不影响训练,但建议保留,因为后续做数据溯源或增量标注时,这个哈希能帮你快速定位原图。

常见做法是先用脚本把文件名里的类别前缀抽出来,生成一份类别映射表。我一般会跑下面这段 Python,把目录下所有图片按类别归拢,顺便检查有没有命名异常的文件:

import os import re from collections import defaultdict img_dir = "./corn_dataset/images" class_map = defaultdict(list) # 匹配「类别名+编号_jpeg.rf.哈希.jpg」结构 pattern = re.compile(r"^([a-zA-Z-]+?)(\d+)_jpeg\.rf\.[a-f0-9]+\.jpg$") for fname in os.listdir(img_dir): match = pattern.match(fname) if match: cls_name = match.group(1) class_map[cls_name].append(fname) else: print(f"命名不符合预期: {fname}") for cls, files in class_map.items(): print(f"{cls}: {len(files)} 张")

这段代码的逻辑很直接:用正则把类别名和编号拆开,类别名作为 key 归入字典。参数上唯一需要改的是img_dir,指向你解压后的图片目录。跑完之后你会得到每个类别的图片数量,如果某个类别只有个位数,那就要警惕了——YOLOv8 虽然对小样本有一定容忍度,但单类少于 50 张时,验证集准确率波动会非常大,93.8% 这个数字大概率是在类别均衡的前提下测出来的。

2.2 YOLOv8 标注格式与目录组织

YOLOv8 用的是 YOLO 格式的 txt 标注,每张图对应一个同名 txt 文件,内容格式是「类别索引 中心x 中心y 宽 高」,坐标全部归一化到 0~1 之间。这份数据集既然是人工标注,标注质量主要看两点:框是否贴紧病斑区域、类别索引是否和 data.yaml 里的 names 顺序一致。我见过太多人直接拿标注文件训练,结果 mAP 死活上不去,最后发现是 names 列表顺序和标注里的索引对不上,这种坑后面会专门讲。

目录组织建议按下面这个结构来,YOLOv8 官方推荐的就是 images/labels 分离,train/val 再分:

corn_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml

data.yaml 的内容需要根据你实际的类别数来写。假设数据集里只有 fusarium-ear-rot 和 gibberella-ear-rot 两类,那 yaml 就是:

path: ./corn_dataset train: images/train val: images/val names: 0: fusarium-ear-rot 1: gibberella-ear-rot

这里有个细节:names 的索引必须从 0 开始连续,不能跳号。如果你把 fusarium-diseases 也单独列一类,那就要确认标注文件里确实有对应的索引值,否则训练时 YOLOv8 会直接报「Label class out of range」然后中断。人工标注的数据集尤其容易出这个问题,因为不同标注员可能对同一张图给了不同的类别标签,合并的时候索引就乱了。

3. YOLOv8 训练全流程:从环境配置到 93.8% 准确率复现

3.1 环境配置与依赖安装

YOLOv8 的环境配置不算复杂,但版本兼容性是个玄学。我一般用 Python 3.9 或 3.10,太新的版本反而容易和 torch 的 CUDA 版本打架。下面这套命令在 Ubuntu 和 Windows WSL 下都跑通过:

conda create -n corn_yolo python=3.10 -y conda activate corn_yolo # 安装 PyTorch,根据你的 CUDA 版本选对应命令 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics pip install ultralytics # 验证安装 yolo checks

yolo checks会输出当前环境的信息,重点看 CUDA 是否可用、torch 版本和 ultralytics 版本是否匹配。如果你用的是 GTX 1660 Ti 这类 6GB 显存的卡,训练时 batch size 要往下压,后面参数部分会讲。常见做法是先跑一遍yolo checks,确认没有报错再开始训练,不然训练到一半崩了,排查成本更高。

3.2 训练命令与关键参数设置

YOLOv8 的训练入口是yolo detect train,最简命令只需要指定 data.yaml 和模型权重:

yolo detect train \ data=./corn_dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ project=./runs/corn \ name=exp1

这段命令里每个参数都值得说清楚。model=yolov8n.pt用的是 nano 版本,参数量最小,适合先跑通流程;如果你追求更高准确率,可以换成yolov8s.pt或yolov8m.pt,但显存占用会明显上升。imgsz=640是输入分辨率,玉米穗腐的病斑在果穗上占比不大,640 够用,但如果你有大量远距离拍摄的整株图,可以考虑提到 1280,代价是训练速度减半。batch=16在 6GB 显存上比较稳,8GB 以上可以试 32。epochs=100是起步值,这份数据集如果类别均衡、标注干净,100 轮左右验证集准确率就能到 90% 以上,但想稳定复现 93.8%,建议加到 200 轮并开早停。

训练过程中最该盯的是runs/corn/exp1/results.csv里的 losses 和 metrics。YOLOv8 默认会画损失函数曲线图,但那个图是存在results.png里的,如果你想自己用 matplotlib 画更细的曲线,可以读 csv 文件:

import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("./runs/corn/exp1/results.csv") df.columns = df.columns.str.strip() plt.figure(figsize=(10, 5)) plt.plot(df["epoch"], df["train/box_loss"], label="box_loss") plt.plot(df["epoch"], df["train/cls_loss"], label="cls_loss") plt.plot(df["epoch"], df["metrics/mAP50(B)"], label="mAP50") plt.xlabel("epoch") plt.legend() plt.savefig("./loss_curve.png", dpi=150)

这段代码读的是训练日志 csv,列名里可能有空格,所以先 strip 一下。box_loss 和 cls_loss 是训练损失,mAP50 是验证集指标。正常情况下 box_loss 应该稳步下降,如果它震荡剧烈或者反弹,大概率是学习率太大或者标注框质量有问题。

3.3 验证集评估与准确率复现

训练结束后,用yolo detect val在验证集上跑一遍:

yolo detect val \ model=./runs/corn/exp1/weights/best.pt \ data=./corn_dataset/data.yaml \ imgsz=640 \ batch=16

输出里会给出 mAP50、mAP50-95、precision、recall 等指标。93.8% 这个数字,如果对应的是 mAP50,那说明模型在 IoU=0.5 时的平均精度已经很高了;如果对应的是 precision,那还要看 recall 是否均衡。我一般会同时看 precision 和 recall,两者差距超过 10 个百分点,就说明模型在某类上偏了。比如 fusarium-ear-rot 的 precision 很高但 recall 低,意味着模型只对特别明显的病斑有响应,早期症状漏检严重。

想进一步看每类的表现,可以加verbose=True或者直接看混淆矩阵。YOLOv8 验证时会自动生成confusion_matrix.png,那个图比数字更直观。如果某一类的对角线颜色很浅,说明该类召回率不行,要么加数据,要么检查标注是否把该类标成了别的类。

4. 避坑与排查:人工标注数据集最容易翻车的五个点

4.1 类别索引与 names 顺序不一致

现象:训练启动后报Label class 2 is out of range,或者训练能跑但 mAP 极低。原因:标注 txt 里的类别索引是 2,但 data.yaml 的 names 只定义了 0 和 1。人工标注时不同批次可能用了不同的索引方案,合并后没统一。解决:写个脚本扫一遍所有 label 文件,统计出现的索引值,和 names 列表比对。下面这段代码可以直接用:

import os label_dir = "./corn_dataset/labels/train" idx_set = set() for fname in os.listdir(label_dir): if fname.endswith(".txt"): with open(os.path.join(label_dir, fname)) as f: for line in f: if line.strip(): idx_set.add(int(line.split()[0])) print("标注中出现的类别索引:", sorted(idx_set))

跑完之后看输出,如果索引集合和 names 的 key 集合不一致,就要么改 names,要么批量改标注文件里的索引。

4.2 图片与标注文件不配对

现象:训练时提示No labels found,或者某张图被跳过。原因:图片是 jpg,标注是 txt,但文件名前缀不一致,比如图片叫fusarium-ear-rot5_jpeg.rf.xxx.jpg,标注却叫fusarium-ear-rot5.txt,YOLOv8 找的是同名文件。解决:批量重命名标注文件,把哈希那段去掉,只保留和图片一致的前缀。或者反过来,把图片名里的哈希去掉。我一般用 shell 脚本批量处理:

cd corn_dataset/labels/train for f in *.txt; do # 去掉 _jpeg.rf.哈希 部分,只保留类别+编号 newname=$(echo "$f" | sed 's/_jpeg\.rf\.[a-f0-9]*\.txt/.txt/') mv "$f" "$newname" done

注意先备份,重命名操作不可逆。

4.3 验证集准确率虚高:数据泄漏

现象:验证集准确率 93.8%,但换一批新图测试就掉到 70% 以下。原因:同一张原始图片经过裁剪或旋转后,一部分进了训练集,一部分进了验证集。人工标注数据集尤其容易出这个问题,因为标注员可能对同一张图的不同区域分别标注,生成多个文件。解决:按原始图片的哈希值分组,同一哈希的图片只能出现在训练集或验证集之一。如果数据集里已经有 train/val 划分,先检查两边有没有相同哈希前缀的文件。

4.4 小目标病斑漏检严重

现象:整穗腐烂的图检测很好,但早期小病斑的图 recall 很低。原因:YOLOv8 默认 anchor 对中等目标更友好,病斑在 640 分辨率下可能只有几十个像素。解决:提高输入分辨率到 1280,或者在 data.yaml 里加rect=True做矩形训练,减少 padding 带来的无效计算。另外可以试yolov8m.pt或yolov8l.pt,大模型对小目标的特征提取能力更强。

4.5 训练中断后无法续跑

现象:训练到第 80 轮断电了,重新跑又从第 1 轮开始。原因:没加resume=True。YOLOv8 支持断点续训,但需要指定 last.pt 的路径:

yolo detect train resume model=./runs/corn/exp1/weights/last.pt

注意 resume 时不需要再传 data 和 epochs,这些参数会从 last.pt 里读。但如果你改了 data.yaml 的路径,resume 会失败,所以训练中途不要动配置文件。

5. 进阶技巧:用热力图和 RK3588 部署验证模型真实能力

训练指标好看不代表模型能用。我一般会做两件事来验证:一是可视化热力图,看模型到底在关注果穗的哪个区域;二是把模型导出到 RK3588 这类边缘设备上跑一遍,看推理速度和实际检测效果。

热力图用 YOLOv8 的model.predict加 Grad-CAM 就能做,核心是拿到最后一层卷积的特征图,然后对目标类别做梯度加权。下面是一个简化版实现:

import cv2 import numpy as np import torch from ultralytics import YOLO model = YOLO("./runs/corn/exp1/weights/best.pt") img = cv2.imread("./test.jpg") results = model(img, imgsz=640) # 取第一个检测框的类别和坐标 box = results[0].boxes[0] cls_id = int(box.cls) xyxy = box.xyxy[0].cpu().numpy().astype(int) # 裁剪病斑区域并叠加热力示意 roi = img[xyxy[1]:xyxy[3], xyxy[0]:xyxy[2]] heatmap = cv2.applyColorMap(cv2.convertScaleAbs(roi, alpha=2), cv2.COLORMAP_JET) overlay = cv2.addWeighted(roi, 0.6, heatmap, 0.4, 0) cv2.imwrite("./heatmap_roi.jpg", overlay)

这段代码不是严格的 Grad-CAM,但能快速看出模型检测框是否落在病斑上。如果框偏了,说明标注本身就有问题,这时候回头查标注比调模型更有效。

RK3588 部署 YOLOv8 的流程是:先把 pt 导出成 onnx,再用 rknn-toolkit2 转成 rknn 模型,最后用 rknn-toolkit-lite2 在板子上推理。导出命令:

yolo export model=./runs/corn/exp1/weights/best.pt format=onnx imgsz=640

转 rknn 的脚本网上有很多模板,核心是配置mean_values和std_values,要和训练时的预处理一致。RK3588 的 NPU 对 YOLOv8 支持不错,640 分辨率下单帧推理能到 30fps 以上,但前提是量化校准集要覆盖各类病斑,否则 int8 量化后小目标召回会掉得很厉害。

从那以后我每次拿到新数据集,都强制先跑一遍类别索引检查和图片标注配对检查,再开始训练。这两个检查花不了十分钟,但能省掉后面几小时的无效训练。希望帮到你。

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

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

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

立即咨询