番茄目标检测数据集:YOLO农业标注与训练实战

发布时间:2026/9/26 2:52:06
番茄目标检测数据集:YOLO农业标注与训练实战 简介番茄目标检测数据集是一套面向农业场景的YOLO格式标注数据主要服务于计算机视觉研究人员、农业自动化工程师以及相关专业学生数据集中包含训练集、验证集和测试集数量分别为六百二十六张、一百七十九张和九十张合计八百九十五幅真实田间图像。所有图像均经过统一标注类别为番茄覆盖果实成熟度差异、不同生长阶段、光照变化、密集分布和枝叶遮挡等复杂情况。压缩包内共一千七百九十二个文件除八百九十五张图像外还提供等量的文本标注文件以及便于模型训练的配置文件和数据集说明文档整体大小约十五兆字节。当前已有三百二十四人学习下载该数据集特别适合用于开发番茄采摘机器人视觉系统、构建温室生长监测与产量预估模型也可作为精准农业和植物表型分析的教学科研素材能够帮助使用者在真实环境中快速验证和部署轻量化检测方案。1. 番茄目标检测数据集一份能直接喂给 YOLO 的农业标注数据做温室采摘机器人或者大田巡检的时候最卡脖子的不是模型结构而是数据。番茄目标检测数据集正是这类场景下急需的东西——它是一套已经标注好的番茄果实图像集标注格式按 YOLO 的 txt 规范组织拿到手就能开始训练不用再花一两周去画框。这份数据集对两类人最有用一类是正在做农业视觉项目、被标注逼到崩溃的工程师另一类是刚接触 YOLO 系列、想找个正经数据集练手的学生。和网上随手抓的杂图集不同这份数据里的目标尺度、遮挡情况和光照条件都更贴近真实棚室环境用它训出来的结果才有参考价值。2. 数据集结构与标注格式先看清家底再动手2.1 目录组织与 txt 标签的读写方式这份数据集解压之后目录层次是标准的 YOLO 布局images存放 JPG 原图labels存放同名 txt 标注文件。每个 txt 文件的文件名和对应图片完全一致只是扩展名不同。这个一一对应的关系是整个训练流程的地基任何一步破坏了这个映射训练时就会报Image not found或者干脆跳过样本。txt 文件里每行代表一个目标格式是class x_center y_center width height前四个值全部是归一化坐标范围在 0 到 1 之间。归一化的好处在于不随图片分辨率变化迁移到不同尺寸输入时不需要重新标一遍。我用一个脚本快速验证过文件对应关系代码如下import os from pathlib import Path img_dir Path(./images) label_dir Path(./labels) imgs {p.stem: p for p in img_dir.glob(*.jpg)} labels {p.stem: p for p in label_dir.glob(*.txt)} # 找出有图无标签或有标签无图的文件 img_only set(imgs.keys()) - set(labels.keys()) label_only set(labels.keys()) - set(imgs.keys()) print(f图片总数: {len(imgs)}) print(f标签总数: {len(labels)}) print(f有图无标注: {len(img_only)}) print(f有标注无图: {len(label_only)}) # 打印一个标签文件的内容看看格式 sample list(labels.values())[0] print(f样例标签: {sample}) with open(sample, r, encodingutf-8) as f: for line in f.readlines()[:5]: print(line.strip())这段代码的作用是体检先统计图片和标签数量是否一致再打印出一个标签文件的前几行肉眼确认坐标值是不是在合理区间。参数上需要注意glob的匹配规则如果数据里有 PNG 格式图片要把*.jpg改成*.png或者同时匹配两种。这是最容易翻车的细节很多人在这里核对不仔细结果训练跑了一半才发现漏了文件。2.2 类别分布与目标尺度训练前必须做的一次摸底看到标签格式正常别急着开训。先统计类别分布和边界框的大小分布这决定后面要不要调类别权重、要不要改 anchor 或者做切片。农业场景和通用目标检测的最大差异是目标尺度极其不均匀——番茄在幼苗期可能只有十几个像素成熟期却能占满半个画面。如果整个数据集都以成熟大果为主模型对早期小果的召回率会惨不忍睹。我一般用下面这个脚本做分布统计import numpy as np from pathlib import Path label_dir Path(./labels) class_counts {} box_areas [] for txt_path in label_dir.glob(*.txt): with open(txt_path, r, encodingutf-8) as f: for line in f: parts line.strip().split() if len(parts) ! 5: print(f格式异常: {txt_path} - {line.strip()}) continue cls int(parts[0]) w float(parts[3]) h float(parts[4]) class_counts[cls] class_counts.get(cls, 0) 1 box_areas.append(w * h) total sum(class_counts.values()) print(类别分布:) for cls, cnt in sorted(class_counts.items()): print(f 类别 {cls}: {cnt} 个目标, 占比 {cnt/total*100:.1f}%) areas np.array(box_areas) print(f边界框面积: 中位数{np.median(areas):.4f}, 5%分位{np.percentile(areas, 5):.4f}, 95%分位{np.percentile(areas, 95):.4f})这个统计结果对后续参数选择是决定性的。如果 5% 分位的框面积小于 0.01说明存在大量小目标训练时imgsz不能设太低至少 640 起步必要时用 1280。如果类别分布严重偏斜比如类别 0 占了 90%那就得考虑class_weights或者采样策略。这类数据摸底不是可选步骤而是训练前必须做的功课。3. 数据集划分与 YOLO 训练配置让模型真正跑起来3.1 训练集/验证集划分与 data.yaml 的组织方式数据没问题之后第一步是把数据切成训练集、验证集可能还要留一批测试集。常见做法是 8:1:1 或者 9:0.5:0.5。切分的时候有一个玄学问题同一棵番茄的不同视角照片会被分到两个集合里导致验证集和训练集高度相似mAP 虚高。为了尽量避开这个坑建议按图片采集时间或者植株编号来分组切分而不是纯随机打散。切分完成后YOLO 训练需要一份data.yaml它告诉模型去哪里读数据、要预测几个类别。对这个数据集配置文件长这样# data.yaml path: /path/to/tomato_dataset # 数据集根目录改成你实际解压路径 train: images/train val: images/val test: images/test # 类别数 nc: 3 # 类别名顺序要和标签txt里的class id一致 names: 0: tomato_red 1: tomato_green 2: tomato_partialpath字段建议写绝对路径。相对路径在单机训练时问题不大换机器或者换工作目录就会炸。nc和names必须和标注文件的 class id 严格对应一旦错位模型会把红番茄当成绿番茄来学训练过程不报错但验证结果会莫名其妙地差。划分脚本我通常写成可复现的形式固定随机种子import random from pathlib import Path import shutil random.seed(42) img_dir Path(./images) train_dir Path(./images/train) val_dir Path(./images/val) test_dir Path(./images/test) # 按文件名前缀分组同一株番茄的图放同一组 groups {} for img_path in img_dir.glob(*.jpg): prefix img_path.stem.split(_)[0] # 假设文件名形如 plant01_frame001.jpg groups.setdefault(prefix, []).append(img_path) group_names list(groups.keys()) random.shuffle(group_names) n_train int(len(group_names) * 0.8) n_val int(len(group_names) * 0.1) train_groups group_names[:n_train] val_groups group_names[n_train:n_train n_val] test_groups group_names[n_train n_val:] def copy_groups(group_list, dest_dir): dest_dir.mkdir(parentsTrue, exist_okTrue) for g in group_list: for img_path in groups[g]: shutil.copy(img_path, dest_dir / img_path.name) copy_groups(train_groups, train_dir) copy_groups(val_groups, val_dir) copy_groups(test_groups, test_dir) print(f训练组 {len(train_groups)}, 验证组 {len(val_groups)}, 测试组 {len(test_groups)})注意这个脚本是按文件名前缀分组的前提是文件名有规律。如果这份数据集的命名不带植株编号那就退回到随机切分但心里要清楚验证集 mAP 会有一定程度虚高。labels 目录也要同步切分YOLO 默认找images/train对应labels/train只需要把同样的分组逻辑复制到标签文件上即可。3.2 训练命令与超参取舍从 YOLOv8 到 YOLOv12 的差异数据集就绪后训练命令本身不复杂。以 YOLOv8 为例一行命令就能启动yolo train modelyolov8s.pt datadata.yaml epochs200 imgsz640 batch16 device0 projectruns nametomato_v8s关键参数逐个说清楚。modelyolov8s.pt是从 COCO 预训练权重开始迁移学习比从零训练收敛快得多对数据量少的场景尤其重要。epochs200是起步值农业数据集一般不大200 轮足够让 loss 进入平台期。imgsz640是精度和速度的平衡点如果你在 2.1 小节发现小目标比例高改成 896 或 1280 会更稳。batch16要看显存12GB 显存跑 640 分辨率用 16 基本安全不够就降到 8但梯度噪声会变大学习率也要相应调低。YOLOv12 或者更晚的变体在训练命令上几乎一致但内部机制有差异。v12 系列引入了注意力机制的重新设计对小目标和遮挡目标的特征提取更有利代价是显存占用比 v8 高。用 v12 的话建议 batch 降一档imgsz保持 640 起步。我一般会同时跑一组 v8s 和一组 v12s 做对比选择验证集 mAP 更高的那个作为最终模型因为农业场景里漏检比误检更致命不同版本在这两个指标上的取舍并不一样。训练过程中的监控点是 loss 曲线。box_loss和cls_loss应该在训练中段出现明显下降并趋于平滑如果box_loss反复震荡优先怀疑学习率过高把lr0从默认的 0.01 调到 0.005 再试。4. 数据增强与样本平衡小样本训练不翻车的关键4.1 内置增强参数Mosaic、MixUp 与 HSV 扰动怎么配数据集规模有限时增强不只是锦上添花而是决定模型能否泛化的关键。YOLO 内置的增强参数都集中在超参数文件里通过命令行的hyp参数指定。对番茄这类颜色特征显著、形状相对统一的目标HSV 扰动要相对克制。番茄的成熟度判断依赖颜色如果hsv_h调得太大红番茄被增强成紫番茄模型学到的颜色语义就歪了。我在农业数据集上常用的增强配置如下# hyp_tomato.yaml lr0: 0.01 lrf: 0.01 momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 hsv_h: 0.015 # 色相扰动降一半保护成熟度颜色信息 hsv_s: 0.4 # 饱和度扰动保持默认偏下 hsv_v: 0.4 degrees: 10.0 # 小角度旋转番茄藤蔓姿态变化有限 translate: 0.1 scale: 0.5 # 尺度扰动模拟相机远近 fliplr: 0.5 mosaic: 1.0 # Mosaic 增强训练前 60% 轮次开启 mixup: 0.1 # MixUp 比例调低避免把番茄纹理混合得太模糊mosaic和mixup是增强的核武器但也是翻车重灾区。Mosaic 把四张图拼在一起训练可以大幅提升模型对遮挡和小目标的适应力但训练后期必须关掉或调低否则模型会依赖拼接图的伪特征。YOLO 里mosaic设置为 1.0 表示全程开启我一般配合close_mosaic40让最后 40 轮关闭 Mosaic。4.2 自定义增强脚本Cutout 模拟枝叶遮挡内置增强解决的是全局光照和几何变化但番茄场景最常见的干扰是叶片遮挡。果实被枝叶挡住一半在检测框里表现为目标不完整。Mosaic 虽然能模拟遮挡但遮得太随机不如专门加一层 Cutout 增强来得可控。我自己写过一版针对遮挡的增强在训练前对图片做离线增强扩充一份遮挡样本import cv2 import numpy as np from pathlib import Path def cutout_random(img, num_holes3, hole_size_ratio0.05): h, w img.shape[:2] out img.copy() for _ in range(num_holes): hole_w int(w * hole_size_ratio * np.random.uniform(0.8, 1.2)) hole_h int(h * hole_size_ratio * np.random.uniform(0.8, 1.2)) x1 np.random.randint(0, w - hole_w) y1 np.random.randint(0, h - hole_h) # 用绿色填充遮挡块贴近叶片颜色 out[y1:y1 hole_h, x1:x1 hole_w] (50, 120, 50) return out img_dir Path(./images/train) out_dir Path(./images/train_cutout) out_dir.mkdir(exist_okTrue) for img_path in img_dir.glob(*.jpg): img cv2.imread(str(img_path)) if img is None: continue augmented cutout_random(img) cv2.imwrite(str(out_dir / f{img_path.stem}_cutout.jpg), augmented) # 标签文件直接复制同名 txt label_src Path(./labels/train) / f{img_path.stem}.txt if label_src.exists(): shutil.copy(label_src, out_dir / f{img_path.stem}_cutout.txt)这个增强脚本的关键是填充颜色选用了偏绿的值(50, 120, 50)模拟叶片遮挡。如果填充黑色或者白色增强出来的特征和真实遮挡差异太大模型学到的鲁棒性会打折扣。num_holes控制在 3 个以内太多会让目标完全消失标签框内容变成纯噪声。需要说明的是离线增强会成倍增加数据量训练时间跟着涨。一个折中的做法是只对训练集中被遮挡比例较高的图片做增强而不是全量复制。5. 避坑排查标注、训练、验证中最常见的 5 个翻车点5.1 现象训练开始后 loss 直接 NaN或者训练完 mAP 为 0原因多半出在标签文件上。最常见的两种情况一是 txt 里的类别 id 超出了data.yaml里nc的声明范围模型在计算分类损失时遇到非法索引二是某个标注框的坐标写成了负数或者大于 1 的绝对值归一化坐标非法时损失函数计算会直接爆炸。解决方法是训练前用脚本清洗标签文件。我一般会在数据集划分脚本里加一道校验过滤掉坐标越界的行并统计有多少文件被修改过import math from pathlib import Path def clean_labels(label_dir): cleaned 0 for txt_path in label_dir.glob(*.txt): lines txt_path.read_text(encodingutf-8).strip().splitlines() valid_lines [] for line in lines: parts line.split() if len(parts) ! 5: continue cls, x, y, w, h map(float, parts) # 坐标必须在 (0,1) 区间宽高必须为正 if not (0 cls 10 and 0 x 1 and 0 y 1 and w 0 and h 0): continue if x w / 2 1 or y h / 2 1: # 框超出右/下边界裁剪到边界内 w min(w, 2 * (1 - x)) h min(h, 2 * (1 - y)) valid_lines.append(f{int(cls)} {x:.6f} {y:.6f} {w:.6f} {h:.6f}) if len(valid_lines) ! len(lines): txt_path.write_text(\n.join(valid_lines), encodingutf-8) cleaned 1 return cleaned这个清洗逻辑会静默修正轻微的越界问题严重越界的行直接丢弃。使用这份数据集之前强烈建议先跑一遍清洗哪怕原始标注质量看起来很高批量处理的数据集难免有格式瑕疵。5.2 现象训练正常但验证集 mAP 很高实拍场景却频繁漏检原因典型是训练分布和实际部署分布不一致。数据集里的图片可能集中在一段时间、一个棚室、一种光照条件下采集模型学到的是特定条件下的特征换个环境就失效。这时候先别急着调参应该检查验证集图片和实拍图片的分布差异——光照角度、背景颜色、番茄品种是否一致。解决方法是做两组实验验证把实拍图片放进数据集并标注一小批参与训练观察 mAP 的变化。如果加入少量现场数据后实拍漏检率明显下降说明原数据集场景覆盖不够需要补充数据而不是调参。这不是数据集的问题而是迁移场景的自然约束。5.3 现象小目标番茄全部漏检大目标一切正常原因在上面说过目标尺度分布不均。YOLO 的下采样倍数决定了小目标在特征图中的有效信息量如果大部分标注框面积占比小于 0.05默认的 P3 检测头对小目标响应很弱。解决手段从上到下依次是把imgsz提高到 1280、开启 SAHI 切片推理、增加 P2 检测头YOLOv8 的yolov8s-p2.yaml可以直接用。切片推理效果最明显但推理耗时翻倍实时性要求高的场景要慎重。5.4 现象Windows 下训练报错提示图片读取失败原因多是路径分隔符和数据集路径中有中文字符。YOLO 在 Windows 上对中文路径兼容性很差path字段如果包含中文目录名OpenCV 读取图片时直接返回 None但训练脚本不会立即崩溃而是大量跳过样本训练出来的模型基本是废的。解决方法是把数据集放在纯英文路径下比如D:/datasets/tomato_dataset并且确保data.yaml里的路径使用正斜杠/不要用 Windows 默认的反斜杠\。5.5 现象训练时显存爆掉但模型很小原因不是模型大小问题而是batch和imgsz的乘积超出了显存。农业数据集经常有高分辨率原图按 640 输入训练时显存占用可控但如果你试着把imgsz提到 1280 而没降batch12GB 显存可能连 batch 8 都跑不动。解决方法是先跑一个batch4 imgsz1280的测试确认占用后再逐步往上加。也可以用yolo train的ampTrue混合精度训练显存占用能减少近一半。6. 进阶验证用 mAP、混淆矩阵和可视化判断模型是否真的能用训练完不是看训练曲线收没收敛就完事要用验证结果反向验证数据集的可用性。第一件事是复现最佳权重在验证集上的结果YOLO 在runs/tomato_v8s/weights/best.pt保存了验证集上 mAP 最高的权重。先跑一遍验证把指标拆开看yolo val modelruns/tomato_v8s/weights/best.pt datadata.yaml batch16 imgsz640正常情况mAP50应该能到 0.85 以上mAP50-95在 0.6 到 0.75 之间。如果mAP50很高但mAP50-95很低说明模型框的位置不够准边界框回归还有提升空间可以试试换更大的模型或者增加训练轮数。更细致的检查是画混淆矩阵。YOLO 训练完成后会在runs/tomato_v8s/confusion_matrix.png生成矩阵图。要看的关键位置是主对角线之外的密集点如果绿色青果和红果之间互相误检比例很高说明模型对成熟度的颜色区分还没学透需要检查增强配置里的hsv_h是否设置得太大。如果背景被误检为某类果实的比例高说明模型学到了一堆背景伪特征优先怀疑是标注框太松框里带了大量叶片或者标注框太小只框了果实中心。最后一步是可视化推理结果。找 10 到 20 张验证集里没参与训练的图片用权重跑推理保存结果图yolo predict modelruns/tomato_v8s/weights/best.pt source./images/test imgsz640 save_txtTrue save_confTrue人工看这 20 张图比看十行指标更有用。重点观察两类错误漏检图里有明显的番茄但模型没框和误检把叶子、侧枝当成果实。漏检集中在远处小果还是近处大果直接决定下一步是升分辨率还是加切片推理。误检的背景是重复纹理还是特定光照决定了要不要在增强里加特定颜色的遮挡模拟。我自己的习惯是每个数据集至少跑三组对比实验v8s、v12s、v8s 加自定义增强每组记录 mAP、漏检率、推理耗时。选模型的时候不能只看 mAP 数字要结合部署硬件的实际推理速度来判断毕竟采摘机器人对单帧推理耗时有硬约束。有一次我用了 mAP 最高的大模型上机实测单帧推理 85 毫秒运动模糊直接让漏检率升了 12 个百分点从那以后我每次选型都强制走一遍推理耗时测试再加现场图验证。希望这份番茄数据集的落地笔记能帮你少走这一步弯路。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询