资讯动态

中草药目标检测数据集:YOLO格式实战与避坑指南

发布时间:2026/10/10 18:14:22 来源:尧图企业网站定制
简介面向目标检测任务的中草药图像YOLO数据集适合需要训练中草药识别模型的算法工程师、科研人员及目标检测初学者。数据已按YOLOv5目录结构严格划分训练集约2600张、验证集约190张、测试集约100张图片及对应txt标注类别共8个包括Cardamom、Cumin、Neem等具体可查看classes文件。标注采用YOLO标准相对坐标格式类别、中心点x、中心点y、宽、高无需任何格式转换可直接投入YOLO系列模型训练与评估。压缩包内共2000个文件以1999个txt标注文件为主配合1个show.py数据可视化脚本该脚本无需修改即可随机读取图片并绘制边界框结果自动保存至当前目录方便快速核查标注质量。资源包大小209.51MB已有1017人学习下载无论是用于毕设、科研实验还是实际项目原型验证都能省去数据准备环节帮助开发者直接聚焦模型效果是一份可直接上手的现成数据基础。1. 中草药目标检测数据集拿过来就能跑的YOLO格式资源做目标检测最头疼的不是模型选型而是数据。中草药这类细粒度目标网上公开数据集少得可怜自己爬图标注一张平均要两分钟两千张就是六十多个小时。这份YOLO格式的中草药图像数据集解决了从零开始攒数据的最大痛点——它已经完成标注、划分和格式整理下载后直接用YOLOv5/v8训练即可连目录结构都是按datasets标准摆放的。八类中草药Cardamom、Cumin、Neem等训练集约2600张、验证集约190张、测试集约100张全部采用YOLO相对坐标标注class, x_center, y_center, w, h。适合三类人刚入门想跑通YOLO训练全流程的新手、做农产品或药材检测项目需要快速验证方案、以及需要一份干净基线数据做算法对比的研究者。2. 数据集内部结构YOLOv5目录规范与标注文件格式2.1 目录树拆解为什么说“按YOLOv5文件夹保存”就能直接训拿到数据集后第一件事是先摸清目录结构。项目按YOLOv5官方推荐的datasets布局组织根目录下是images和labels两个大文件夹各自再按train、val、test拆分。这种结构的好处是YOLOv5的train.py默认就读取这种布局不需要改数据加载代码只是训练时在data.yaml里指定路径即可。datasets/ ├── images/ │ ├── train/ # 约2600张 │ ├── val/ # 约190张 │ └── test/ # 约100张 ├── labels/ │ ├── train/ # 对应txt标注 │ ├── val/ │ └── test/ ├── classes.txt # 类别文件 └── show.py # 可视化脚本注意labels的目录层级必须与images完全镜像文件名也必须一一对应——图片是1000_F_604576389_xxx.jpg标注就是1000_F_604576389_xxx.txt只差后缀名。训练时YOLO靠这个对应关系去找标注文件一旦文件名对不上就会在训练日志里刷Warning而且这些图片会被静默跳过属于常见的数据集翻车点。2.2 labels里的txt到底写的什么相对坐标解析打开任意一个txt文件内容长这样2 0.48359375 0.3578125 0.603125 0.575 5 0.6953125 0.18359375 0.240625 0.284375每行对应一个目标框四个数字的含义是类别id、归一化后的中心点x坐标、归一化后的中心点y坐标、归一化后的框宽、归一化后的框高。归一化是指除以图片原始宽高所以所有值都在0到1之间。这一点和VOC的x_min, y_min, x_max, y_max格式不同很多从VOC转过来的新手在这里翻车——拿着VOC的绝对坐标直接当YOLO用训练出来的框全是偏的。类别id与classes.txt的序号一一对应。比如classes.txt内容如果是Cardamom Cumin Neem ...那么第一行开头写2就代表该框属于第三类Neem从0开始计数。训练前务必用文本编辑器打开classes.txt核对类别顺序因为data.yaml里的names列表必须与之一致否则类别标签会错位——表现是loss正常下降但推理出来的类别名和实际物体对不上这是最难排查的玄学问题之一。2.3 用Python快速检视数据集完整性在动手训练前我习惯先写个脚本做完整性检查图片数量与txt数量是否一致、有没有空标注文件、类别分布是否均衡。这个检查只需要Python标准库就能实现不用装额外依赖import os from pathlib import Path for split in [train, val, test]: img_dir Path(fdatasets/images/{split}) label_dir Path(fdatasets/labels/{split}) imgs list(img_dir.glob(*.jpg)) list(img_dir.glob(*.png)) labels list(label_dir.glob(*.txt)) print(f{split}: images{len(imgs)}, labels{len(labels)}) empty_labels [] for label_path in labels: if label_path.stat().st_size 0: empty_labels.append(label_path.name) label_path.unlink() # 直接删掉空文件 if empty_labels: print(f - 发现并删除{len(empty_labels)}个空标注: {empty_labels[:5]})这里删除空txt对应图片的标注是必要的——YOLO训练时遇到空文件会视为背景图如果你的应用场景不需要背景图留着反而干扰训练。不过删之前最好确认一下该图片是否真的没有目标有时候是标注工具漏标了删掉标注会让这张图变成纯背景样本影响正负样本平衡。2.4 类别分布统计训练前必须知道的数字from collections import Counter category_counter Counter() for split in [train, val, test]: label_dir fdatasets/labels/{split} for file in os.listdir(label_dir): with open(os.path.join(label_dir, file)) as f: for line in f: category_counter[int(line.split()[0])] 1 for class_id, count in sorted(category_counter.items()): print(fclass {class_id}: {count} instances)类别分布直接决定模型收敛质量。如果某类只有几十个实例而其他类有两千多个训练出来的模型对该类的recall会明显偏低。这份数据集整体分布相对均衡但不同类别间仍然有几倍的差距。遇到不平衡常见的做法是给data.yaml里每个类别设置不同的weight或者简单粗暴地对少数类做数据增强——Mosaic、Copy-Paste这类增强对中草药这种纹理特征明显的目标效果不错。3. 数据可视化与质量自检show.py的运行逻辑和改造方法3.1 原版show.py做了什么项目自带的show.py是典型的数据集可视化复盘工具核心逻辑很简单随机抽一张图片读取对应的txt标注用OpenCV或PIL把矩形框画在图上保存到当前目录。不需要改任何配置直接运行就能出图对新手很友好。import cv2 import glob import random image_files glob.glob(datasets/images/train/*.jpg) img_path random.choice(image_files) label_path img_path.replace(images, labels).replace(.jpg, .txt) img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: cls, x_center, y_center, bw, bh map(float, line.split()) x1 int((x_center - bw / 2) * w) y1 int((y_center - bh / 2) * h) x2 int((x_center bw / 2) * w) y2 int((y_center 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.5, (0, 255, 0), 1) cv2.imwrite(visualized.jpg, img)这段代码的关键点是坐标转换把yolo的相对坐标乘回图片宽高得到像素坐标然后用cv2.rectangle画框。类别用数字id展示要显示类别名称的话需要从classes.txt读进来做一个id到name的映射。3.2 改造一批量生成可视化缩略图而不是单张原脚本一次只画一张图要看全貌得反复运行效率低。我一般会改造成批量模式——从每个类别里抽几张有代表性的图一次画完拼成网格图。import os import cv2 import numpy as np from collections import defaultdict # 按类别分组收集图片 class_images defaultdict(list) for label_file in os.listdir(datasets/labels/train): with open(fdatasets/labels/train/{label_file}) as f: first_line f.readline().strip() if not first_line: continue cls int(first_line.split()[0]) img_name label_file.replace(.txt, .jpg) class_images[cls].append(os.path.join(datasets/images/train, img_name)) # 每个类别抽3张拼成3x3网格 for cls, imgs in class_images.items(): if len(imgs) 3: selected np.random.choice(imgs, 3, replaceFalse) grid np.zeros((h * 3, w * 3, 3), dtypenp.uint8) for i, img_path in enumerate(selected): img cv2.imread(img_path) img cv2.resize(img, (w, h)) r, c divmod(i, 3) grid[r*h:(r1)*h, c*w:(c1)*w] img cv2.imwrite(fclass_{cls}_sample.jpg, grid)这个改造的核心价值是快速暴露类别错标问题——如果某个类别抽出来的3张图里有明显不是该类别的物体说明标注阶段有噪声训练前需要清洗。3.3 改造二画框的同时附带类别名和置信度正式训练后你可能会想可视化预测结果而不是标注这时候我把同样的框画法用在模型输出上多了一个置信度维度# 假设这是模型输出的格式cls, conf, x_center, y_center, w, h def draw_yolo_prediction(img_path, detections, class_names, output_path): img cv2.imread(img_path) h, w img.shape[:2] for cls, conf, xc, yc, bw, bh in detections: name class_names[int(cls)] label f{name} {conf:.2f} x1, y1 int((xc - bw/2) * w), int((yc - bh/2) * h) x2, y2 int((xc bw/2) * w), int((yc bh/2) * h) color (0, 255, 255) if conf 0.5 else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, label, (x1, y1 - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 1) cv2.imwrite(output_path, img)低置信度框用红色画高置信度框用黄色画一眼就能看出哪些目标模型拿不准这些就是需要补数据或调阈值的候选样本。3.4 可视化输出的判读标准什么样的图说明数据有问题可视化不只是“看一眼有没有框”要看的是框的质量。我总结了几个快速判读维度一是框是否紧贴目标边缘——如果框明显大于目标比如框里有一大半是背景说明标注时用上了外接矩形的习惯这样训练出来的模型定位精度会差一点但不算致命。二是同类目标在不同图片里框的大小分布是否合理——如果某类在中远景下框都很小而数据集里几乎没有大目标的样本模型对该类的大目标检测能力会偏弱。三是框之间有没有大量重叠——如果同一张图里同类目标框大面积重叠这通常是重复标注而不是目标密集需要人工确认。把可视化脚本多跑几次随机抽几十张图看一遍比盯着一千行log有用得多。4. 避坑指南这份数据集最容易踩的五个坑4.1 图片和txt文件名对不上导致训练样本缩水现象训练日志里出现大量WARNING: Ignoring empty label file或者训练完发现val集的mAP比预期低很多训练集明明有两千六百张图但实际参与训练的只有两千张左右。原因这份数据集来自多个渠道文件名里带rf.前缀的是Roboflow导出格式部分图片在导出时丢失了对应的txt文件或者某些txt是空的。YOLOv5在数据加载阶段会把没有标注或标注为空的图片直接过滤掉这个过滤是静默的只在日志里刷Warning容易被忽略。解决数据集根目录下跑一次完整性脚本把没有对应txt的图片文件单独拎出来确认这些图片是否真的没有目标——如果是漏标注可以人工补如果本身是背景图就直接移出训练集避免影响正负样本比例。脚本逻辑不复杂遍历images目录下所有jpg检查同名txt是否存在即可。4.2 验证集和测试集被当作同一个目录用现象看项目介绍时发现测试集路径写的是datasets-images-val明明是test却指向val目录。原因原作者在整理目录时把测试集和验证集放在了同一个目录下或者README里路径写重复了。这种情况在网上下载的数据集里经常出现——标注工作量太大最后划分阶段偷懒了。解决训练前自己检查一遍三个目录的实际图片数量确认真实存在test目录并且有大约100张图片。如果发现test目录和val目录是同一个软链接或重复拷贝要么自己从val里随机抽出100张当测试集要么接受只用val做评估但要在日志里注明测试集和验证集有重叠mAP数值会有虚高成分。4.3 类别id从1开始而不是从0开始现象模型训练完成后推理时发现预测的类别名整体往右偏移一位——比如真正的Cardamom被识别成了CuminCumin被识别成了Neem。原因数据集的classes.txt里类别序号从1开始编号但YOLO要求的类别id是从0开始。如果标注文件里写的是1-8而data.yaml里names列表按0-7映射那么类别名和id就错位了。解决训练前打开一个txt文件看里面的class数字范围。如果最大数字等于类别总数而最小数字是1说明标注从1开始需要写个脚本把所有txt里每行第一个数字减1或者干脆在data.yaml的names列表第一行加一个None占位让索引对齐。这个坑比较隐蔽因为loss会正常收敛不推理基本发现不了。4.4 中草药图像背景复杂导致的漏标现象可视化抽检时发现部分图片里的中草药在画面边缘、被遮挡或与背景颜色接近的位置没有被标注。原因中草药数据集很多是从素材网站爬的图背景有纯白、木桌、草地等多种场景。标注人员面对复杂背景时容易漏掉被遮挡的目标特别是叶片颜色和背景相近的Neem这类深色植物。解决训练前用第3章的批量可视化脚本把所有训练图过一遍重点看那些小目标密集的图片。如果发现连续多张图都有漏标可以考虑把标注工具LabelImg或X-AnyLabeling重新打开手动补充漏标框。漏标对模型的负面影响比错标还大——错标的框至少让模型学到了一个位置漏标则直接告诉模型“这个位置没有目标”在推理时模型会倾向于略过相似位置。4.5 图片尺寸不统一导致归一化坐标换算错误现象可视化时发现某些框明显偏移框的中心点和目标实际位置不重合且只出现在特定几张图上。原因数据集里混入了不同分辨率的图片标注软件在导出时如果按统一尺寸归一化而实际图片没有resize到那个尺寸就会导致坐标错位。比如标注时把图片统一resize到640x640再归一化但实际保存的是原图1920x1080框的x_center是按640宽度算的画到1080p图上自然偏移。解决可视化脚本里加一个图片宽高打印抽检时对比不同尺寸图片的标注质量。如果发现特定尺寸的图片全部错位写脚本把这些图片统一转成标注时的尺寸或者重新生成标注文件。严格来说YOLO格式的归一化坐标是自适应的不会因为图片尺寸变化而失效只有标注时用了错误基准尺寸才会出现这种问题。5. 进阶用法从跑通到跑好——锚框重聚类与训练参数调优数据集能直接训练但“能训练”和“训练得好”是两回事。这份中草药数据集的标注目标多为中等尺寸的叶片或果实个体而YOLOv5/v8默认的锚框是基于COCO数据集聚类的COCO的目标普遍偏大直接迁移到中草药场景不是最优解。我推荐训练前先跑一次k-means锚框聚类用数据集自身的框尺寸分布替换默认锚框。import numpy as np from sklearn.cluster import KMeans def load_boxes(label_dir): boxes [] for file in os.listdir(label_dir): with open(os.path.join(label_dir, file)) as f: for line in f: _, _, _, w, h map(float, line.split()) boxes.append([w, h]) return np.array(boxes) boxes load_boxes(datasets/labels/train) kmeans KMeans(n_clusters9, random_state0).fit(boxes) anchors kmeans.cluster_centers_.flatten() print(新锚框:, np.round(anchors, 3))聚类结果出来后把新锚框写进models/yolov5s.yaml或yolov8的yaml配置里同时注意配合数据集的图片尺寸——如果训练时imgsz设为640锚框值不需要额外缩放因为YOLO内部会做归一化处理。训练参数方面我建议batch size根据显存来定GTX 1080Ti级别用16A100用32或更大。epochs设150-200足够因为数据集规模不大300轮以上容易过拟合。中草药这类目标是典型的纹理识别任务模型不需要很大的感受野所以优先用最小的模型yolov5s或yolov8n起步跑通了再考虑升级到m或l。lr0.01、momentum0.937是YOLOv5的默认值一般不用动但weight_decay可以适当调到0.0005防止在小数据集上过拟合。训练完成后除了看val集的mAP我还有一个习惯把测试集里每个类别的预测结果单独导出按置信度排序看低置信度的前十个样本长什么样。这些样本通常是遮挡严重、目标极小或背景高度相似的hard case它们比mAP数字更能告诉你模型的真实边界在哪。这份数据集自带测试集正好用来做这个分析。数据增强方面中草药叶片边缘纹理是辨识关键所以颜色抖动HSV和轻微旋转是有益的但上下翻转要慎用——药用植物特征和朝向无关的话没问题但如果某些类别有方向性特征比如花朵朝上翻转反而会引入噪声。建议在hyp.yaml里把flipud设为0fliplr保持0.5hsv_h、hsv_s、hsv_v分别设为0.015、0.7、0.4。说到最后我自己每次拿到一份新数据集都会强制走一遍同样的流程完整性检查、类别分布统计、可视化抽检、锚框重聚类、小模型试跑。这套流程帮我筛掉了至少七八份看起来能训但实际有各种暗病的数据集。这份中草药数据集整体质量在线核心坑位我都标注在上面了按这个顺序过一遍训练流程基本不会出大问题。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑