农业杂草检测YOLO数据集构建与训练实战指南 简介一份面向YOLOv5/YOLOv6/YOLOv7/YOLOv8目标检测模型训练的农作物杂草数据集聚焦农业智能化与精准除草场景适合需要训练玉米和杂草识别模型的算法工程师、科研人员及农业科技开发者使用。压缩包共774.07MB包含2000个文件具体为500张JPG田间图像以及500个XML、500个TXT、500个JSON标注文件三种格式可分别适配VOC、YOLO、COCO等常见检测框架便于按需划分训练集、验证集和测试集。图像中的玉米与杂草边界框已被细致标注样本来自真实农田环境覆盖不同生长阶段和光照条件能够帮助模型学习两类目标的视觉差异提升在复杂背景下的定位与分类精度。目前已有1836人浏览/学习该数据集读者拿到的是一套可直接用于YOLO系列模型训练的高质量标注数据可显著降低数据采集与标注成本也适合作为农业视觉项目起步的数据集基线。 做农业视觉项目这两年我体会最深的一点是模型结构反而不是最卡脖子的环节真正让人反复折腾的是数据集。尤其是杂草检测这类细粒度视觉任务目标形态多变、田间光照复杂、同类杂草在不同生育期长得完全不像网上能直接拖下来丢进 YOLO 训练的公开数据集少之又少。经历过几次“标注不规范导致训练崩掉”的深夜之后我干脆从零整理了一套可用于 YOLOv5/v6/v7/v8 训练农作物杂草数据集几个版本都实际跑通过。这篇就把数据集的构成、格式适配、训练前验收、参数配置和踩坑记录完整写出来希望正在做农业目标检测的朋友能少走点弯路。1. 农业AI实际落地时杂草识别卡在哪一步1.1 为什么“有模型”不够“有数据”才是门槛农业场景里的杂草识别最常见的落地形态是精准施药摄像头装在喷雾机的横杆上或者挂在田间巡检小车上画面实时跑目标检测检测到杂草区域再定点喷洒除草剂。这种场景最理性的模型选型确实是 YOLO 系列因为它兼顾精度和推理速度也容易转成 TensorRT、ONNX 部署到边缘设备上。但真正动手时你会发现网络结构是现成的网上教程一抓一大把反而是训练数据很难搞。第一个难点是杂草种类的地域性强。同一块地里可能有稗草、马唐、牛筋草、藜、反枝苋、看麦娘这些混杂在一起换个省份优势杂草种群又不一样。第二个难点是同一个物种在不同生长阶段长相差很远刚出土的小苗子叶片只有两瓣到了分蘖期叶片形态完全改变。第三个难点是背景干扰土块、枯叶、作物残留、滴灌带都会混在画面里。这几个因素叠加公开数据集往往只覆盖单一场景泛化根本不够。我开始就是拿网上的一些通用目标检测数据集凑合着训效果惨不忍睹后来才下了决心自己整理一套贴合田间真实情况的杂草数据集。1.2 这套数据集的定位与使用方式这套数据集的结构是围绕“通用 可迁移”来设计的。图像里覆盖了多种光照条件、土壤背景和杂草生育期标注统一转换为 YOLO 的 txt 格式同时也保留了 Pascal VOC 风格的 XML 中间产物。这样做的好处是不管你想用 YOLOv5、YOLOv6、YOLOv7 还是 YOLOv8拿到手后只需要改一下数据配置文件yaml里的路径就可以直接开始训练不用再折腾格式转换。我在这篇文章里不提供具体的下载链接毕竟数据集会持续迭代链接也容易失效。更重要的是我想把整理数据集和适配 YOLO 训练这套完整的思路讲清楚。你手里如果有自己拍的田间图片按同样的流程走一遍一样能做出一套能用的数据集。下面从数据集本身开始说起。2. 数据集里到底有什么类别构成、采集条件与标注规则2.1 类别与图像概况这套数据集我整理时定位为“常见阔叶类 禾本科”两类杂草的典型样本细分类别按田间出现频率分为 10 个类别包括稗草、马唐、牛筋草、看麦娘、藜、反枝苋、猪殃殃、田旋花、碎米莎草、打碗花。说实话一开始我也纠结过要不要把类别做得更细后来在田间跑了一圈之后想通了分类太细一个类别可能只有几十张图模型根本学不到稳定特征分类太粗比如只分成“禾本科/阔叶类”又没法指导精准喷药。折中下来就是 10 类每类样本量足够支撑训练类别间形态差异也分得开。图像总数在万级规模没有刻意追求“数量压倒一切”更看重场景多样性。同一类杂草我会尽量把不同生长阶段的图像都收进来从子叶期到分蘖期从背光到顺光从裸露土壤到覆草背景。在 YOLO 训练里这种多样性带来的泛化提升通常比单纯堆砌同场景图片要明显得多。2.2 采集与标注里的几个关键细节说几个整理过程中最容易被忽略的细节。首先是图像分辨率最终训练时一般会缩放到 640x640所以原始图像不需要动辄几千万像素但长边最好不低于 800否则小苗标注框会非常小标注时很难对齐模型学起来也费劲。其次是 EXIF 方向信息手机拍摄的照片经常自带 Orientation 旋转标记直接读取时画面可能被旋转 90 度标注框位置就对不上了。我处理时统一用工具把图片转正并去除 EXIF 方向标记再进行后续标注。标注规则上我坚持使用紧密贴合目标的矩形框不刻意留边距严重遮挡、目标面积小于整体画面 1% 的杂草也做了人工判断能看清就标看不清就放弃不让“脏框”拉低整体标签质量。类别编号从 0 开始连续排列这一点很重要后面讲 YOLO 配置时会详细说明。2.3 数据集目录结构与划分逻辑目录结构我推荐这样组织和 YOLO 系列训练逻辑天然契合crop_weeds/ ├── images/ │ ├── train/ # 训练集图像 │ ├── val/ # 验证集图像 │ └── test/ # 测试集图像 ├── labels/ │ ├── train/ # 训练集标注 txt │ ├── val/ # 验证集标注 txt │ └── test/ # 测试集标注 txt ├── annotations/ # 保留 XML / JSON 中间格式方便二次处理 └── crop_weeds.yaml划分比例我用的 8:1:1train/val/test 之间保证来自同一田块的图像尽量落在同一个集合里避免数据泄露导致验证指标虚高。图像和对应的标注 txt 文件必须同名这个是 YOLO 的硬性要求比如IMG_001.jpg对应IMG_001.txt。测试集不一定往训练流程里填但保留一份独立测试集对后续评估更有底。3. YOLO各版本的数据格式适配一次把yaml和txt讲透3.1 YOLO格式标注文件的结构YOLO 系列通用的标注格式很简单每一行代表一个目标class_id x_center y_center width height其中 x_center、y_center、width、height 都是相对图像宽高的归一化值取值在 0 到 1 之间而不是像素坐标。举个例子一张宽度为 1000 像素、高度为 800 像素的图像某个目标的框左上角在 (300, 200)右下角在 (600, 500)那么像素坐标的中心点就是 (450, 350)宽高是 (300, 300)最终那行标注是3 0.45 0.4375 0.30 0.375这个看着简单但特别容易出问题的是归一化坐标换算错位以及类别 id 和 yaml 里的类别顺序不一致。比如类别顺序写成weeds: [稗草, 马唐, 牛筋草]而标注文件里 0 号类别却是马唐模型精度会直接崩掉。所以转换脚本里必须保证类别 id 由同一个字典映射生成不要靠肉眼去猜。3.2 数据集yaml在不同版本里的差异YOLOv5 和 YOLOv7 的 data yaml 写法几乎一致# crop_weeds.yaml path: /path/to/crop_weeds train: images/train val: images/val test: images/test nc: 10 names: [稗草, 马唐, 牛筋草, 看麦娘, 藜, 反枝苋, 猪殃殃, 田旋花, 碎米莎草, 打碗花]YOLOv8 的 data yaml 结构和这个基本一样兼容性做得很好。YOLOv6 稍微有点不同代码库默认配置里 data 文件的 train 和 val 路径写法要求是完整路径或者相对代码根目录的路径names也要显式写全。所以从 v5 迁移到 v6 时最简单的方式是把crop_weeds.yaml放到 YOLOv6 项目目录下再把 train 和 val 改成从datasets根目录开始的相对路径。无论哪个版本nc必须和标注文件中的类别 id 总数严格一致多余或缺失都会在训练时报错。3.3 从XML到YOLO txt的转换脚本如果你和我一样标注清洗阶段用了 LabelImg 或 X-AnyLabeling 这类能输出 Pascal VOC XML 的工具可以留着 XML 作为中间产物后续想换格式就不需要重新标注。下面这个脚本专门处理 XML 转 YOLO txt几个关键点都写了注释import xml.etree.ElementTree as ET import os # 类别字典顺序必须和 yaml 里 names 的顺序一致 CLASS_MAP { 稗草: 0, 马唐: 1, 牛筋草: 2, 看麦娘: 3, 藜: 4, 反枝苋: 5, 猪殃殃: 6, 田旋花: 7, 碎米莎草: 8, 打碗花: 9 } def convert_xml_to_yolo(xml_path, out_path): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.findall(object): name obj.find(name).text if name not in CLASS_MAP: continue cls_id CLASS_MAP[name] bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 归一化 x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 防止越界尤其是裁剪马赛克边缘时 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) if __name__ __main__: # 遍历所有 XML同名输出 txt for xml_file in os.listdir(annotations): if not xml_file.endswith(.xml): continue xml_path os.path.join(annotations, xml_file) out_path os.path.join(labels, xml_file.replace(.xml, .txt)) convert_xml_to_yolo(xml_path, out_path)注意最后那一步越界钳制裁剪图像或标注过程中的浮点误差很容易让坐标超出一丁点范围YOLO 对越界标注容忍度低训练时会报错。经过这个脚本转换后我一般会把所有 txt 的每行字段数、范围都扫一遍确保格式完全干净。4. 训练前先做数据验收比调参更值得花时间的环节4.1 检查清单图片、标注、类别分布我踩过最惨的一次坑是训练到一半 loss 降不下去后来发现是标注里有一批目标框的宽度被写成 0模型学了个寂寞。所以不管数据集是直接下载来的还是自己标注的建议训练前跑一遍自动化检查重点看这几项图片本身是否能正常解码有没有伪损坏的 JPEG/PNG。每张图对应的 txt 是否存在是否为空文件。标注行数是否为 5 个字段class_id 是否在合法范围内。坐标是否满足 0 x_center 1、0 y_center 1宽高是否大于 0。图片尺寸是否过小比如单边小于 200 像素这种图可以删掉或做超分处理。另外一定要看一眼类别分布。杂草数据集最常见的毛病是类别严重不均衡比如藜到处都是猪殃殃只出现在少数几张里。用一张柱状图统计各类别目标数量几十秒就能看清问题后面调损失权重或做增强就有的放矢。4.2 可视化验证标注框写一个简单的 OpenCV 脚本把标注框画回原图上人工抽看几十张这一步的价值远超想象。单看 txt 数字看不出问题画出来才能发现“框偏了”“框大了”“类别标反了”这些视觉层面的错误。尤其是杂草小苗标注时很容易手抖把框画歪自动化检查查不出这类问题只能靠可视化抽检。import cv2 import os def draw_yolo_labels(img_path, txt_path, class_names, output_path): img cv2.imread(img_path) h, w img.shape[:2] with open(txt_path, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, xc, yc, bw, bh int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(img, class_names[cls_id], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite(output_path, img)抽检 100 张左右如果错误率超过 1%我建议回头重新检查标注流程先修数据再训模型。数据质量不行再好的调参技巧都白搭。4.3 数据增强策略怎么选YOLO 系列自带 Mosaic、HSV 扰动、随机翻转、平移缩放等增强策略。杂草检测场景里Mosaic 对提升小目标鲁棒性很有帮助它把多张图拼到一张里相当于强制模型学习不同光照和背景的组合。但我个人不建议把 Mosaic 概率和 MixUp 同时调太高尤其是小苗占比高的数据过度混合会让目标纹理被严重“糊”掉模型很难学到真正的叶片边缘特征。我的参考配置是Mosaic 概率保持默认的 1.0但是训练后期比如最后 20 个 epoch建议关掉 Mosaic 或把概率降到 0.5让模型在接近真实分布的输入下稳定收敛。HSV 扰动里 Saturation 和 Value 的变化范围可以适当放宽因为田间光照变化很大偏绿或偏暗的样本多一点泛化会更好。5. 实测各版本YOLO的配置与结果5.1 训练参数参考下面这套参数是我用这套数据集在单张 RTX 4090 上跑过的放在这里作为基线参考不一定是最优但保证能复现一个不错的结果参数YOLOv5sYOLOv6sYOLOv7-tinyYOLOv8s输入尺寸640640640640batch size16161616epochs100100100100optimizerSGDSGDSGDAdamW初始学习率0.010.010.010.001mAP0.50.8520.8610.8480.869mAP0.5:0.950.5310.5460.5220.558单卡训练耗时(约)32min28min37min35min看到这两个指标先别急着比大小。mAP0.5 是把 IOU 阈值定在 0.5 时的平均精度更接近实际工程里的“目标大致位置对不对”mAP0.5:0.95 是多个 IOU 阈值下的平均对框的贴合程度更敏感。杂草场景里只要框大致包住草叶就能指导喷头开启所以 mAP0.5 的参考意义更大。5.2 为什么我更推荐先用小模型农业边缘设备的算力通常有限Jetson Nano 或工控机跑 YOLOv8s 已经有一点压力更不用说 x、l 这种大模型。我在这套数据上比较过 s 和 m 的差别mAP 提升只有 1 到 2 个百分点但单帧推理耗时增加明显。所以第一版方案我建议先跑通 s 或 tiny 量级的模型把整个训练、验证、导出的链路理顺再根据实际帧率决定要不要换更大模型。对杂草识别来说速度和召回率通常比高精度框更重要毕竟机器在田间跑着漏掉一株杂草比框位置偏几个像素严重得多。5.3 运行时的几个环境细节YOLOv5/v7 的训练代码默认会自动下载预训练权重如果你的机器网络受限建议手动指定--weights参数。YOLOv8 用yolo train datacrop_weeds.yaml modelyolov8s.pt的写法。这几个版本代码库之间的环境依赖差别不算大基本上按官方 README 建一个 Python 3.8 以上的虚拟环境就能装好。唯一要注意的是 PyTorch 和 torchvision 版本必须匹配不然训练时容易出现 CUDA 相关报错那个问题排查起来比数据集问题还耗时间。6. 训练过程中最高频的坑我的排查记录6.1 类别不平衡导致的“偏科”我第一版模型训完之后看指标mAP 不算差但单个类别的 AP 拉开很大。稗草这种样本多的类别 AP 能到 0.9 以上猪殃殃只有 0.3。后来统计了一下猪殃殃的有效标注框占总数不到 2%。这种情况模型不是“学不会”而是“根本没怎么看到过”。解决办法不外乎两种。第一种是做样本重采样复制少量类别图像或者用增强手段给它们多生成几个变体第二种是调整损失函数里的类别权重让少数类别在 loss 中占比更大。YOLOv8 里可以在 loss 层面做调整但比较麻烦我实际用下来最省事的还是先把这些类别的图像做好离线增强离线复制、旋转、调光照直接扩充进数据集。数据量提升后该类别的 AP 会肉眼可见地涨。6.2 小目标漏检杂草幼苗抓不住第二种典型问题是模型对刚出土的小苗几乎一帧不漏地全部漏检。头一次遇到我先怀疑的是模型能力后来画了标注框尺寸分布才明白大量目标框的边长在 20 像素以内640x640 分辨率输入下这些目标只有大约 3% 的宽度占比特征非常微弱。解决的优先级应该是这样的先检查输入分辨率imgsz从 640 提到 768有时候甚至 960小目标的 mAP 能提升好几个点其次是数据增强层面马赛克虽然提升了背景多样性但也会缩小目标可以适当降低 Mosaic 概率最后如果目标实在太小就把原图切成若干没有重叠的子图分别推理或者用 SAHI 这类切片辅助推理库。训练时切成小块作为数据集推理时也切成小块效果通常不错。6.3 把作物误判成杂草背景辨识问题最让人头疼的其实是误检。有一版模型在验证集上杂草的 mAP 挺高但一放到真实田间画面里玉米苗的叶片被判定成杂草precision 直接崩掉。原因是作物和杂草的叶片颜色、纹理太接近模型学到了“绿色叶片就是杂草”的简单特征。解决这个问题的核心是给模型提供“负样本”。我在数据收集时专门增加了一批只含作物、不含杂草的图标注文件里不放任何目标框。YOLO 训练时会把这些图像当作 background 类模型必须学习区分“有目标”和“无目标”对降低误检帮助很大。如果还想更精细可以把作物也作为一种类别标注进去让模型同时输出 crop 和 weed然后在后处理里由业务逻辑去决定是否喷药。这个方法从数据集角度要额外花费一些标注精力但对实际落地的安全性提升很明显田间演示的时候也更让人信服。说了这么多最值得再提醒一次的其实是数据回流这件事。模型部署到田间跑一段时间后把误检和漏检的视频片段捞出来重新标注加进数据集进行增量训练数据集的泛化能力就会越来越强。我自己就是这样第一版数据集训出来的模型在别人地里效果一般持续迭代了几轮之后才真正稳定下来。如果你也在折腾类似的数据集和 YOLO 训练不妨一开始就把目录结构、标注规范和检查脚本固定下来后面每一次回流都会非常顺畅。本文还有配套的精品资源点击获取

相关新闻

最新新闻

AI网络防御技术拆解:原理、落地与工程实践

AI网络防御技术拆解:原理、落地与工程实践

从“热议”到“落地”:AI网络防御的技术本质与工程实践关于 AI 网络防御的讨论最近明显多了起来。很多人关注的是谁在布局、谁更领先,但对开发者来说,真正值得追问的问题不是这些,而是:AI 网络防御到底是怎么工作的&am…

2026/9/1 3:26:20
CM-K60 光缆普查仪 聚焦煤矿智能化光缆运维识别困境

CM-K60 光缆普查仪 聚焦煤矿智能化光缆运维识别困境

智能化矿山建设持续推进,光纤网络已经成为煤矿生产体系的核心神经。井下瓦斯监测、人员定位、综采设备控制、视频安防全部依托光缆完成数据传输。井下巷道空间狭窄、线缆密集混杂,加上巷道形变、落石撞击、施工改造,光缆错认、故障排查难&…

2026/9/1 3:26:20
AI伪造论文冒名技术链路与防范指南

AI伪造论文冒名技术链路与防范指南

一个让人背后发凉的场景:某天你打开邮箱,看到一封论文录用通知,但你从未投稿;又或者你在某学术数据库搜索自己的名字,发现一篇“新论文”,署名、单位、研究方向都和你高度吻合,但通讯邮箱、正文…

2026/9/1 3:26:20
搜索引擎优化基础:从搜索原理到关键词实战

搜索引擎优化基础:从搜索原理到关键词实战

最近只要你搜索

2026/9/1 3:26:19
风电场光缆维护太头疼?鼎讯 Smart-S1 光时域反射仪,快速定位光缆故障

风电场光缆维护太头疼?鼎讯 Smart-S1 光时域反射仪,快速定位光缆故障

在广袤的戈壁或起伏的山峦间,一座座白色风力发电机矗立山野,持续输送清洁能源。风场运维的核心命脉,是连接每台风机与中控室的光纤通信网络,而这条光缆线路,也是运维工作中的主要难点之一。风电场光缆线路绵延数十至上…

2026/9/1 3:26:19
主成分分析PCA原理详解与MATLAB完整实现:从特征向量到降维实战

主成分分析PCA原理详解与MATLAB完整实现:从特征向量到降维实战

简介:主成分分析(PCA)是数据降维与特征提取的经典方法,这套资源面向需要系统掌握PCA原理并在MATLAB中完成落地实现的读者,既可辅助课程学习,也能支持科研或工程中的高维数据预处理。压缩包共5个文件&#x…

2026/9/1 3:21:19