简介:本资源为面向目标检测学习者的马铃薯缺陷检测数据集,适用于YOLO全系列网络训练,可支撑农产品质检、智能农业等场景下的缺陷识别任务。数据集融合了常见马铃薯缺陷图像,涵盖发芽、真菌病害、机械损伤等5个类别,具体类别可参考class文本文件。压缩包共2000个文件,以1999个txt标签文件和1个Python脚本为主,整体约409.72MB,标签采用YOLO格式,可直接投入训练流程。其中show.py脚本可用于数据可视化,将标注框绘制在图像上,便于快速核验标注质量与类别分布。目前已有436人学习下载,适合从事目标检测实践、需要真实缺陷样本进行模型训练与验证的开发者及学生参考使用。
1. 马铃薯缺陷检测数据集:8000 张图、5 类缺陷,能不能直接喂给 YOLO
拿到一个农业质检的项目,客户张口就要「识别发芽、发霉、破损的土豆」,还要求产线速度。你第一反应肯定是找开源数据集,但 COCO、VOC 里根本没有「发芽马铃薯」这种细粒度类别,自己从零标 8000 张图,两个人干一个月都未必标得完。这份马铃薯(potato)图像缺陷检测数据集就是冲着这个缺口来的:它把常见的马铃薯缺陷数据做了融合,总共超过 8000 张图像,配 labelme 标注,并且已经处理成 YOLO 格式,训练集、验证集、标签、class 文件齐全,YOLO 全系列网络都能直接吃。
它解决的不是「有没有图」的问题,而是「类别定义能不能对上产线质检口径」的问题。类别一共 5 类,包括 Sprouted potato(发芽)、Diseased-fungal potato(真菌病害)、Damaged potato(破损)等,具体以 class 文本文件为准。适合谁?做农产品分选、食品加工质检、农业机器人视觉的从业者,以及想拿一个真实缺陷场景练 YOLO 微调的人。下面我按「先看懂结构、再跑通可视化、再训练、最后避坑」的顺序拆一遍。
2. 数据集结构与 YOLO 格式:先搞懂目录和标签长什么样
2.1 目录组织与文件命名规律
这份数据集最容易被忽略的是它的文件命名。你从项目正文里能看到一堆像images-11-_jpeg_jpg.rf.79ba1df764e9e8c303a2e7e7b6259ab0.txt这样的标签文件名,中间那串rf.加 32 位十六进制是典型的在线标注平台导出特征——图像和标签同名,只是扩展名不同。这意味着你拿到手后,图像目录和标签目录是分开的,靠文件名主干一一对应。
常见做法是整理成这样的结构,方便 YOLO 直接读:
potato_dataset/ ├── images/ │ ├── train/ # 训练图像 │ └── val/ # 验证图像 ├── labels/ │ ├── train/ # 训练标签 txt │ └── val/ # 验证标签 txt ├── classes.txt # 5 个类别名,一行一个 └── show.py # 可视化脚本这里有个血泪经验:很多人直接把所有图丢进一个文件夹就开训,结果验证集里混进了训练图,mAP 虚高到 0.95,上线一测全崩。训练集和验证集必须在文件层面就分开,别指望训练脚本帮你随机切。
2.2 YOLO 标签格式逐字段拆解
YOLO 的标签是纯文本,每行一个目标,格式是class_id x_center y_center width height,后四个都是归一化到 0~1 的相对值。拿一行举例:
0 0.512 0.634 0.221 0.3180:类别索引,对应 classes.txt 里的第 0 行,比如 Sprouted potato0.512:目标框中心点 x 坐标 ÷ 图像宽度0.634:中心点 y 坐标 ÷ 图像高度0.221:框宽 ÷ 图像宽度0.318:框高 ÷ 图像高度
为什么用归一化而不是绝对像素?因为 YOLO 训练时会做多尺度增强,绝对坐标一缩放就错位,归一化后无论图怎么 resize 都成立。这也是为什么你改图像尺寸时不用动标签。
2.3 用脚本校验标签合法性
在训练前,我一般会先跑一个校验脚本,把越界、空标签、类别越界的文件揪出来。这类融合数据集最容易出现标注平台导出时的坐标溢出:
import os import glob def check_labels(label_dir, num_classes=5): bad_files = [] for txt in glob.glob(os.path.join(label_dir, "*.txt")): with open(txt, "r") as f: lines = f.readlines() if not lines: bad_files.append((txt, "空标签")) continue for i, line in enumerate(lines): parts = line.strip().split() if len(parts) != 5: bad_files.append((txt, f"第{i}行字段数={len(parts)}")) continue cls_id = int(parts[0]) coords = [float(x) for x in parts[1:]] if cls_id < 0 or cls_id >= num_classes: bad_files.append((txt, f"第{i}行类别越界={cls_id}")) if any(c < 0 or c > 1 for c in coords): bad_files.append((txt, f"第{i}行坐标越界={coords}")) return bad_files if __name__ == "__main__": bad = check_labels("potato_dataset/labels/train") print(f"发现 {len(bad)} 个问题文件") for path, reason in bad[:20]: print(path, reason)逻辑说明:遍历标签目录下所有 txt,逐行检查字段数是否为 5、类别 id 是否在[0, num_classes)内、四个坐标是否落在[0,1]。参数num_classes默认 5,如果你的 class 文件实际类别数不同,改这个值。跑完把问题文件列出来,坐标越界的要么修要么删,别带着脏数据训练,否则 loss 会莫名其妙震荡。
3. 可视化与训练:show.py 怎么用、YOLO 怎么配
3.1 show.py 把 box 画回图像上
数据集自带的show.py是验证「图和标签对不对得上」的第一道关。它的作用就是把 YOLO 格式的 box 反归一化后画到原图上。核心逻辑大概是这样:
import cv2 import os def draw_yolo_box(img_path, label_path, classes, save_path=None): img = cv2.imread(img_path) h, w = img.shape[:2] if os.path.exists(label_path): with open(label_path) as f: for line in f: cls_id, xc, yc, bw, bh = line.strip().split() cls_id = int(cls_id) xc, yc, bw, bh = map(float, (xc, yc, bw, bh)) # 反归一化:中心点 + 宽高 -> 左上右下像素坐标 x1 = int((xc - bw / 2) * w) y1 = int((yc - bh / 2) * h) x2 = int((xc + bw / 2) * w) y2 = int((yc + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, classes[cls_id], (x1, max(y1 - 5, 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) if save_path: cv2.imwrite(save_path, img) return img if __name__ == "__main__": classes = [l.strip() for l in open("potato_dataset/classes.txt")] draw_yolo_box("potato_dataset/images/train/xxx.jpg", "potato_dataset/labels/train/xxx.txt", classes, "vis_out.jpg")逻辑说明:先读图拿宽高,再把归一化坐标乘回像素。xc - bw/2是左上角 x,xc + bw/2是右下角 x,y 同理。参数classes从 classes.txt 读,顺序必须和标签里的 class_id 严格对应,错一位就会把「发芽」标成「破损」。跑几张图肉眼看一下,框是不是正好套在缺陷上,这是最省事的质检方式。
3.2 生成 YOLO 训练用的 data.yaml
YOLO 系列训练靠一个 yaml 描述数据路径和类别。常见写法:
path: /home/user/potato_dataset train: images/train val: images/val nc: 5 names: 0: Sprouted potato 1: Diseased-fungal potato 2: Damaged potato 3: class_4 4: class_5path是数据集根目录,train/val是相对路径。nc必须等于类别数,names的键从 0 开始连续。这里最容易翻车的是names顺序和 classes.txt 不一致——训练能跑,但推理时类别名全错位,你还以为是模型没学好。
3.3 起训命令与关键参数
以 YOLOv8 为例,一条命令就能起训:
yolo detect train \ data=potato_dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=20 \ project=runs/potato \ name=exp1参数逐个说:model=yolov8n.pt用 nano 版先跑通,确认流程没问题再换 s/m;imgsz=640是输入分辨率,缺陷目标小的话可以提到 960,但显存翻倍;batch=16按显存调,爆显存就降到 8;lr0=0.01初始学习率,微调预训练模型时我一般降到 0.001 更稳;patience=20是早停,20 轮没提升就停,省时间。训练日志里重点盯mAP50和mAP50-95,前者看召回,后者看框的精度。
4. 避坑与排查:融合数据集最容易踩的五个坑
4.1 类别名对不上,训练正常但推理全错
现象:训练 loss 正常下降,mAP 也还行,但推理时框的位置对、类别名全乱。原因:data.yaml的names顺序和classes.txt不一致,或者标签里的 class_id 是从 1 开始而不是 0。解决:用 2.3 的校验脚本确认 class_id 范围,再逐行比对 classes.txt 和 yaml 的 names,顺序必须完全一致。
4.2 图像和标签文件名主干不匹配
现象:训练报「找不到标签」或大量图被跳过,实际参与训练的样本远少于 8000。原因:融合数据来自多个来源,命名规则不统一,有的图是.jpg标签是.txt但主干差一个后缀。解决:写脚本按主干(去掉扩展名)做匹配,把没有对应标签的图移出去,别让它们污染训练集。
4.3 验证集混入训练图导致指标虚高
现象:验证 mAP 高得离谱,上线一测惨不忍睹。原因:切分时随机打乱,同一张图的增强版本同时进了训练和验证。解决:按原始图像(不是增强后)切分,训练验证比例 8:2 或 9:1,切完再各自做增强。
4.4 小目标缺陷被 resize 抹掉
现象:发芽这种小目标召回率极低。原因:imgsz=640时原图被压缩,几十像素的芽点直接糊没。解决:提高输入分辨率到 960 或 1280,或者用切片推理(把大图切小块分别检测再合并)。代价是显存和推理时间上升,产线要权衡。
4.5 类别不平衡导致模型偏向多数类
现象:破损类样本多,发芽类样本少,模型几乎不预测发芽。原因:5 类缺陷在 8000 张图里分布不均。解决:训练时开类别权重,或用过采样补少数类;YOLOv8 可以在 loss 里调cls权重,也可以先统计每类框数量再决定策略。
5. 进阶技巧:用混淆矩阵和单类 AP 定位短板
训练跑完不是看个总 mAP 就完事。我习惯先看混淆矩阵,它能告诉你模型把哪两类搞混了——比如「Diseased-fungal」和「Damaged」经常互串,说明这两类视觉特征接近,得回去看标注边界是否清晰。YOLO 训练完会在runs/potato/exp1/下生成confusion_matrix.png和results.csv。
results.csv里每轮都有metrics/mAP50-95(B),但真正有用的是按类拆开的 AP。用下面这段把每类 AP 拉出来对比:
import pandas as pd df = pd.read_csv("runs/potato/exp1/results.csv") df.columns = [c.strip() for c in df.columns] # 找出所有按类记录的 AP 列 ap_cols = [c for c in df.columns if "AP" in c and "50-95" in c] print(df[ap_cols].iloc[-1].sort_values())逻辑说明:读训练结果 csv,筛出每类的 AP50-95 列,取最后一轮的值排序。排在最下面的就是短板类。参数上,如果某一类 AP 明显低于其他类,优先补这类样本或检查标注质量,而不是盲目加轮数。
再补一个实用习惯:推理时把置信度阈值调低到 0.25 先看召回,确认漏检情况,再逐步提到 0.5 看精度。产线场景宁可多报也别漏报,阈值策略要按业务定。我一般会在验证集上画 PR 曲线,找召回和精度的平衡点,而不是拍脑袋定 0.5。
从那以后我每次拿到融合数据集,都强制先跑一遍标签校验、再可视化抽检 20 张、最后按类看 AP,这三步走完才敢起正式训练。希望这份拆解帮到你,少走几个我踩过的坑。
本文还有配套的精品资源,点击获取