水稻慈姑杂草检测:221张小样本数据集YOLO训练全流程
发布时间:2026/10/1 3:42:28来源:尧图网络
简介面向水稻慈姑类杂草检测的221张图片数据集为农业目标检测模型训练提供Pascal VOC与YOLO双格式标注。影像采集自田间水稻环境标注对象包括sagittaria与sagittaria_flower两类分别有744个和520个真实框合计1264个边界框可直接用于训练Faster R-CNN、YOLO系列等常用检测模型适用于农业视觉识别、精准施药、杂草密度评估等研究与应用场景。 压缩包共665个文件包含221张jpg原图、221个xml标注与221个txt标注并附有类别说明等文本整体大小约129.55MB。文件与标注一一对应目录结构清晰便于用户自行划分训练、验证与测试集。目前已有144人学习下载。 这份数据集省去了田间采集与人工标注的重复工作提供可直接读取的规范数据两类目标覆盖植株与花器官可支撑模型在不同生长阶段下的识别效果验证加速农业检测项目的迭代。1. 水稻慈姑类杂草检测数据集221张图能撑起什么场景慈姑是长江中下游稻田里最难缠的杂草之一箭形叶片贴着水面生长苗期混进稻丛里人工分拣效率极低。想做精准施药或机械除草第一道坎就是让机器在田间准确区分哪棵是稻、哪棵是慈姑。这个水稻慈姑类杂草检测数据集一共提供221张田间图像标注了2个检测类别——水稻和慈姑类杂草属于典型的小样本目标检测数据集。它的直接用途是训练一个能区分稻苗和慈姑的检测模型为田间巡检机器人或智能喷雾设备的视觉模块提供前级感知。221张图数量不大但类别少、场景聚焦适合做迁移学习练手也适合刚接触目标检测的人把数据处理到训练评估的完整流程走一遍。2. 慈姑类杂草检测的数据基础标注格式、类别构成与221张样本的真实价值2.1 数据集的类别设计与标注格式拿到此类数据集第一步不是急着开训而是摸清标注文件的格式和标签质量。农田目标检测数据集常见的标注格式有两种Pascal VOC格式和YOLO txt格式。VOC格式是每张图配一个同名xml文件框的坐标用像素值写在bndbox节点里YOLO格式则是每个框一行文本记录类别id和归一化后的中心点坐标与宽高。如果是labelme标注产出的json还需要先转成VOC或直接解析成YOLO格式多数发布方为了便捷使用通常会给VOC或YOLO里的至少一种。假设拿到的是VOC格式标注单个xml文件大致长这样annotation filenameIMG_0231.jpg/filename size width1280/width height720/height /size object namerice/name bndbox xmin356/xmin ymin188/ymin xmax512/xmax ymax342/ymax /bndbox /object object namesagittaria/name bndbox xmin720/xmin ymin400/ymin xmax910/xmax ymax560/ymax /bndbox /object /annotation一个object块对应一个目标框name是类别名bndbox里的四个数字是左上角和右下角的像素坐标。这里最容易踩坑的位置是size里的宽高必须和jpg的物理尺寸严格一致。如果标注阶段对原图做过缩放而xml里没有同步更新后面转YOLO格式时所有坐标都会整体偏移这种错位不报错但训练出来后框的位置会普遍偏上或偏左排查起来非常隐蔽。多数数据集发布方不会附带详细的类别分布文档所以我会先写一个统计脚本把xml扫一遍看类别数量、每类框数、图像尺寸的一致性。这是数据侧最早的排雷步骤。import os import xml.etree.ElementTree as ET ann_dir annotations box_count {} size_map {} image_count 0 for xml_file in os.listdir(ann_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(ann_dir, xml_file)) root tree.getroot() image_count 1 w int(root.find(size/width).text) h int(root.find(size/height).text) size_map[(w, h)] size_map.get((w, h), 0) 1 for obj in root.iter(object): name obj.find(name).text box_count[name] box_count.get(name, 0) 1 print(图像总数:, image_count) print(各类别目标框数:, box_count) print(图像尺寸分布:, size_map)这段脚本跑完能看到两类关键信息一是rice和sagittaria的框数量分别是多少如果差距超过3倍后面必须处理类别不平衡二是图像尺寸是否存在多种分辨率混用分辨率时转YOLO格式必须逐张读取实际宽高不能写死。2.2 221张样本的分布特点与训练可行性分析221张图按最常见的8:1:1切分训练集约176张验证集22张测试集23张。验证集22张意味着什么一张图上漏掉一个关键的慈姑框mAP可能直接掉2到3个点。同一套配置跑三次结果波动3到5个点是常态这不是模型不稳定而是验证集样本太小单张图的偶然因素会在指标里被放大。所以面对这类小样本目标检测数据集头号原则是评测时不迷信单次数值要看多次实验的均值和方差。我的习惯做法是第一所有实验固定同一个随机种子保证数据划分和增强顺序可复现第二如果手头只有221张图把训练和验证切成3到5折做交叉验证每折留出20%左右的图像做验证最终把各折mAP取平均单次实验的运气成分会被抹平不少第三做对比实验至少跑三组别一组定生死。另外要关注图像分辨率和目标框面积。如果原图多为1920x1080而水稻苗在图上只有40x40像素这种小目标在训练尺寸设为640x640时会被压到13x13像素左右特征非常微弱。我的习惯是先统计所有目标框的宽高看面积中位数再决定imgsz用640还是896还是1024。统计脚本就是在2.1那段脚本里加一个框面积列表输出分位数即可不复杂但非常管用。3. 用YOLO在本地跑通水稻慈姑类杂草检测VOC转YOLO格式与最小训练流程3.1 VOC标注转YOLO格式转换脚本与目录结构YOLO系列训练时接受txt标注文件每行格式是class_id x_center y_center width height坐标都是归一化到0到1的浮点数。Ultralytics YOLO不能直接吃VOC xml必须先转换。转换脚本的核心就一个把xml里的像素坐标除以图像宽高变成相对坐标再改写成txt。下面这个脚本我复制改一下类别列表就能用到多个数据集上import os import xml.etree.ElementTree as ET CLASSES [rice, sagittaria] def voc_to_yolo(xml_path, out_dir, img_width, img_height): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): name obj.find(name).text if name not in CLASSES: continue cls_id CLASSES.index(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.0 / img_width y_center (ymin ymax) / 2.0 / img_height box_width (xmax - xmin) / img_width box_height (ymax - ymin) / img_height lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_width:.6f} {box_height:.6f}) out_name os.path.basename(xml_path).replace(.xml, .txt) with open(os.path.join(out_dir, out_name), w) as f: f.write(\n.join(lines)) xml_dir annotations label_dir labels os.makedirs(label_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() w int(root.find(size/width).text) h int(root.find(size/height).text) voc_to_yolo(os.path.join(xml_dir, xml_file), label_dir, w, h)逻辑说明x_center和y_center由左右边界取平均值算出box_width和box_height是框的实际宽高全部除以图像宽高完成归一化。输出文件和xml同名后缀改为.txt。最关键的是逐张读取图片宽高再转换如果目录里混着多种分辨率的图写死宽高必然出错。转完后用文本编辑器随便开一个txt看一眼坐标值必须在0到1之间类别id只能是0或1。转换完的目录结构按YOLO惯例组织dataset/ ├── images/ │ ├── train/ # 约176张 │ ├── val/ # 约22张 │ └── test/ # 约23张 ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml里写清楚路径、类别数和类别名path: /绝对路径/dataset train: images/train val: images/val test: images/test nc: 2 names: 0: rice 1: sagittaria3.2 训练配置与超参数选择小数据集不该上大模型。221张图用YOLOv8x这种大模型即使有预训练权重也容易过拟合。我一般从yolov8s或yolov8n开始n最轻量s是速度和精度的平衡点。实际训练命令如下yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs200 \ imgsz640 \ batch8 \ seed42 \ device0几个参数背后的选择逻辑modelyolov8s.pt加载COCO预训练权重这是小样本训练能否收敛的底座随机初始化权重在221张图上基本跑不动epochs200对这个小数据集偏多但配合早停没有问题Ultralytics会在验证指标不再提升时自动停止batch8在单张消费级显卡上没问题显存不够就降到4seed42保证每次实验的数据划分和增强顺序一致方便对照。如果前面统计发现目标框偏小把imgsz改成896或1024代价是训练时间翻倍但小目标召回率通常会有明显提升。这里没有万能答案我的经验是从目标框面积中位数出发如果中位数边长小于原图宽度的5%imgsz就值得往上调。3.3 训练前必做的三件事训练前花十分钟检查数据能省掉后面两个小时的排错时间。我每次都会做以下三件事。第一检查有没有空的标签文件。部分标注过程会保存xml但没画框转换出来就是0字节txt。训练时images里有图但labels里没有对应文件YOLO会直接跳过这张图浪费样本且不易察觉。import os img_dir images/train label_dir labels/train img_names {f.split(.)[0] for f in os.listdir(img_dir)} label_names {f.split(.)[0] for f in os.listdir(label_dir)} missing img_names - label_names empty [f for f in os.listdir(label_dir) if os.path.getsize(os.path.join(label_dir, f)) 0] print(有图无标注:, missing) print(空标签文件:, empty)第二检查标注框是否越界。如果原始xml里的xmax比图像宽度还大归一化后会出现大于1的坐标训练和推理时会有边界错误。用脚本扫描所有txt坐标全部限制在0到1之间才安全。第三检查类别id顺序。data.yaml里的names顺序必须和训练读取的类别id一致。最典型的错误是xml里类别名用的是中文水稻和慈姑而CLASSES列表写的是英文顺序一错模型就把水稻学到了id1、慈姑学到了id0精度低还排查不出原因。跑训练前先打印一下任意一个txt文件内容确认。4. 小样本数据集避坑指南221张图最常见的5个翻车点4.1 翻车点一val loss掉头上升模型过拟合现象训练loss一路下降验证集loss在某个epoch后开始回升mAP停在低位不再提升。原因221张图太少模型在训练集上反复迭代逐渐把背景纹理、光照色偏这些无关特征也学进去了验证集环境一变就露馅。这是小样本目标检测数据集最典型的死法。解决先开早停Ultralytics里patience参数设30到50val loss连续多轮不降就停其次是降低模型容量yolov8s改成yolov8n再就是加强数据增强重点加光照和色偏扰动让模型不能靠颜色捷径区分目标。如果这三板斧下去val loss还在升就回到数据层面检查是不是训练集里有重复样本。4.2 翻车点二水稻和慈姑边界混淆现象预测结果里rice框里混着sagittaria或者反过来置信度高的框实际框住的是另一类。原因慈姑的箭形叶片在远距离拍摄时轮廓特征和水稻的条形叶片区分度不高苗期两种都是绿色模型很容易把形状特征学混。这个小项目本身类别语义就接近属于难分对不是模型坏了。解决我的经验是给模型加料而不是换药。先按标注框把rice和sagittaria的局部图块裁出来单独做图像分类的辅助训练或者把这些图块做copy-paste增强贴回训练图让模型多看到两类叶片的细部差异。推理阶段可以调低置信度阈值到0.15左右宁可多出框部署端再用目标位置和大小做规则过滤。如果换模型结构优先试带注意力机制的变体对细粒度差异有帮助。4.3 翻车点三验证集划分导致指标虚高现象训练时val mAP能到0.9部署到新田块直接垮掉。原因最常见的错误是随机划分时同一片田、同一时段拍摄的连拍图同时被分进训练集和验证集。验证集里全是见过场景指标自然好看一到新光照、新土质环境就原形毕露。这属于数据划分的结构性问题代码层面查不出异常。解决划分前先按拍摄时间、田块编号或文件名前缀分组确保同一场景的图像全部进train或全部进val。宁可验证集只有十几张也要场景隔离。这一步是田间小数据集的生死线我在这上面栽过一次后来所有农项目都先看文件名规律再切分。4.4 翻车点四类别不平衡白训练一场现象两个类别AP差距悬殊rice的AP有0.85sagittaria只有0.5。原因田间水稻苗数量通常远多于慈姑标注框数差距超过3倍时模型天然偏向多数类。221张图里如果rice框数3000、sagittaria只有800差距已经很危险。常见的数据集发布方式不会特意平衡两类框数需要自己处理。解决先看统计脚本输出的框数量。两种常见处理一是按框数量反比给少数类加loss权重在Ultralytics中可以调整分类损失的类别权重二是对少数类做重复增强把含慈姑的图像多复制几份再配合随机裁剪变相增加少数类样本量。注意copy-paste增强时贴进去的目标必须做轻微缩放和旋转否则模型会记住固定形态和位置。4.5 翻车点五图像尺寸与训练尺寸不匹配小目标全漏检现象大目标检测正常小目标几乎全漏召回率很低。原因原图1920x1080下40x40像素的稻苗缩到640x640输入时只剩约13x13像素特征图上一个格子都分不到漏检是必然结果。这个项目里慈姑苗期个体小特别容易踩这个坑。解决把imgsz调到896或1024同时打开mosaic增强。mosaic会把四张图拼接每个目标在新图里的相对尺寸更小模型被迫学会在更小尺度上识别目标。显存不够时batch降到2也要保住imgsz精度优先。训练后看验证集里小目标的recall变化这一步的收益通常非常明显。5. 数据增强与迁移学习把221张图的价值放大到极限5.1 针对性数据增强策略光照、裁剪和拼接水田环境的视觉干扰主要是光照变化和倒影。晴天正午和阴天早晨拍摄同一种杂草的颜色特征差异非常大所以数据增强里最值得加的是亮度扰动、对比度扰动和色调偏移。Ultralytics里这些augmentation参数可以直接在训练命令里控制yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs200 \ imgsz896 \ batch8 \ hsv_h0.02 \ hsv_s0.6 \ hsv_v0.5 \ degrees15 \ fliplr0.5 \ mosaic1.0参数说明hsv_h控制色调偏移幅度0.02已经足够太大容易让水稻叶片的绿色失真hsv_s和hsv_v控制饱和度和明度扰动0.6和0.5是田间场景常用的激进值能有效抵抗日照变化degrees15允许图像旋转15度田间拍摄角度并不总是水平fliplr0.5是水平翻转概率水稻田场景左右对称性高这个增强几乎没有副作用mosaic1.0让每个训练批都做拼接对提升小目标鲁棒性帮助很大。除了Ultralytics内置参数针对这个数据集我还会额外做一步把验证集里表现差的图像单独拿出来看如果集中在某个亮度区间就回去调hsv_v而不是盲目堆增强。增强参数不是越大越好过度增强会让模型学到失真纹理。5.2 迁移学习的关键参数预训练权重、冻结骨干层与学习率221张图上从零训练几乎等于白做预训练权重是唯一可靠起点。用COCO预训练权重时模型底层已有边缘、纹理、颜色特征需要学的只是水稻和慈姑的粗粒度形态差异这种上层概念用少量数据就能学出来。常见做法是冻结骨干网络的前10层只训练检测头和后几层收敛更快且有效降低过拟合风险。Ultralytics里用freeze参数控制yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs200 \ imgsz896 \ batch8 \ freeze10 \ lr00.005 \ lrf0.01freeze10表示冻结前10层参数这些层学到的是通用视觉特征没有必要让它们在221张图上重新调整lr0从默认的0.01降到0.005小数据集上学习率太大会把预训练特征在早期冲掉lrf0.01是最终学习率占初始学习率的比例让后期收敛更稳。冻结层数不是越多越好。如果冻到20层相当于只训练检测头模型学不到任何新的特征组合遇到苗期形态差异反而表现更差。我会先从freeze10试起对比不冻结和冻结两种配置在验证集上的AP差再决定。数据量越少冻结的层数越应该靠后这条经验在这个221张的项目里非常适用。6. 验证与进阶小样本也能做稳定评估再从221张往外扩展6.1 小样本下的稳定评估方法验证集只有二十几张图mAP方差大得惊人。我常用的做法是K折交叉验证把221张图按场景分组后切成3折每折轮流做验证最终报告3折mAP的平均值和标准差。这样虽然要训练3次但每一次都用到约200张训练图信息利用率比8:1:1高得多结论也更可信。评估时不只盯mAP还要单独看rice和sagittaria各自AP和召回率。如果recall偏低优先提高imgsz和mosaic强度如果precision偏低优先降低置信度阈值并加强后处理过滤。最后把验证集预测结果可视化把误检图并排贴出来看能发现很多指标上看不出的规律。6.2 从221张走向更大规模的数据扩展方向221张图作为起步够用要部署到真实田间环境还需要扩大一个量级。扩展优先级如下第一优先补不同生长阶段的图像慈姑从幼苗期到分蘖期形态差异极大只学一个阶段没法覆盖全年第二补不同天气和时段大逆光、阴天、雨后水反光、傍晚低照度这些是部署时最容易翻车的场景第三补不同地域的田块不同土壤背景和种植密度会影响泛化最后才是通过调整拍摄高度补充目标尺度多样性。收集新图像后沿用同一套标注标准和类别定义与现有221张合并重新划分再做一轮完整训练和评估。这个迭代流程的价值在于每一轮数据扩展都能定位当前模型的失效模式而不是盲目加数据。说到底小样本检测数据集拼的不是数量是每一次训练前对数据的理解和对坑的预判。221张图完全可以跑通一个像样的检测管线但前提是划分隔离、增强克制、迁移学习到位。我自己的习惯是每次拿到这类数据集先跑统计脚本再看loss曲线最后才信mAP。这套流程帮我避过不少坑希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网