资讯动态

6849张杂草检测数据集:YOLOv8实战训练与避坑指南

发布时间:2026/10/18 13:11:21 来源:尧图企业网站定制
简介面向目标检测与农业智能化场景YOLO杂草检测数据集适用于训练和验证YOLOv5/v7/v8/v9/v10/v11等系列模型帮助学习者快速上手农业环境下的目标识别与杂草定位。压缩包共2000个文件以xml标注文件为主要形式整体大小约236.6MB数据已划分为训练、验证等子集并附带可直接修改的data.yaml配置。标注同时提供YOLO格式txt和VOC格式xml两套文件分别存入独立目录YOLO格式记录类别索引及归一化后的中心点、宽高比例VOC格式则保留标准边界框信息便于在主流检测框架中切换使用。已有201人学习下载。数据整体适合模型训练、精度对比以及农业自动化项目的前期验证可降低数据准备成本无论是首次接触YOLO的初学者还是需要快速验证模型效果的开发者都能基于该数据集直接开展实验。1. 杂草检测数据集拿到6849张图后的第一件事不是训练做yolo系列算法目标检测数据集踩坑的人都有一个共同体验找数据集不难难的是拿到手后还要清洗标签、统一格式、手动划分训练验证集。这份杂草检测数据集把这几步都省了6849张图像连同yolo格式和voc格式的标签一起打包train和val已经切好data.yaml也配置好了。它要解决的是你从零开始训练一个杂草识别模型最耗时间的标注与格式问题适合正在做农业场景检测、想用yolov5到yolo11快速验证算法效果的开发者。但别急着把压缩包丢给训练脚本我接下来说的几件事会直接决定你是3小时跑出可用模型还是花一整天在debug标签格式。2. 数据集的真实构成两种标签格式、目录结构与data.yaml逐项拆解2.1 解压之后先看目录结构这份资源解压后的标准布局是下面这个样子我建议你先对照自己的目录复核一遍别急着往训练工程里塞. ├── data.yaml ├── images/ │ ├── train/ │ │ ├── img_0631_937.jpg │ │ ├── img_0631_942.jpg │ │ └── ... │ ├── val/ │ │ ├── img_0631_3137.jpg │ │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_0631_937.txt │ │ └── ... │ ├── val/ │ │ ├── img_0631_3137.txt │ │ └── ... ├── voc_labels/ │ ├── train/ │ │ ├── img_0631_937.xml │ │ └── ... │ └── val/ │ └── ...img_0631_937.xml 这类文件对应的就是 images 下同名 jpg 的 Pascal VOC 标注txt 则是同内容的 yolo 标注。重点在于train 和 val 在 images、labels、voc_labels 三个目录里是同步划分的xml 和 txt 的文件名必须与 jpg 完全一致后缀不同而已。常见做法是训练时只用 labels 下的 txt 文件voc_labels 留作参考或二次校验。不要同时把两个标签目录都指给训练脚本否则 yolo 会读进重复标签轻则警告重则训练崩。我一般会先写一行命令统计标签数量确保 txt 与 jpg 一一对应find images/train -name *.jpg | wc -l find labels/train -name *.txt | wc -l如果两边数量不一致说明解压或划分环节出了问题。常见坑是压缩包嵌套了一层目录导致脚本按相对路径找不到文件。先把目录结构理顺后面训练才不折腾。这一类数据集下载资源里目录层级是最容易被忽视的隐性坑很多人栽过。2.2 两种标签格式逐行对照yolo 归一化坐标与 voc 绝对坐标打开任意一个 txt 文件内容大概是这样的三行0 0.511719 0.361547 0.153385 0.401042 0 0.289844 0.575000 0.231250 0.636667 0 0.724219 0.851042 0.203385 0.270417每行表示一个目标框class 类别索引从0开始、x_center、y_center、width、height。所有坐标值都是相对图像宽高的比例范围在0到1之间。比如第一个框中心点x是图像宽度的51.17%也就是约一半位置框宽是图像宽度的15.34%。对应的 xml 里长这样annotation folderimages/folder filenameimg_0631_937.jpg/filename size width1280/width height720/height depth3/depth /size object nameweed/name bndbox xmin342/xmin ymin143/ymin xmax531/xmax ymax438/ymax /bndbox /object /annotationxml 里是绝对像素坐标xmin、ymin 是左上角xmax、ymax 是右下角。从 voc 转 yolo 需要做一次归一化核心公式就四句x_center (xmin xmax) / 2 / width y_center (ymin ymax) / 2 / height w (xmax - xmin) / width h (ymax - ymin) / heightwidth 和 height 取自 xml 的 size 节点。很多人会把 xmin、ymin 直接当成 x_center、y_center 用或者忘记除以宽高训练时 loss 直接不收敛。这份资源把两种格式都备齐了正好可以做交叉验证用上面的公式把 xml 转成 txt看是否和你手里的 txt 一致既练了格式转换又验了数据质量。2.3 data.yaml 里的关键配置项逐个说data.yaml 是 yolov5、v7、v8、v9、v10、yolo11 共用的数据配置入口。打开它你看到的是这样一个模板path: /path/to/your/weed_dataset # 数据集根目录路径 train: images/train val: images/val test: images/test # 可选字段 names: 0: weed先用最简单的一句话解释这套结构的约定yolo 训练时会根据 train 字段找到图片目录然后在同级的 labels 目录下寻找对应 txt。也就是 images/train 对应 labels/train。如果你的 labels 目录名不是 labels或者被嵌套了一层就会报 no labels found。三个字段的值要留意。path 是根目录我一般写成绝对路径尤其是多人协作或跨机器跑的时候相对路径很容易因为工作目录不同而全部失效。Windows 用户不要直接复制反斜杠路径填进 yaml建议把 path 写成正斜杠的绝对路径比如 D:/weed_dataset。train 和 val 是从 path 出发的相对路径写法只有 images/train没有斜杠开头或盘符。names 这个字典是重点索引必须与 txt 文件里的 class 数字严格对齐。这份数据集只有一个类别 weed索引0对应杂草。如果你的复制版本里还有作物类names 会写成 0: weed, 1: crop这时 txt 里第二个字段如果是1就代表作物训练前务必确认索引语义。使用这份数据集前我建议你手动加载一下 yaml打印出 train、val 的实际长度确认数据量符合预期。这一步花半分钟能避免后面训练跑了几十分钟才发现 val 是空的import yaml from pathlib import Path with open(data.yaml, r, encodingutf-8) as f: cfg yaml.safe_load(f) base Path(cfg[path]) for split in [train, val]: img_dir base / cfg[split] count len(list(img_dir.glob(*.jpg))) print(split, count)如果 val 打印出来是0要么是划分时没放文件要么是 yaml 里 val 路径写错了。224张这类故障我看到过太多次。数据集已经划分好的好处就在这里你只需要验证不用自己切分但验证这一步不能跳过。3. 用yolov8实测训练环境准备、标签校验与训练参数明细3.1 环境安装与工程目录我一般在中专门跑yolo训练避免把核心环境弄乱。基于这份数据集推荐用 python3.10 建环境然后安装固定版本的 ultralyticsconda create -n weed python3.10 -y conda activate weed pip install ultralytics8.2.0为什么指定 8.2.0 而不是 latest因为新版本对 yolo 模型结构有过调整某些小版本会把预训练权重格式改掉旧权重报 key mismatch导致你从coco迁移来的 pretrain 失效。固定一个验证过的版本配合 yolov8n.pt 和 yolov8m.pt 都不会出问题。如果手里是显卡比较普通的机器yolov8n 是起步配置m 适合有8G以上显存的情况逐个试。数据集不需要拷到 ultralytics 工程里只要 data.yaml 的 path 写对训练脚本就能找到。常见的做法是把数据集放在项目同级目录mkdir weed_project cd weed_project # 把解压好的 weed_dataset 放到这个目录下 tree -L 1然后你看到的 weed_project 里应该有 data.yaml、images、labels、voc_labels 四个顶层内容。这样写路径时不容易产生层级错乱也方便随时回头看 voc 标签。3.2 训练前强制做一次标签内容校验解压后的数据不代表完全不存在脏数据。我习惯写一段一次性校验脚本把标签缺失、字段数不对、坐标越界三类问题都扫出来from pathlib import Path base Path(weed_dataset) for split in [train, val]: label_dir base / flabels/{split} img_dir base / fimages/{split} for label in sorted(label_dir.glob(*.txt)): # 图片缺失检查 img img_dir / label.with_suffix(.jpg) if not img.exists(): print(fmissing img: {img}) # 标签行格式检查 with label.open() as f: for line_no, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: print(fbad column: {label}:{line_no}) continue cls int(parts[0]) x_center, y_center, w, h map(float, parts[1:]) if cls 0: print(fnegative class: {label}:{line_no}) if w 0 or h 0 or w 1 or h 1: print(fbbox out of range: {label}:{line_no})这段脚本会逐个检查 labels/train 和 labels/val 下的所有 txt。注意 w 或 h 大于1的情况意味着 bbox 的宽度或高度超过了图像本身通常是 voc 转 yolo 时没有除以 width 和 height或者除以反了。如果发现 out of range返回 voc_labels 里对应的 xml重新按 2.2 的公式转不要直接在 txt 里做小修补。这项校验是这条数据集资源里最值得做的复现步骤。因为 xml 和 txt 两套格式都存在你完全可以随机抽200个文本用公式手工核算坐标确认资源质量。反正它已经划分好你训练出来的模型好坏数据决定一半。我见过有人拿到相同的数据集没做校验直接训结果发现6000多张里只有80%的图像有标签剩下的空跑一遍花费的时间没法后悔。3.3 训练命令与关键参数明细校验通过后可以开始训练。以 yolov8n 为例yolo train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16 device0 patience20 save_dirruns/weed这条命令的参数逐个拆开说。datadata.yaml 指向刚才校验过的配置modelyolov8n.pt 是从coco预训练权重开始的迁移学习杂草这类目标与常规物体差异较大但底层特征依然能复用比从头训练快很多。epochs100 是上限配合 patience20 表示连续20个epoch在验证集上mAP没提升就早停实际跑完可能只到60个epoch左右。imgsz640 是标准输入尺寸如果你的图像是1280宽建议把imgsz也提到1280但要相应调小 batch。batch16 在8G显存下跑n没问题m或l模型要降到8或4。device0 指定GPU如果只有CPU则改成 devicecpu但训练速度会慢到难以接受。save_dir 要把每次实验输出放到独立目录避免 later 混淆不同参数下的结果。如果希望在 jupyter 或 python 脚本里控制训练等价写法是from ultralytics import YOLO model YOLO(yolov8n.yaml).load(yolov8n.pt) results model.train( datadata.yaml, epochs100, imgsz640, batch16, patience20, save_dirruns/weed, )注意这里用的是 yolov8n.yaml 初始化网络结构再 load 预训练权重。普通新手最容易写错的版本是直接写YOLO(yolov8n.pt)这样会把预训练权重里的80个类别结构带进你的杂草任务到训练时报类别数不匹配或者输出头多余。用 yaml 初始化再到 pt 里加载权重模型输出头会自动变成你的类别数也就是 names 里定义的1类。训练过程中的增强配置也值得调。杂草检测常见的问题是叶片遮挡、光照变化可以在训练参数里显式打开yolo train ... fliplr0.5 flipud0.0 mosaic1.0fliplr0.5 表示水平翻转50%概率flipud 不建议开因为农田里杂草不会倒着长开多了干扰语义。mosaic1.0 在 yolo 里默认开启它把四张图拼成一张训练能在数据集有限的情况下极大丰富小目标样本组合对杂草这类密集小目标很有用。3.4 训练日志里的关键曲线怎么看训练启动后ultralytics 会在 save_dir 下生成 weights/best.pt 和 weights/last.pt同时不断写出 results.csv。我习惯随时用命令看尾部tail -f runs/weed/results.csvcsv 里核心字段与含义可以按下表速查字段名含义我关注的点train/box_loss训练集边框损失应逐步下降不降说明学习率或数据问题val/box_loss验证集边框损失若先降后升说明开始过拟合val/cls_loss验证集分类损失类别少时该值应很快接近0metrics/mAP50(B)IoU0.5 的平均精度我评估模型可用的首要指标metrics/mAP50-95(B)更严格的 mAP追求精度时关注波动大是正常的如果你发现 mAP50 始终为0但 loss 在下降优先怀疑标签类别索引对不上 names。其次检查数据集中是否有大量超出图像边界的框这些框会让网络学不到正样本。翻车现场非常多细节会在第5章展开。这一轮训练跑完你会拿到 best.pt。接下来要做的不是直接部署而是先评估它在 val 上的具体表现找到漏检的重灾区是哪些图像这决定了你的阈值怎么选、需不需要换更大模型。4. 交叉验证与模型评估mAP的读法、混淆矩阵形态与多版本切换注意点4.1 评估指标速读与阈值选择训练结束后用 best.pt 对 val 集做一次推断并产生指标报告yolo val modelruns/weed/weights/best.pt datadata.yaml结果里会看到 mAP50、mAP50-95、precision、recall。杂草检测这类农田场景我第一看 mAP50因为杂草框不需要覆盖到像素级只要框住主要叶片区域后续机械除草或喷洒都能用。mAP50-95 更严格它要求预测框与真实框的 IoU 从0.5到0.95逐步提高对框位置的精确度很敏感用于比较算法调优时更有效。对于这份数据集如果 mAP50 在0.7以上属于可用的状态。0.5到0.7说明存在较多漏检或误检。0.5以下需要回到数据层面排查。conf 阈值也会影响最终表现yolo val 默认 conf0.001 是极端宽松的评估方式适合计算 mAP如果你部署时用 conf0.5实际看到的数量会少很多。我一般会在 val 上多跑几个阈值对比yolo val modelbest.pt datadata.yaml conf0.25 yolo val modelbest.pt datadata.yaml conf0.5观察阈值提高后 precision 和 recall 的平衡点。杂草密集时 bias 是 recall 优先适当放宽到 conf0.25宁可多框几个冗余区域不能漏掉重度杂草区。4.2 混淆矩阵与预测图案例排查ultralytics 会在验证输出目录生成 confusion_matrix.png。对于单类别检测你会发现矩阵只有4个象限真阳性、假阴性、假阳性、背景误检。这个矩阵能直接告诉你漏检高不高。如果左下角的假阴性数值明显偏高说明大量真实杂草框没被预测出来可能原因一是小目标太多二是框太小在缩放到640时特征消失。然后看 val 集对应的预测图保存通常在 save_dir/val_batch0_pred.jpg。这些图上绿色框是真实标注红色或蓝色框是预测。对比两套框的位置你会直观看到问题集中在密集小草区域还是叶片重叠区域。我通常会挑选20张预测图翻一遍这个步骤虽然原始却比任何指标分析都能发现问题。4.3 换yolov5、v7、v10、yolo11时的三个注意点这份数据集因为同时提供 yolo 和 voc 两种标签实际在迁移到不同版本时都具备基础条件但换版本有三个坑值得先说。第一个是训练入口差异。yolov5 官方仓库用 train.py 加 --data data.yaml不带 yolo 命令yolov8/v10/yolo11 用 ultralytics 的 yolo train 命令。yolov7 则要求标签目录必须严格包含 train 和 val 子目录并且不自动在 labels 下类推如果你的路径层级不同它会直接报错找不到标签。第二个是预训练权重的类别数对齐。从 yolov8 迁移到 yolov11 时直接用 yolo11n.pt 迁移没问题但若把 yolov8 训练得到的 best.pt 交给 yolov7 加载会涉及结构改动基本没意义。换版本后应重新加载官方预训练权重从零迁移学习不要指望跨版本权重直接晋升。第三个点是 anchor 配置。yolov5 和 v7 里有默认 anchor针对coco数据粒度设计的。杂草目标普遍小默认 anchor 可能不合适。v8 及以后是 anchor-free基本不用管。如果你用 v5/v7 训练后发现框偏大或偏移优先检查 imgsz把输入尺寸从640提到960或1280小目标框对齐会有显著改善。这就是为什么我总说数据准备好算法版本的迁移成本集中在超参数调整。完成评估和版本选择后模型基本稳定了。接下来要说的这些避坑经验是你在实际使用时最容易踩到、且会白白消耗时间的部分。5. 避坑杂草检测数据集最容易误的事故现场5.1 现象txt 文件存在但训练时一直报 no labels found训练一启动就报“找不到标签”去 labels 目录看文件明明都在。原因通常是目录结构和 ultralytics 的约定不一致。它默认在图片目录同级的 labels 下找标签也就是 images/train 对应 labels/train。如果你把标签放在了 images/train_labels 这类自定义目录里即使 data.yaml 只写了 images/train它也不会去找自定义路径。解决的办法是先按第2章的标准目录重新整理或者把 data.yaml 里的 train 改成指向包含标签结构的父目录并同时修改 labels 路径。最常见的做法是把 labels 作为 images 的同级目录保持默认约定。我从那次之后任何数据集到手第一眼就是看 labels 目录位置根本不看那些花哨的 README。5.2 现象loss 正常下降但 mAP 始终为零预测框全部空白训练过程看起来很正常损失也降了但到 val 阶段 mAP 是零输出的预测图上一片空白。核查标签时才发现 txt 里的类别索引写的是 1而 data.yaml 的 names 只有 0: weed。原因是类别索引没有从0开始。yolo 里的类别索引是绝对的names 字典定义了0对应weed你却给了1于是所有样本都落在一个模型根本不认识的类别上。解决方法是把 txt 里的第一个字段统一改成0或保留1但 names 里同时补上1的空类别。最好用脚本批量改成0因为这本来就是单类别问题。养成训练前统计类别索引的习惯awk {print $1} labels/train/*.txt | sort | uniq -c看到最大索引超过 names 长度再减一就该停手检查了。5.3 现象voc 格式转换后部分 bbox 位置偏移跑到图像外面你在二次开发时想重新生成 txt把 xml 里的 xmin、ymin、xmax、ymax 代入公式后发现部分框的中心坐标大于1或宽高大于1。原因是原始 xml 的部分边界框超出了图像尺寸比如 xmax 写的是 1290但图像宽只有 1280。标注软件允许画出图像边缘外的框转换脚本却没有做裁剪。解决是在转换时对边界做裁剪确保 xmax 不超过 width-1、ymax 不超过 height-1xmax min(xmax, width - 1) ymax min(ymax, height - 1)之后再归一化。这份数据集本身已经转换好了大概率不会出现这种问题但如果你自己扩展标注或从其它资源合并图像时一定记得这一步。边界框超出图像范围在训练时会让模型学习到错误的坐标分布。5.4 现象训练中途报 CUDA out of memory显存不足是训练时最常见的报错特征很明显训练几个 batch 后直接崩掉。原因多数是 imgsz 和 batch 的组合超出了显卡显存。用这份数据集的图像是 1280 宽你强行用 imgsz1280 且 batch168G显卡直接扛不住。解决思路是先减 batch从8降到4再不行降到2。降到2后还崩才考虑换更小模型或减小 imgsz。另一个补救是同时打开训练参数:yolo train ... batch8 accumulate2accumulate2 表示每2个batch累计一次梯度等效于 batch16 的效果但显存占用只有 batch8 的水平。这个参数很多人不知道遇到显存不足先想到缩小 batch而不是调整累计步数。5.5 现象训练完评估时 val 集是空的数据集已经划分好但你训练时发现验证后指标全无。经验总会出现 val 目录下文件数量为0。原因可能是解压时 val 文件夹没被正常解压出来或者 data.yaml 里 val 路径指向了 test 的目录。解决方法是进入 images/val 和 labels/val 分别数文件确认数量大于0。如果在 Windows 下解压 zip偶尔会出现某些长文件名无法解压的问题比如 img_0631_5586.xml 这类文件名超长容易被截断导致对应 jpg 找不到标签。解决办法是用解压工具兼容的短路径重解压或者把数据集放到磁盘根目录例如 D:/weed_dataset避免前面叠加太深的目录前缀。6. 从检测到实用杂草小目标的切片推理优化技巧训练得到最佳模型之后拿整张原图直接推理往往表现就不错但当杂草目标比较小比如图像里每株草只占二三十像素时把整幅图缩放到 640 输入小目标基本被压缩到模糊。我验证过多次把 1280 宽的大图直接丢给模型与切成四块分别推理再合并结果后者在小目标上的召回率明显更高。具体实现不复杂核心是把原图切块推理后再做坐标还原from ultralytics import YOLO import cv2 model YOLO(runs/weed/weights/best.pt) img cv2.imread(field_sample.jpg) h, w img.shape[:2] crop_size 640 stride 480 # 重叠区域避免目标被切分 detections [] for y in range(0, h, stride): for x in range(0, w, stride): crop img[y:ycrop_size, x:xcrop_size] results model(crop, conf0.25, iou0.45) for box in results[0].boxes.data.cpu().numpy(): x1, y1, x2, y2, score, cls box detections.append([x x1, y y1, x x2, y y2, score, cls])切片尺寸取训练时的 imgsz这里用 640。步长设为 480让相邻切片有160像素的重叠保证横跨切分线的大目标在两边都完整出现。推理时每个切片独立调用模型得到的是局部坐标所以还原时要加上切片起点坐标也就是代码里的 x 和 y。合并结果后可以用 NMS 把重叠区域的重复框合并简单方式是对同一类别的检测框做贪心去重或者把结果直接存入列表后统一应用 cv2.dnn.NMSBoxes。这种切片策略有两个适用前提一是原图分辨率显著大于训练尺寸二是目标占图像面积比例小且呈均匀分布。如果你的场景是整幅图像本身就不大或目标已经占了半个画面切片反而会破坏语义让目标变形此时不建议用。我实际跑农田航拍图时用的比较多地块大的没边3600万像素的图缩到640杂草直接小成一个点切片是唯一有效解。这个方法还有个副产品你能看到模型在每个局部区块的独立预测置信度从而快速定位哪些区域是难例。比如长期阴影下的杂草单独切出来的置信度总是低于0.2那就知道下一轮训练要补充阴影条件下的样本或者调高图像增强里的亮度扰动强度。从那以后我每次部署杂草检测模型都强制走一遍切片推理验证先跑几十张代表性场景图确认小目标召回率不存在明显洼地再进正式流程。整套数据资源和切片验证脚本配合起来模型从训练到落地的时间能压缩一大截。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑