简介:这是一份面向YOLO系列目标检测算法学习者的杂草检测数据集,适用于农业场景下的杂草识别与定位任务,可支撑模型训练、验证与测试全流程。数据集共6849张图像并配有标签,已按训练与验证需求划分完毕,同时提供data.yaml配置文件,兼容yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本。压缩包内文件总数2000个,以xml标注文件为主,同时包含yolo格式的txt标签,分别存放于两个文件夹中,yolo标签采用类别索引与归一化中心点、宽高坐标表示,便于直接读取训练。资源包整体约236.6MB,目录结构清晰,方便按格式快速切换与复用。目前已有201人学习下载,适合需要快速搭建杂草检测基线、验证标注格式转换或开展农业视觉实验的开发者与研究人员参考使用。
1. 杂草检测数据集与 YOLO 落地:6849 张带标签图像能跑出什么
田里那点事,最怕的不是草多,是草和苗长得太像。马唐、稗草、狗尾草在幼苗期跟水稻、玉米几乎一个模子,人工背着药桶打一遍,药害和漏喷同时发生。6849 张带标签的杂草图像,价值就在这儿——它把「哪株是草、哪株是苗」这件事变成了可训练的监督信号。YOLO 系列做杂草检测,本质是把田间识别拆成两个动作:先定位,再分类,一次前向就出框。这套组合适合谁?做智慧农业的算法同学、想拿真实数据练 YOLO 训练全流程的工程师、以及需要给变量喷药设备做视觉模块的团队。数据集是起点,不是终点,能不能用、怎么用、坑在哪,下面一层层拆。
2. 杂草数据集拆开看:6849 张图像到底该怎么读
拿到一个压缩包,第一件事不是解压完就train.py,而是先搞清楚里面装的是什么。杂草检测数据集和通用 COCO 最大的区别在于:类别少、背景杂、目标密集且互相遮挡。6849 张这个量级,说大不大,说小也不小——够训一个能收敛的模型,但不够你随便浪费。
2.1 先做数据体检:类别分布、框尺寸与图像分辨率
解压后先别急着划分,用脚本把标注统计一遍。YOLO 格式的标签是每行class x_center y_center width height,全部归一化到 0~1。下面这段脚本能一次性输出类别计数、框的宽高分布和异常框。
import os from collections import Counter import numpy as np label_dir = "labels/train" # 标注目录 img_dir = "images/train" # 图像目录 cls_counter = Counter() wh_list = [] bad_files = [] for name in os.listdir(label_dir): if not name.endswith(".txt"): continue path = os.path.join(label_dir, name) with open(path) as f: lines = [l.strip() for l in f if l.strip()] if len(lines) == 0: bad_files.append(name) # 空标注文件,通常是漏标 continue for line in lines: parts = line.split() if len(parts) != 5: bad_files.append(name) # 格式错误 continue c, x, y, w, h = parts cls_counter[int(c)] += 1 wh_list.append((float(w), float(h))) wh = np.array(wh_list) print("类别分布:", dict(cls_counter)) print("框宽 中位数/均值:", np.median(wh[:,0]), wh[:,0].mean()) print("框高 中位数/均值:", np.median(wh[:,1]), wh[:,1].mean()) print("异常文件数:", len(bad_files))逻辑说明:cls_counter告诉你类别是否均衡,如果某一类占了 80% 以上,训练时就要考虑重采样或类别权重。wh的中位数决定你 anchor 或输入尺寸怎么设——如果中位框宽只有 0.03,说明目标极小,输入 640 可能不够,得考虑 960 或切片推理。bad_files里的空标注文件是血泪经验:很多公开数据集会把「无目标」的负样本留成空 txt,YOLO 训练时会被当成背景,少量可以,多了会让模型学偏。
参数说明:label_dir和img_dir要对应你的实际目录结构,YOLO 默认 images 和 labels 平行。如果标注是 VOC 的 XML,先转格式再跑这段。
2.2 划分训练验证集:别用随机划分糊弄杂草数据
通用做法是 8:1:1 随机划分,但杂草数据有个坑:同一块田、同一时间拍的图高度相似,随机划分会让训练集和验证集出现近乎重复的样本,验证指标虚高,上线就翻车。常见做法是按拍摄批次或地块划分。
import os, random, shutil src_img = "images/all" src_lbl = "labels/all" dst_root = "dataset" random.seed(42) files = [f for f in os.listdir(src_img) if f.lower().endswith((".jpg",".png",".jpeg"))] # 如果文件名里带批次号,比如 batch01_xxx.jpg,按批次分组 groups = {} for f in files: key = f.split("_")[0] if "_" in f else "default" groups.setdefault(key, []).append(f) keys = list(groups.keys()) random.shuffle(keys) n_val = max(1, int(len(keys) * 0.2)) val_keys = set(keys[:n_val]) for split in ["train","val"]: os.makedirs(f"{dst_root}/images/{split}", exist_ok=True) os.makedirs(f"{dst_root}/labels/{split}", exist_ok=True) for f in files: key = f.split("_")[0] if "_" in f else "default" split = "val" if key in val_keys else "train" shutil.copy(os.path.join(src_img, f), f"{dst_root}/images/{split}/{f}") lbl = os.path.splitext(f)[0] + ".txt" if os.path.exists(os.path.join(src_lbl, lbl)): shutil.copy(os.path.join(src_lbl, lbl), f"{dst_root}/labels/{split}/{lbl}")逻辑说明:按文件名前缀分组,保证同一批次整组进训练或验证,避免数据泄漏。如果你的文件名没有批次信息,退而求其次按图像相似度聚类分组,或者至少用hash(f) % 10这种稳定划分而不是每次随机。
参数说明:n_val控制验证集比例,杂草数据建议 15%~20%,因为类别少,验证集太小指标波动大。random.seed固定后结果可复现。
2.3 生成 data.yaml:类别名和路径写错是最常见的低级坑
YOLO 训练靠一个 yaml 描述数据位置和类别。写错路径不会报错,只会让你怀疑人生——loss 不降、mAP 为 0。
# data.yaml path: /home/user/dataset # 数据集根目录,绝对路径最稳 train: images/train val: images/val nc: 4 # 类别数,按你的实际改 names: 0: crabgrass # 马唐 1: barnyardgrass # 稗草 2: goosegrass # 牛筋草 3: crop # 作物(如果标了)逻辑说明:path是根,train/val是相对根的路径。nc必须和 names 数量一致,否则训练直接报索引越界。names 的顺序要和标注里的 class id 严格对应,错一位整个模型就学反了。
参数说明:如果只有杂草一类,nc: 1,names 只写一个。多类时建议把「作物」也标进去,模型学会区分苗和草,误检会明显下降。
3. YOLO 训练杂草检测模型:从环境到收敛的完整链路
数据理顺了,接下来是训练。YOLOv8 是目前杂草检测里最常用的版本,API 干净、文档全、社区坑都踩过了。这一章按「环境配置 → 训练命令 → 参数怎么调 → 指标怎么看」走一遍。
3.1 环境配置:CUDA、PyTorch 和 ultralytics 的版本对齐
环境配置是新手第一道坎。常见做法是用 conda 建独立环境,先装对 CUDA 版本的 PyTorch,再装 ultralytics。
conda create -n weed python=3.10 -y conda activate weed # 按你的显卡驱动选 CUDA 版本,这里以 CUDA 11.8 为例 pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics==8.1.0 pip install opencv-python numpy pyyaml # 验证 python -c "import torch; print(torch.cuda.is_available(), torch.__version__)"逻辑说明:torch.cuda.is_available()返回 True 才算环境通了。如果返回 False,八成是 CUDA 版本和驱动不匹配,或者装成了 CPU 版 torch。ultralytics 版本建议锁死,不同版本 API 有差异,model.train()的参数名会变。
参数说明:CUDA 11.8 对应驱动 520+,CUDA 12.1 对应驱动 530+。显卡是 V100 的话,CUDA 11.8 兼容性最好。别用pip install ultralytics不锁版本,更新后旧脚本可能直接跑不动。
3.2 训练命令与关键参数:epochs、imgsz、batch 怎么定
最小可跑命令就一行,但参数决定成败。
yolo detect train \ data=data.yaml \ model=yolov8s.pt \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.01 \ lrf=0.01 \ patience=30 \ device=0 \ project=runs/weed \ name=exp1逻辑说明:model=yolov8s.pt用预训练权重,杂草数据量不大时迁移学习收敛快得多。epochs=150配合patience=30,30 轮没提升就早停,省时间。imgsz=640是默认,但如果你的框普遍很小,改 960 会明显提升小目标召回。
参数说明:batch=16在 16G 显存上跑 640 尺寸比较稳,显存不够就降到 8 或 4,同时把lr0按比例降一点。lr0=0.01是 SGD 的常用起点,用 AdamW 的话改 0.001。lrf是最终学习率比例,0.01 表示衰减到初始的 1%。device=0指定第一块 GPU,多卡用device=0,1。
3.3 损失函数与 BN 崩溃:训练不收敛时先看这两个
YOLO 的损失由三部分组成:分类损失(BCE)、框回归损失(CIoU 或 DFL)、目标置信度损失。杂草检测里最常见的异常是 loss 突然变 NaN,或者 mAP 卡在 0.1 不动。
BN 崩溃是热词里高频出现的问题,现象是训练几十轮后 loss 突然爆炸。原因通常是 batch 太小,BatchNorm 统计量不稳。解决办法有两个:把batch提到 16 以上,或者换用yolov8s以上的模型(大模型 BN 更稳)。如果显存实在不够,可以在训练配置里把 BN 换成 GroupNorm,但这需要改源码,属于进阶操作。
另一个高频坑是类别不平衡导致的 loss 震荡。如果某一类样本极少,分类损失会被多数类主导。常见做法是在 data.yaml 里给类别加权,或者对稀有类做过采样。YOLOv8 本身没有直接的 class weight 参数,需要在数据集层面解决。
3.4 看指标:mAP50、mAP50-95 和混淆矩阵怎么读
训练完看results.csv和confusion_matrix.png。mAP50 是 IoU 0.5 下的平均精度,杂草检测里这个指标通常能到 0.8 以上才算可用。mAP50-95 更严格,能到 0.5 就不错。
混淆矩阵是排查类别混淆的利器。如果「作物」和「稗草」互相误判严重,说明这两类视觉特征太近,要么加数据,要么在推理时用后处理规则(比如位置先验)区分。热词里提到的「混淆矩阵总合不唯一」通常是归一化方式不同导致的,YOLO 输出的混淆矩阵默认按真实标签归一化,行和是 1,列和不唯一是正常的。
4. 推理与部署:从验证集到田间的最后一公里
模型训完,mAP 好看不代表能用。田间推理面临光照变化、遮挡、运动模糊,还有边缘设备算力限制。这一章讲推理参数怎么调、部署到边缘设备要注意什么。
4.1 推理命令与置信度阈值:conf 和 iou 的取舍
yolo detect predict \ model=runs/weed/exp1/weights/best.pt \ source=test_images/ \ conf=0.25 \ iou=0.45 \ imgsz=640 \ save=True逻辑说明:conf=0.25是置信度阈值,低于这个值的框被丢弃。杂草检测里如果漏检代价高(比如漏了一株草导致减产),把 conf 降到 0.15;如果误检代价高(比如把苗当草打了药),提到 0.4。iou=0.45是 NMS 的 IoU 阈值,杂草密集时调低到 0.3 能减少框重叠。
参数说明:source可以是单张图、目录或视频。save=True保存可视化结果,方便人工复核。批量推理时加stream=True省内存。
4.2 边缘部署:RK3588 和树莓派上的量化与加速
热词里 RK3588、树莓派、边缘部署监控误检率高,都是真实痛点。YOLOv8 导出 ONNX 再转 RKNN 是 RK3588 的标准路径。
# 导出 ONNX yolo export model=best.pt format=onnx imgsz=640 opset=12 simplify=True # RKNN 转换(需在 RKNN Toolkit2 环境) python -c " from rknn.api import RKNN rknn = RKNN() rknn.config(mean_values=[[0,0,0]], std_values=[[255,255,255]], target_platform='rk3588') rknn.load_onnx(model='best.onnx') rknn.build(do_quantization=True, dataset='quant_dataset.txt') rknn.export_rknn('best.rknn') "逻辑说明:do_quantization=True做 INT8 量化,模型体积缩小 4 倍,速度提升明显,但精度会掉 1~3 个点。quant_dataset.txt是量化校准集,放 100~200 张代表性田间图,别用训练集里的图,否则量化偏差。
参数说明:mean_values和std_values要和训练时的预处理一致,YOLO 默认是 0~255 输入、除以 255 归一化。target_platform写错会导致推理结果全乱。
边缘部署误检率高的常见原因是量化后小目标特征丢失。解决办法:量化时保留检测头不量化,或者用混合量化。树莓派上跑 YOLOv8n 比较现实,s 以上帧率会掉到个位数。
5. 避坑与排查:杂草检测训练里最容易翻车的五件事
这一章全是踩过的坑,按「现象 → 原因 → 解决」写,对号入座。
现象一:训练 loss 正常下降,但 mAP 一直是 0。原因:data.yaml 里nc和 names 数量不一致,或者标注 class id 从 1 开始而不是 0。YOLO 要求 class id 从 0 连续编号。 解决:跑一遍 2.1 的统计脚本,确认类别 id 是 0 到 nc-1。如果标注从 1 开始,批量减 1。
现象二:验证集 mAP 很高,但拿新田块的图推理全是误检。原因:训练集和验证集来自同一批次,数据泄漏。模型记住了背景而不是目标。 解决:按地块或拍摄日期重新划分,确保验证集来自模型没见过的田块。如果数据不够,至少做一次跨批次验证。
现象三:训练到一半 loss 变 NaN,GPU 利用率掉到 0。原因:BN 崩溃,通常是 batch 太小或学习率太高。 解决:batch 提到 16 以上,lr0降到 0.005,加warmup_epochs=3让学习率慢慢升。还不行就换大模型。
现象四:小目标(刚出芽的草)几乎全漏检。原因:输入尺寸 640 下,小目标经过下采样后特征几乎消失。 解决:imgsz提到 960 或 1280,或者在数据加载时做 mosaic 增强(YOLO 默认开)。如果显存不够,用切片推理(SAHI)把大图切小块分别检测。
现象五:推理速度在 V100 上很快,部署到边缘设备后帧率只有 2。原因:没做量化,或者用了 yolov8l 这种大模型。 解决:导出 ONNX 后做 INT8 量化,换 yolov8n 或 yolov8s。RK3588 上 NPU 只支持特定算子,导出时用simplify=True去掉冗余节点。
6. 把 6849 张用到极致:数据增强与主动学习的进阶技巧
数据集就这么多,想再提点,得在增强和采样上做文章。YOLO 默认的增强包括 mosaic、mixup、HSV 抖动、随机翻转,但杂草场景有些增强要慎用。
随机翻转没问题,杂草没有固定朝向。但上下翻转要小心,如果训练图都是俯拍,上下翻转会产生不自然的视角,模型学偏。HSV 抖动里,色调(hue)幅度别开太大,杂草和作物的区分有时靠颜色,色调抖过头会把绿色抖成黄色,类别特征就乱了。
我一般会额外加两个增强:随机遮挡和运动模糊。随机遮挡模拟叶片互相遮挡,运动模糊模拟喷药机行进中的拍摄。这两个在 ultralytics 里可以通过自定义 dataloader 加,或者用 albumentations 预处理后再喂给 YOLO。
主动学习是另一个提效手段。训完第一版模型后,拿它去推理未标注的田间图,把置信度在 0.3~0.6 之间的框挑出来人工复核,这些是模型最不确定的样本,标完加进训练集,通常两三轮就能把 mAP 提 5 个点以上。6849 张不是天花板,用主动学习滚起来,数据会越用越多。
最后说个验证技巧:别只看 mAP,拿模型去跑一段田间视频,人工数一下漏检和误检。视频里的连续帧能暴露单张图看不出的问题,比如模型对某个方向的运动模糊特别敏感。我习惯在部署前跑三段不同光照的视频(早晨、正午、傍晚),每段 30 秒,人工统计误检率。这个数字比 mAP 更能说明能不能上线。
这套流程我前后调了几个月,最大的教训是:数据划分比模型选型重要,推理参数比训练参数影响大。别在模型结构上反复折腾,先把数据和部署链路理顺。希望帮到你。
本文还有配套的精品资源,点击获取