
简介一套面向YOLO系列目标检测算法训练的作物杂草数据集针对需要带标注图像做模型验证与测试的开发者、学习者而准备。压缩包内共601个文件包括200幅JPG图像、200个txt标注、200个xml标注以及1个data.yaml配置文件总大小185.56MB数据已经预先划分完毕可直接用于YOLOv5、YOLOv8、YOLOv9、YOLOv11等主流算法的训练与评估。标注信息分两种格式存放YOLO格式txt按“类别索引 中心点x y 宽高”存储且坐标均经过归一化处理贴合模型输入VOC格式xml提供目标框的详细定位信息方便结合传统检测流程或二次开发。两种格式对应同一批图像可灵活选用。附带的数据集配置文件data.yaml进一步简化了训练前的参数设置。目前已有106人浏览学习适合目标检测入门者快速获得一套标准、干净的作物杂草数据集用于实验教学或算法效果对比。1. 这份YOLO作物杂草数据集解决的不只是“有没有标签”的问题做目标检测的人应该都有过这种体验好不容易找到一份看上去能用的数据集下载完一解压不是缺标签文件就是标签格式跟自己的预训练模型对不上还得自己写脚本重新转一遍半天时间就这么没了。这份200张图像的作物杂草数据集给的是一套“开箱即用”的完整结构——标签同时备好了YOLO格式和VOC格式data.yaml已经按yolov5/v8/v9/v10/yolo11的规范写好连训练集、验证集都划分好了下载下来直接放进工程目录就能跑。它适合两类人一类是刚接触YOLO系列、想用现成数据把训练流程跑通的新手另一类是做农田杂草检测项目、需要快速验证算法选型的熟手。200张图不算大但作为基线实验、模型对比、格式转换练习完全够用。这篇文章把目录结构、标签格式、训练参数、常见坑一次说透照着做就能出一个可用的检测模型。2. 数据集目录与标签格式从data.yaml到txt/xml的约定2.1 目录结构到底长什么样拿到压缩包解压之后第一件事是搞清楚文件怎么组织的。这种带标签的数据集最怕的就是命名混乱、目录嵌套好几层训练脚本一跑就报“找不到图片”。我习惯先把目录树列出来. ├── data.yaml ├── train │ ├── images │ └── labels ├── val │ ├── images │ └── labels └── test ├── images └── labelstrain、val、test三个目录下各有images和labels子目录images里放的是img_0323_*.jpg这种原始图片labels里放的是同名txt文件。需要注意的是这份数据集同时提供了YOLO格式和VOC格式两套标签分别存放在不同文件夹下。如果按YOLO格式直接用就找txt那一套如果习惯VOC的xml标注训练前要先转成YOLO格式再跑。提示训练集、验证集、测试集的划分在文件组织层面已经完成不需要再写随机划分脚本。但划分比例要看清楚200张图如果train占150、val占30、test占20属于比较常规的分配小数据集下不建议再手动抽图出来当验证集。2.2 data.yaml里写了什么data.yaml是YOLO系列训练时必读的配置文件它告诉模型“去哪找图片、总共分几类、类别叫什么”。这份数据集的data.yaml已经帮你写好了内容大概是这样的path: ./ train: train/images val: val/images test: test/images nc: 2 names: [crop, weed]path指定数据集根目录train/val/test对应各自的图片文件夹路径nc是类别数names是类别名称列表。类别名这里按常见的“作物/杂草”二分类来理解实际训练前打开yaml看一眼names跟你的任务是否一致。常见做法是在训练脚本里用绝对路径覆盖path字段比如把path改成/home/yourname/datasets/crop_weed/这样无论工程目录在哪都不会找错图。我在实际项目里遇到“训练启动后一直停在Loading images”的情况十有八九就是path配错了相对路径。2.3 YOLO格式标签五个数字的归一化约定YOLO格式标签是每行五个数字顺序是class x_center y_center width height。前四个坐标全部是归一化比例值范围0到1表示相对图像宽高的比例。打开一个txt文件能看到类似这样的内容0 0.538281 0.376389 0.105469 0.122222 1 0.725391 0.654861 0.083594 0.108333第一列是类别索引从0开始对应names列表中的位置。第二列是目标框中心点的x比例第三列是中心点的y比例第四列是框宽比例第五列是框高比例。训练脚本加载时会自动把这些比例值还原成像素坐标去计算损失所以这五列数据直接决定检测框的位置和大小错一个数就是错一米。如果这类标签哪天真写错了肉眼又不好查我会直接写个Python脚本加载图片和txt在图片上把归一化坐标还原成像素框画出来看import cv2 img_path train/images/img_0323_96.jpg label_path train/labels/img_0323_96.txt img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: for line in f.readlines(): cls, xc, yc, bw, bh map(float, line.strip().split()) 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, 255, 0), 2) cv2.putText(img, str(int(cls)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imwrite(check_visual.jpg, img)这段代码做的事情是读取一张图片和它的txt标签把归一化框还原为像素坐标并画框保存成新图。检查时重点看框是否贴合目标边缘——如果框明显偏大或者偏小说明标签本身标注质量一般如果框位置乱跑多半是归一化坐标写错了。这一步是训练前最值得花时间的自检比模型跑半天再看loss曲线高效得多。3. 训练前的数据校验与预处理拒绝翻车从这步开始3.1 图片与标签文件名一致性检查200张图的数据集理论上文件名是成对出现的但实际下载的数据集偶尔会出现缺张少张的情况。训练时如果图片存在但标签缺失YOLO会直接跳过这张图反过来标签存在但图片缺失训练直接报错退出。稳妥的做法是跑一遍文件名比对脚本import os from pathlib import Path for split in [train, val, test]: img_dir Path(split) / images lab_dir Path(split) / labels imgs {p.stem for p in img_dir.glob(*.jpg)} labs {p.stem for p in lab_dir.glob(*.txt)} missing_lab imgs - labs missing_img labs - imgs print(split, 缺标签:, len(missing_lab), 缺图片:, len(missing_img)) if missing_lab: print(list(missing_lab)[:5])这一步输出会直接告诉你哪个split下存在文件不配对的情况。我之前有一次跑一个公开数据集train里有三张图没有标签文件当时没检查训练跑完后发现这三张图的损失特别大还以为是模型问题查了半天才发现是数据本身缺标签。数据集小的时候这种错误对模型的影响比想象中更明显。3.2 VOC格式与YOLO格式的取舍这份数据集同时提供了xml标注对熟悉VOC格式的人来说用xml标注能在可视化工具里直接打开检查。但YOLO训练只认txt所以如果你要用VOC那套标签得先做一次格式转换。xml标注长这样annotation filenameimg_0323_96.jpg/filename size width1280/width height720/height /size object namecrop/name bndbox xmin120/xmin ymin80/ymin xmax340/xmax ymax260/ymax /bndbox /object /annotationxmin/ymin/xmax/ymax是像素坐标转成YOLO格式需要做一次换算xc(xminxmax)/2再除以宽度yc(yminymax)/2再除以高度w(xmax-xmin)/宽度h(ymax-ymin)/高度。如果xml里的name是字符串还需要先映射成整数索引再写进txt。VOC转YOLO的脚本网上很多但最关键的是类别映射别写错。比如xml里是nameweed/name你的映射字典里必须有一项{crop: 0, weed: 1}而不是靠字符串顺序猜。转完之后建议抽样画框验证跟标签自检的套路一样。3.3 图像尺寸与Exif信息的问题YOLO训练前会把图片缩放成网络输入尺寸常见是640×640或416×416。但原始图片如果带Exif旋转信息某些读取方式下会出现“看到的图像方向和实际数据方向不一致”的玄学问题框就画到错误的位置上。我一般会先用Python批量稳一遍图像from PIL import Image from pathlib import Path for img_path in Path(train/images).glob(*.jpg): with Image.open(img_path) as im: im.load() exif im.getexif() if exif is not None and 274 in exif: # 274 是Orientation标签 img Image.open(img_path).transpose( Image.Transpose.ROTATE_180 ) img.save(img_path)这段代码做的事情是检查每张jpg的Exif Orientation字段如果存在旋转信息就重写图像数据把方向修正回来。实测中手机拍的照片比较常出现这类问题用工业相机或无人机拍的相对少。这个步骤不做后面训练可能莫名其妙不收敛或验证集mAP算出来特别低。4. YOLOv8与YOLO11训练参数设置与一次跑通4.1 用YOLOv8跑通完整训练流程YOLOv8是目前最成熟、资料最多的版本之一环境安装相对顺手。假设你已经在conda环境里装好了ultralytics库训练命令非常简单yolo detect train \ data/path/to/your/dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ project./runs \ namecrop_weed_v8data参数指向我们前面看过的data.yamlmodel用yolov8n.pt预训练权重epochs设定100轮imgsz设为640batch大小看显卡显存来定device0表示用第一块GPUproject和name控制输出目录。训练日志会实时打印每个epoch的box_loss、cls_loss、mAP50等指标注意观察mAP50是不是在前20个epoch内明显爬升。200张的小数据集大概一两分钟就能跑一个epoch百轮下来也就一两个小时的事跑完直接看results.csv或者val目录下的混淆矩阵图。4.2 用YOLO11验证新版本兼容性YOLO系列迭代到v11之后ultralytics的接口基本保持稳定换模型只需要改动model参数yolo detect train \ data/path/to/your/dataset/data.yaml \ modelyolo11n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ project./runs \ namecrop_weed_v11yolo11n.pt是YOLO11的nano版本如果你的ultralytics版本足够新它会自动下载对应的预训练权重。相比yolov8nyolo11n在下采样结构上有调整在小目标检测上通常会好一点点但具体增益要等跑完看验证集结果。这份数据集因为标签是标准YOLO格式v5/v7/v9/v10理论上都可以直接套同样的命令只是个别版本需要对应版本的detect脚本参数格式略有不同。提示运行yolo命令之前确认ultralytics库版本。yolov10和yolo11需要相对较新的版本老版本会报“Unknown model”错误升级到最新版就行。4.3 超参数调整batch、epoch和imgsz怎么配batch大小由显存决定8G显存跑yolov8n可以开16跑yolov8s建议减到8再大就会OOM。epoch的设定看loss曲线变化200张图通常50到100轮足够收敛跑太多轮反而会过拟合——训练集loss低到几乎为零验证集mAP却掉下来。imgsz这里有个小知识点如果原始图像宽高比例不是1:1YOLO会做letterbox补边处理这个处理和标签的归一化坐标无关是训练前自动完成的所以你不需要自己预先裁剪图片。但imgsz设得越大单张图占显存越多batch就要相应减小。第一次跑建议直接用batch8 epochs100 imgsz640先把流程跑通有结果了再尝试调大batch或imgsz对比mAP。5. 避坑指南标签自检、路径配置与训练异常的排查5.1 训练启动报错“No labels found”现象执行yolo detect train之后马上报错提示在train/images下找不到labels。原因数据集目录里labels文件夹没放在正确位置。data.yaml里写的是train: train/imagesYOLO会自动去train/labels找txt文件。如果你把标签放在别处或者txt后缀名大小写不对就会报这个错。解决检查train/labels目录是否存在txt文件后缀小写标签文件名必须与图片文件名完全一致不含扩展名。如果用的是VOC xml标签需要先转成txt再放过来。5.2 训练正常但mAP值忽高忽低现象每轮评估的mAP50在0.5到0.9之间剧烈波动看起来完全没有收敛。原因验证集图片太少200张图里验证集一般只有30到50张每张图的检测结果对整体指标影响都很大波动属于正常现象。另一种可能是类别标签索引和xml里的名字映射错位——比如crop标成了1weed标成了0模型学到的内容和评估时的期望完全反过来。解决用前面写的可视化脚本抽样20张图确认标签类别索引与目标实际语义一致。小数据集训练参考标准是看最终轮次的mAP不要被中间的波动干扰。5.3 loss正常下降但检测框整体偏移现象训练loss收敛得很好但验证集图片上画出来的框明显偏向某个方向和目标位置有固定偏移。原因最常见的原因是图像读取通道顺序不一致。OpenCV默认BGRPIL默认RGB如果你在训练前后自己做了图像预处理可能把通道顺序搞乱模型提取的特征错位框就跟着偏了。另一种情况是之前改过图片尺寸但没有同步修改标签归一化坐标。解决如果你只是直接用YOLO框架训练不自己写预处理基本不会遇到这个问题。如果自己写过增强或预处理统一用BGR顺序并且改图像尺寸时一定要用“等比缩放补边”的方式不能直接拉伸——一旦拉伸归一化坐标和像素的对应关系就变了。5.4 txt标签里出现空文件现象某个txt文件是0字节训练日志提示“skipping empty label file”。原因标注工具导出时漏了对象或者这张图确实没有目标物却被放进了训练集。YOLO不允许训练集中存在空标签图片它会直接跳过该图等于这张图没有参与训练。解决删除空txt文件同时把对应的图片从训练集里移出或者把它挪到验证集作为负样本。如果空标签文件出现在验证集也会影响评估逻辑建议统一清理。5.5 尝试v5/v7训练时模型结构不兼容现象用ultralytics命令下载了yolov5版本的预训练权重但训练时报结构不匹配。原因v5/v7与v8/v9/v10/v11虽然都叫YOLO但代码库并不相同。yolov5是独立仓库v8之后的版本才统一在ultralytics框架里。官方评测量指标计算方式也略有差异。解决如果你的操作环境是ultralytics就统一用v8/v9/v10/v11系列权重。想跑v5就单独clone yolov5仓库按它自己的train.py命令来不要直接套用yolo命令。6. 进阶验证集可视化与自定义类别扩展训练结束之后我一般不会只盯着mAP数字就完事。mAP代表整体水平但具体在哪些图片上翻车还是得眼见为实。用训练好的权重跑一次验证集推理把所有预测框画到原图上yolo detect predict \ model./runs/crop_weed_v8/weights/best.pt \ source./val/images/ \ saveTrue \ conf0.25预测结果默认保存在runs/detect/predict目录下。打开图片看两件事一是看看有没有漏检比如杂草很小、颜色和土壤接近导致完全没框出来二是有没有误检比如把土块当成了作物。这两类错误在mAP曲线里都有体现但在图上一张张翻更容易看出模型到底是“不会”还是“学错了”。如果发现某一类目标经常漏检可以往下调conf阈值再看一遍比如conf0.1看看到底是模型压根没给出这个位置的预测还是给了但置信度不高被过滤掉了。如果是后者说明模型有检测能力只是把握不大可以考虑增加该类别的训练图样数量。如果之后想扩展类别比如除了作物和杂草之外还想区分三种不同杂草需要做几件事准备新类别的图片、按YOLO格式标注、更新data.yaml里的nc和names列表。注意nc是个数字names是一个字符串列表两者的长度必须一致漏改一个就会在训练启动时报“nc mismatch”。我自己习惯把这部分检查和权重保存做成一套固定流程训练完→跑验证集预测→翻图片→记下错误类型→决定是调阈值还是补数据。从那以后我每次拿到新的数据集都会强制走一遍这套流程不会因为loss好看就跳过。小数据集本来就不容易出现“完美模型”多看几张图比换更大的预训练权重更管用。希望这些具体操作能帮你把这份数据集的训练道路理顺少走几个弯路。本文还有配套的精品资源点击获取