简介:这份资源面向从事目标检测学习与课程实践的学生、教师及算法入门者,提供一套真实场景下的树叶分类目标检测数据集,可直接用于YOLO系列模型的训练与验证。压缩包共2000个文件,约27.93MB,包含1000张高质量标注图片,以及voc格式的xml、coco格式的json和yolo格式的txt三种标签文件,另附yaml配置文件、划分脚本与训练教程网页,方便按需组织数据。资源还提供训练集、验证集、测试集划分脚本,可将图片与标签按比例写入新文件夹,并生成ImageSets下的txt索引,便于复现标准实验流程。教程部分覆盖Windows与Linux下的YOLO环境搭建、Ubuntu安装及基于案例修改训练自己数据集的完整思路,帮助读者快速跑通训练与评估。目前已有471人学习下载,适合需要现成数据与配套脚本快速开展目标检测实践的用户。
1. 树叶检测数据集怎么选:1000 张真实场景图 + 三格式标签能省掉多少标注功夫
做农业视觉或者林学调查的同行,十有八九都卡在同一个地方:模型结构抄得飞快,数据集却要从零标。我见过一个团队为了做叶片病害初筛,三个人标了两周才凑出 600 张,最后 mAP 还上不去,问题就出在标注框松紧不一、遮挡样本太少。这份 YOLO 树叶分类目标检测数据集,核心价值就在于把最耗人的那一步替你干完了——1000 张真实场景图片,用 labelImg 标注,同时给出 VOC(xml)、COCO(json)、YOLO(txt)三种格式标签,分文件夹存放,拿到手就能直接喂给 YOLO 系列。它适合三类人:刚入门目标检测、想跑通第一个自定义数据集的新手;需要快速验证某个改进点(比如换 head、加注意力)但懒得重新标数据的老手;以及做树叶计数、冠层分析、病虫害区域定位这类落地任务、需要一份干净基线数据的工程师。配套还塞了环境搭建、训练教程和划分脚本,Windows 和 Linux 两套都有,等于把「从装环境到出结果」这条链路铺平了。
2. 三格式标签到底怎么选:VOC、COCO、YOLO 的差异与转换逻辑
2.1 三种格式的坐标系差异,先搞懂再动手
很多人拿到压缩包第一反应是「三个文件夹,随便挑一个用呗」,结果训练时报坐标越界或者框全跑到左上角。根子在于三种格式的坐标定义根本不是一回事。VOC 的 xml 存的是绝对像素坐标xmin, ymin, xmax, ymax,原点在左上角;COCO 的 json 存的是[x, y, width, height],同样是绝对像素,但它是左上角点加宽高;YOLO 的 txt 存的是归一化后的x_center, y_center, width, height,全部除以图片宽高,落在 0 到 1 之间。你如果直接把 VOC 的绝对坐标塞进 YOLO 的标签文件,训练时损失函数会直接爆炸,因为网络期望的是 0~1 的值。
这份数据集把三种格式分开存放,就是让你按框架选,而不是自己转。常见做法是:用 Ultralytics 的 YOLOv5/v8/v11 就选 yolo 格式的 txt;用 Detectron2 或者 MMDetection 就选 COCO 的 json;用早期 Darknet 或者某些老教程就选 VOC 的 xml。我一般会先确认训练框架的 dataloader 读哪种,再决定用哪个文件夹,避免中间多一次转换引入误差。
2.2 用脚本验证标签与图片是否一一对应
拿到数据集别急着开训,先跑一遍一致性检查。下面这段脚本我每次拿到新数据集都会跑,专门查图片和标签是否配对、坐标是否越界。
import os from pathlib import Path from PIL import Image img_dir = Path("images") # 图片目录 lbl_dir = Path("labels") # YOLO txt 标签目录 img_files = {p.stem for p in img_dir.glob("*.jpg")} lbl_files = {p.stem for p in lbl_dir.glob("*.txt")} # 1. 检查是否有图片没标签,或标签没图片 missing_lbl = img_files - lbl_files missing_img = lbl_files - img_files print(f"缺标签的图片: {len(missing_lbl)} 张") print(f"缺图片的标签: {len(missing_img)} 个") # 2. 检查 YOLO 坐标是否越界 bad = [] for txt in lbl_dir.glob("*.txt"): for line in txt.read_text().strip().splitlines(): parts = line.split() if len(parts) != 5: bad.append((txt.name, "字段数不对")) continue cls, x, y, w, h = parts vals = list(map(float, [x, y, w, h])) if any(v < 0 or v > 1 for v in vals): bad.append((txt.name, f"坐标越界: {vals}")) print(f"异常标签: {len(bad)} 个") for b in bad[:10]: print(b)逻辑说明:第一步用集合差集找出图片和标签不匹配的情况,这是最常见的低级错误,尤其是手动删过图之后。第二步逐行读 YOLO txt,检查每行是不是 5 个字段(类别 + 4 个归一化坐标),再判断坐标是否落在 0~1。参数上,img_dir和lbl_dir按你实际解压后的路径改,图片扩展名如果是 png 就把*.jpg换掉。跑完如果异常数为 0,说明这份数据是干净的,可以放心进入划分环节。
2.3 划分脚本怎么用:train/val/test 三种切法
压缩包里给了三个划分脚本,名字分别是「训练集、验证集、测试集划分脚本」「训练集、验证集划分脚本」和「split_train_val 生成 ImageSets 下 txt 文件划分脚本」。前两个是把图片和标签复制到新文件夹,第三个是生成 VOC 风格的 ImageSets txt 索引。我一般用第一个做三划分,因为验证集和测试集分开能更真实地反映泛化能力。
# 典型调用方式(按脚本内 argparse 参数调整) python 训练集、验证集、测试集划分脚本.py \ --images_dir ./images \ --labels_dir ./labels \ --output_dir ./dataset_split \ --train_ratio 0.7 \ --val_ratio 0.2 \ --test_ratio 0.1 \ --seed 42逻辑说明:脚本按比例把图片和对应标签复制到dataset_split/train、val、test三个子目录,保证图片和标签同步移动,不会出现「图在 train、标签在 val」的错位。参数上,三个比例加起来必须等于 1,seed固定随机种子保证可复现。注意 1000 张的规模下,test 给 0.1 就是 100 张,够做一次最终评估;如果数据更少,建议改成 8:1:1 甚至 8:2:0,把验证集当测试集用,别为了凑三划分把训练集压得太小。
3. 从环境搭建到跑通训练:Windows 与 Linux 两条路
3.1 环境搭建的关键版本约束
配套教程分了 Windows 和 Linux 两版,还单独给了 Ubuntu 安装教程。我踩过的坑是:教程里的 CUDA 版本和你显卡驱动不匹配,装完 torch 之后torch.cuda.is_available()返回 False。常见做法是先nvidia-smi看驱动支持的最高 CUDA 版本,再去 PyTorch 官网找对应命令,别直接抄教程里的pip install torch。
# Linux 下确认 GPU 与 CUDA nvidia-smi # 输出右上角 CUDA Version 是驱动支持上限,安装的 torch 不能超过它 # 创建独立环境,避免污染系统 Python conda create -n leaf_yolo python=3.9 -y conda activate leaf_yolo # 按官网命令装 torch,示例(以实际驱动为准) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 验证 python -c "import torch; print(torch.cuda.is_available())"逻辑说明:nvidia-smi给出的 CUDA Version 是驱动能支持的最高运行时版本,你装的 PyTorch 自带 CUDA runtime,只要不超过这个上限就行。用 conda 建独立环境是为了避免和系统里其他项目的依赖打架,这个习惯能省掉大量「昨天还能跑今天报错」的玄学问题。最后那行验证必须返回 True,否则后面训练会默默跑在 CPU 上,速度差几十倍。
3.2 按教程改配置训练自己的数据集
教程的核心是「根据案例修改训练自己的数据集」,也就是把官方示例的 data yaml 和模型配置改成指向你的树叶数据。以 Ultralytics YOLOv8 为例,你需要新建一个leaf.yaml:
# leaf.yaml path: ./dataset_split # 数据集根目录 train: train/images # 训练图片相对路径 val: val/images # 验证图片相对路径 test: test/images # 测试图片相对路径 nc: 1 # 类别数,树叶分类按你的实际类别改 names: ['leaf'] # 类别名,顺序要和标签里的 class id 对应逻辑说明:path是根目录,下面的 train/val/test 都是相对它的路径,这样换机器只要改一处。nc是类别数量,如果你标了多种树叶就改成对应数字,names列表的顺序必须和标注时用的类别 id 一致,否则模型学出来的类别会张冠李戴。改完 yaml 就可以起训:
yolo detect train \ data=leaf.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ device=0参数上,model用预训练权重能明显加快收敛,imgsz=640是通用起点,显存不够就降到 416 或 320,batch跟着显存调,device=0指定第一块 GPU。1000 张数据用 yolov8n 大概几十分钟能跑完 100 轮,具体看卡。
3.3 训练日志里该盯哪几个指标
跑起来之后别只等最后结果,训练日志里有几个信号要实时看。box_loss和cls_loss应该整体下降,如果 cls_loss 一直不降,多半是类别标签对不上或者类别不平衡。mAP50 在验证集上应该稳步上升,如果训练集 mAP 很高但验证集上不去,就是过拟合,考虑加数据增强或者减模型容量。我一般会在前 10 轮确认 loss 在降,中间看 mAP 曲线有没有平台期,最后看混淆矩阵确认有没有把某一类全预测成另一类。
4. 避坑与排查:树叶数据集训练最容易翻车的五个地方
4.1 现象:训练一开始 loss 就是 nan
原因:YOLO 标签坐标没归一化,或者 txt 里混进了绝对像素值。这份数据集虽然给了正确的 yolo 格式,但如果你自己用 VOC 转的时候忘了除以宽高,就会这样。解决:用 2.2 的检查脚本跑一遍,确认所有坐标都在 0~1,越界的重新生成。
4.2 现象:mAP 一直是 0,模型什么都没学到
原因:data yaml 里的names顺序和标签里的 class id 对不上,或者nc写成了 0。解决:打开一个 txt 看第一个数字是几,那就是 class id,确保names列表长度等于nc且索引对应。树叶数据集如果只有一类,nc: 1、names: ['leaf'],别写成 80。
4.3 现象:验证集图片加载报错,提示找不到文件
原因:划分脚本复制图片时路径层级和 yaml 里写的不一致。比如脚本输出是dataset_split/train/images/xxx.jpg,而 yaml 里写的是train/xxx.jpg。解决:ls一下实际目录结构,yaml 里的 train 路径要指到包含图片的那一层,通常是train/images。
4.4 现象:显存溢出,batch 调到 1 还是 OOM
原因:imgsz太大,或者没开混合精度。1000 张图不算多,但 640 分辨率下 batch 16 在 8G 卡上可能吃紧。解决:先把imgsz降到 416,或者加amp=True开自动混合精度,再不行换更小的模型(yolov8n 已经很小了,可以考虑 nano 级别)。
4.5 现象:训练集指标很好,换一批新图就崩
原因:1000 张真实场景图虽然场景丰富,但如果你的测试场景和训练集分布差太多(比如训练全是晴天、测试全是阴天),泛化就是会掉。解决:这不是脚本能修的,属于数据层面问题。常见做法是把新场景的图补进训练集,或者用更强的数据增强(HSV 抖动、随机遮挡)提升鲁棒性。别指望一个数据集包打天下。
5. 进阶玩法:用这份数据做迁移学习和改进验证
跑通基线只是开始,这份数据集真正的价值在于它够干净、够小,适合快速验证想法。我一般会拿它做两件事:一是迁移学习对比,二是改进模块的消融实验。
迁移学习方面,你可以冻结 backbone 只训 head,看小数据下能不能更快收敛。以 YOLOv8 为例,冻结前 10 层:
yolo detect train \ data=leaf.yaml \ model=yolov8n.pt \ epochs=50 \ freeze=10 \ lr0=0.001freeze=10表示冻结前 10 层,lr0是初始学习率,冻结训练时学习率可以适当调小。对比全量微调,冻结版在小数据上往往更稳,不容易过拟合。
改进验证方面,如果你在试新的 head 或者注意力模块,直接换模型结构文件,数据侧不用动。1000 张的规模下,一次消融实验几十分钟就能出结果,迭代速度很快。验证方法上,我习惯固定随机种子跑三次取平均 mAP,单次结果波动可能有 1~2 个点,别被一次跑高就下结论。
还有个实用技巧:把 test 集单独留出来,每次改完只在 val 上调参,最后用 test 跑一次最终数字。我见过太多人反复在 test 上调,最后报出来的指标虚高,换真实场景就露馅。从那以后我每次划分数据集都强制把 test 锁死,不到最后不碰。希望这份数据和脚本能帮你把树叶检测这条链路快速跑通,少走我当年那些弯路。
本文还有配套的精品资源,点击获取