ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

YOLO树叶分类检测数据集:1000张图+VOC/COCO/YOLO标签+划分脚本+训练教程

YOLO树叶分类检测数据集:1000张图+VOC/COCO/YOLO标签+划分脚本+训练教程 简介这是一份面向目标检测初学者与算法工程师的YOLO树叶分类检测数据集针对真实场景下树叶类别识别任务解决自建数据集标注成本高、格式转换繁琐的问题。资源包共2000个文件约27.93MB包含1000张高质量实拍图片以及vocxml、cocojson和yolotxt三种格式标签分别存放于不同文件夹可直接接入YOLO系列模型训练另附yaml配置文件、数据集划分脚本与训练教程文档方便按需切分训练集、验证集和测试集。已有470人学习下载适合课程设计、科研实验与竞赛练手。读者可获得一套开箱即用的标注数据、多格式标签转换参考、环境搭建与训练案例说明以及可复用的划分脚本帮助快速跑通从数据准备到模型训练的全流程。1. 树叶分类检测数据集到底解决什么问题从 1000 张图到三种标签格式拿到「YOLO树叶分类目标检测数据集(含1000张图片)对应voc、coco和yolo三种格式标签划分脚本训练教程」这个标题很多人第一反应是「又一个数据集包」。但真正做过树叶识别项目的人知道难点从来不是模型结构而是数据这一层树叶类别细、类间差异小、背景杂乱、标注框容易画歪最后训练出来的模型在验证集上 mAP 看着还行一到真实场景就集体翻车。这个数据集的价值在于它把「图片 三种格式标签 划分脚本 训练教程」打包成一条完整链路省掉了从零标注和格式转换的时间。它适合三类人一是刚接触 YOLO 目标检测、想找一个类别明确的小数据集跑通全流程的新手二是做植物识别、林业调查、农业病虫害相关项目需要树叶检测作为前置模块的从业者三是想验证自己改进的 YOLO 结构比如小目标检测、注意力机制在细粒度类别上是否有效的研究者。1000 张图不算多但足够跑通一次完整的训练-验证-推理闭环也足够暴露数据层面的坑。下面按「数据长什么样 → 怎么转格式 → 怎么划分 → 怎么训练 → 怎么避坑」的顺序拆开讲。2. 三种标签格式的差异与转换VOC、COCO、YOLO 到底该用哪个2.1 三种格式的字段结构和适用场景VOC 格式是 XML 文件每个图片对应一个 XML里面用object标签记录类别名和xmin/ymin/xmax/ymax四个坐标。它的优点是可读性强LabelImg 默认就输出这个格式人工检查标注质量时最方便。缺点是文件数量翻倍1000 张图就是 1000 个 XML批量处理时 IO 开销大。COCO 格式是一个大的 JSON 文件所有图片、标注、类别都塞在一个annotations.json里。它的bbox是[x, y, width, height]注意是左上角坐标加宽高不是右下角坐标。COCO 适合做多任务检测分割关键点也是很多预训练模型的默认输入格式但单文件体积大改一个标注要重写整个 JSON。YOLO 格式是每张图对应一个.txt每行是class_id x_center y_center width height全部归一化到 0~1。它最轻量训练时读取最快但可读性差类别用数字索引表示必须配合classes.txt或data.yaml才能知道数字对应什么树叶。格式文件形态坐标表示优点缺点VOC每图一个 XMLxmin/ymin/xmax/ymax可读性好工具支持广文件多IO 慢COCO单个 JSONx/y/width/height多任务统一生态好单文件大改标注麻烦YOLO每图一个 txt归一化中心点宽高轻量训练读取快可读性差需类别映射2.2 用脚本在三种格式之间转换实际项目里最常见的需求是标注工具输出 VOC但训练要用 YOLO中间可能还要转一份 COCO 给别的模型用。下面这个脚本把 VOC 转成 YOLO同时生成classes.txt。import os import xml.etree.ElementTree as ET # 类别列表顺序决定 class_id必须和训练时的 data.yaml 一致 CLASSES [leaf_type_a, leaf_type_b, leaf_type_c] def voc_to_yolo(xml_dir, out_dir, classes): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue # 跳过不在类别表里的标注避免训练时报错 cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化并转成中心点宽高 x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) out_path os.path.join(out_dir, xml_file.replace(.xml, .txt)) with open(out_path, w) as f: f.write(\n.join(lines)) voc_to_yolo(annotations_xml, labels_yolo, CLASSES)逻辑说明先读 XML 里的图片宽高再把绝对坐标归一化。CLASSES的顺序就是 YOLO 的class_id一旦训练开始就不能改否则类别会错位。参数上xml_dir是 VOC 标注目录out_dir是输出 txt 目录classes必须和数据集实际类别完全一致。如果 XML 里有拼写错误的类别名脚本会跳过训练时那些目标就丢了所以转换后要统计一下每类数量。反过来YOLO 转 COCO 的核心是把所有 txt 聚合成一个 JSON同时生成images、annotations、categories三个数组。这里不展开完整代码但要注意 COCO 的id必须全局唯一image_id和annotation_id不能重复否则评估脚本会报错。2.3 转换后必须做的两项校验第一项是坐标越界检查。归一化后如果出现负数或大于 1 的值说明原始标注框超出了图片边界训练时会被裁掉或报错。用下面这段快速扫一遍import glob bad [] for txt in glob.glob(labels_yolo/*.txt): with open(txt) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: bad.append((txt, i, 字段数不对)) continue vals list(map(float, parts[1:])) if any(v 0 or v 1 for v in vals): bad.append((txt, i, 坐标越界)) print(f异常标注数: {len(bad)}) for b in bad[:10]: print(b)第二项是类别分布统计。1000 张图里如果某一类只有十几张训练时该类几乎学不到mAP 会很难看。统计每类框数后如果发现长尾严重要么补数据要么在data.yaml里给该类加权要么直接合并相近类别。3. 划分脚本怎么写训练集、验证集、测试集的比例和随机种子3.1 为什么不能随便按 8:1:1 切树叶数据集的图片往往来自同一批采集同一棵树的叶子可能连续拍了很多张。如果纯随机划分训练集和验证集里会出现同一棵树的相似图片验证集精度虚高实际部署时性能掉一大截。常见做法是先把图片按「采集批次」或「树种个体」分组再按组划分保证同一组不出现在两个集合里。如果数据集没有分组信息至少固定随机种子让每次划分结果可复现。比例上1000 张图建议 7:2:1 或 8:1:1。验证集不能少于 100 张否则评估指标波动大测试集留 100 张左右只在最后跑一次不要用来调参。3.2 一个可复现的划分脚本import os import random import shutil random.seed(42) # 固定种子保证每次划分一致 img_dir images label_dir labels_yolo out_dir dataset_split train_ratio, val_ratio 0.7, 0.2 images [f for f in os.listdir(img_dir) if f.endswith((.jpg, .png))] random.shuffle(images) n len(images) n_train int(n * train_ratio) n_val int(n * val_ratio) splits { train: images[:n_train], val: images[n_train:n_train n_val], test: images[n_train n_val:] } for split, files in splits.items(): img_out os.path.join(out_dir, split, images) lbl_out os.path.join(out_dir, split, labels) os.makedirs(img_out, exist_okTrue) os.makedirs(lbl_out, exist_okTrue) for img in files: shutil.copy(os.path.join(img_dir, img), os.path.join(img_out, img)) txt os.path.splitext(img)[0] .txt src_txt os.path.join(label_dir, txt) if os.path.exists(src_txt): shutil.copy(src_txt, os.path.join(lbl_out, txt)) else: print(f警告: {txt} 缺失该图无标注)逻辑说明random.seed(42)是后悔药没有它每次跑出来的划分都不一样实验无法对比。shutil.copy保留原文件避免误删。如果某张图没有对应 txt脚本会打印警告这种图要么是负样本可以保留但要在训练配置里允许无标注图要么是漏标需要人工补。参数上train_ratio和val_ratio按需调整剩下的自动归测试集。如果数据集有分组信息把random.shuffle换成按组打乱再展开。3.3 划分后生成 data.yamlYOLO 训练需要一个data.yaml告诉它数据在哪、有几类、类别名是什么path: ./dataset_split train: train/images val: val/images test: test/images nc: 3 names: [leaf_type_a, leaf_type_b, leaf_type_c]nc必须和names长度一致names的顺序必须和转换脚本里的CLASSES完全一致。路径可以用相对路径但建议用绝对路径避免从不同目录启动训练时找不到数据。4. 用 YOLOv8 跑通第一次训练环境、命令和关键参数4.1 环境配置的最小依赖YOLOv8 用 ultralytics 包Python 3.8 以上即可。常见做法是建一个 conda 环境conda create -n leaf_yolo python3.10 -y conda activate leaf_yolo pip install ultralytics如果要用 GPU先确认 CUDA 版本和 PyTorch 匹配。pip install ultralytics会自动装 PyTorch但可能装成 CPU 版。GPU 用户建议先按 PyTorch 官网命令装好对应 CUDA 版本的 torch再装 ultralytics。装完后用yolo checks看环境是否正常它会打印 CUDA 是否可用、版本号等信息。4.2 训练命令和参数含义yolo detect train \ datadataset_split/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/leaf \ nameexp1逐项说明data指向刚才生成的 yamlmodel用预训练权重树叶数据集小从零训练容易过拟合用 COCO 预训练权重迁移学习效果更稳epochs100是上限配合patience20早停验证集 20 轮不提升就停imgsz640是输入尺寸树叶目标通常不大如果图片里叶子占像素很少可以提到 1024但显存占用会翻倍batch16按显存调8G 显存跑 640 大概能到 16不够就降到 8lr00.01是初始学习率小数据集可以降到 0.001 避免震荡。训练过程中重点看三个指标box_loss是否稳定下降、mAP50是否上升、验证集 loss 是否在训练 loss 还在降时提前反弹。如果验证 loss 反弹而训练 loss 继续降就是过拟合要么加数据增强要么减模型复杂度。4.3 推理和置信度门限调整训练完用yolo detect predict跑推理yolo detect predict \ modelruns/leaf/exp1/weights/best.pt \ sourcetest_images \ conf0.25 \ saveTrueconf0.25是置信度门限低于这个值的框不输出。树叶检测里这个值很关键调高到 0.5 会漏掉遮挡或模糊的叶子调低到 0.1 会冒出大量误检。建议在验证集上画一条conf从 0.1 到 0.9 的 Precision-Recall 曲线选 F1 最高的点作为门限。如果业务更怕漏检就选 recall 高的点更怕误检就选 precision 高的点。5. 树叶数据集训练的避坑清单从标注到评估的 5 个翻车现场5.1 标注框贴边导致训练报错现象训练启动几轮后报AssertionError或坐标越界警告loss 变成 NaN。原因VOC 转 YOLO 时某些标注框的xmax等于图片宽度归一化后x_center width/2刚好等于 1浮点误差可能让它略大于 1。解决转换时对坐标做裁剪x_center min(max(x_center, 0), 1)宽高同理或者统一减一个极小值1e-6。5.2 类别名大小写不一致导致类别数翻倍现象data.yaml里写nc: 3但训练日志显示nc: 5或类别索引对不上。原因VOC 标注里同一类叶子有的写Leaf_A有的写leaf_a转换脚本按字符串匹配生成了两个 class_id。解决转换前统一转小写并去空格或者先用脚本统计所有name字段的唯一值人工确认后再生成CLASSES。5.3 验证集 mAP 很高但实际推理全错现象训练完mAP50到 0.9拿真实场景照片推理却几乎检不出。原因划分时没有按采集批次分组验证集图片和训练集高度相似模型只是记住了背景。解决重新按批次或树种个体划分确保验证集里的树在训练集里没出现过。如果做不到至少把验证集换成另一批采集的图片。5.4 小目标叶子被大量漏检现象大叶子检测正常小叶子占图比例小于 1%几乎检不到。原因YOLO 默认下采样到 640 后小目标在特征图上只剩几个像素anchor 匹配不上。解决把imgsz提到 1024 或 1280在data.yaml里开启mosaic和copy_paste增强如果还不行换用带 P2 小目标检测层的模型结构或者把图片切块后再训练。5.5 训练中断后无法续跑现象跑到第 60 轮机器断电重新训练从第 0 轮开始前面的时间白费。原因没有保存 checkpoint 或没指定resume。解决YOLO 默认每轮保存last.pt续跑用yolo detect train resume modelruns/leaf/exp1/weights/last.pt。注意resume会读取原训练的所有参数不要手动改data或model否则可能报错。6. 把 1000 张图用到极致数据增强、交叉验证和类别加权的组合技巧1000 张图在目标检测里属于小数据集直接训容易过拟合。我一般会做三件事第一开启 YOLO 内置的增强组合mosaic1.0、mixup0.1、copy_paste0.1、degrees15、translate0.1、scale0.5。这些参数在data.yaml同级传进去即可比如yolo detect train ... mosaic1.0 mixup0.1。注意mixup太大会让树叶和背景混在一起小数据集上 0.1 到 0.2 比较稳。第二如果类别长尾严重不要只靠增强要在 loss 里给稀有类加权。YOLOv8 默认用cls损失可以通过自定义class_weights传入或者在数据集层面做重采样把稀有类的图片复制多份但复制时只保留稀有类标注其他类删掉避免重复框。更稳妥的做法是分层采样每个 batch 里保证每类至少出现一次。第三用 5 折交叉验证代替单次划分。把 1000 张图按组分成 5 份每次取 4 份训练、1 份验证跑 5 次后取平均 mAP。这样得到的指标更可靠也能看出模型在不同数据子集上的稳定性。代价是训练时间翻 5 倍但小数据集单次训练快总体可接受。最后分享一个我踩过的坑有一次为了提升小目标检测把imgsz从 640 提到 1280结果显存爆了batch 降到 4训练速度慢到无法接受。后来改成先切图再训练把每张原图切成 4 块 640×640 的子图标注框按切图坐标重新计算小目标占比立刻上来了显存也没爆。切图脚本的核心是记录每块的偏移量把原图坐标减去偏移再归一化。这个思路对树叶、病虫害、小目标检测都通用。希望帮到你。本文还有配套的精品资源点击获取
返回列表