
简介这套番茄圣女果/西红柿目标检测数据集面向计算机视觉初学者、课程设计学生及科研入门者尤其适合正在训练YOLOv5等检测模型、需要现成标注数据完成迁移学习或实验验证的读者。压缩包共1788个文件主要提供895张PNG原图、892个PASCAL VOC格式的XML边界框标注文件以及1个数据清单txt整体约180.4MBXML标注可直接交给目标检测框架读取免去自行采集图像和手工标注的重复工作。已有2868人学习下载说明这套数据集在常用场景下经过较多使用者验证。需注意其中tomato0、tomato1、tomato10三个XML文件已损坏需重新标注其余889个XML标注文件完整足够支撑多数目标检测训练与验证任务。借助该数据集可快速搭建番茄检测流程集中精力做数据增强、超参数调优与模型评估也可用于练习PASCAL VOC格式到YOLO等格式的转换提升目标检测实战能力。1. 番茄圣女果/西红柿数据集为什么目标检测团队都拿它做算法验证一个分类良好的番茄数据集今天早就不只是农业采摘机器人的专属原料。做目标检测、实例分割、高光谱分析的工程师往往在跑通公开数据集之后拿它当成验证算法鲁棒性的“实验台”。原因是番茄的形态天然覆盖了目标检测里最难啃的三种情况密集粘连、遮挡重叠、表面反光。同一个果实在不同成熟度下颜色从青绿到深红连续变化目标尺度跨度大这让番茄数据集在迁移学习里几乎成了“小目标形变”的替身。如果你是刚接触数据集清洗、标注格式转换或YOLOv8/YOLOv5训练流程的人这组数据能让你少走很多弯路下载渠道公开、标注格式统一、训练收敛速度快。本文按我实际做过的方案从数据集选型讲到格式转换、训练参数和易踩的坑。2. 把番茄数据集用起来三类公开来源与标注格式的取舍2.1 自建采集 vs. 公开数据集哪种更适合你的场景做番茄相关项目时我通常先问自己一个问题我要的是成熟度分级还是采摘点定位还是单纯拿它验证检测算法这个问题的答案决定了数据来源。如果你做的是采摘机器人或温室监测必须自建采集。常见做法是用RGB相机固定高度、固定角度拍温室或大田覆盖不同光照时段拍完用LabelImg或X-AnyLabeling标注。这类数据集的优点是背景贴近真实作业环境缺点是成本高一批数据从采集到清洗再到标注少说一周时间。如果目标是算法验证和模型调优建议直接使用公开的番茄数据集。目前能找到的主要有三类第一类是用于目标检测的标注格式多为COCO或VOC里面包含大量在不同光照和遮挡条件下拍摄的番茄图像第二类是用于语义分割的提供像素级掩膜常见于成熟度分级研究第三类是用于高光谱分析的格式往往为.mat或HDF5这类和公开的icvl高光谱数据集风格更接近适合做光谱特征提取实验。公开数据集的优势很明显处理好的标签能直接供给YOLO系列训练不需要你为标注质量操心。劣势同样明显背景相对单一换到你的实际场景后往往需要二次微调如果要在YOLOv8上训练自己的数据集通常需要按你的现场图像做增广。2.2 COCO、VOC、YOLO三种格式的核心字段与转换判断拿到番茄数据集后第一件事不是急着开训练而是确认标注格式。很多初学者在“数据格式不统一”这一步就卡住浪费大量时间。这里把三种常见格式的关键字段摆清楚COCO格式的标签文件是单个JSON里面包含images、annotations、categories三部分。annotations里每条记录有bbox、area、segmentation和category_id其中bbox按“左上角x、左上角y、宽度、高度”记录。VOC格式则是一个XML对应一张图片标注信息写在object节点下的bndbox里按“左上角x、左上角y、右下角x、右下角y”记录。YOLO格式则完全不同每张图片对应一个同名txt文件每行是“类别id x_center y_center width height”数值全部做了归一化范围在0到1之间。这三种格式的差异就是无数新手在“处理数据集用于yolov8训练”时翻车的根源。COCO和VOC的bbox坐标都是绝对值像素值YOLO需要的是相对值归一化到0~1。同时COCO的坐标是(x,y,w,h)YOLO也是(x,y,w,h)但VOC的坐标是(x1,y1,x2,y2)这中间要先做一次坐标转换。针对番茄数据集我一般会先写一个脚本检查标注格式再做转换这也是下面要讲的重点。3. 转换到 YOLO 格式并训练从标注框到 mAP 的关键命令3.1 从COCO JSON转换为YOLO TXT的Python脚本把番茄数据集从COCO转成YOLO几乎是我每次做目标检测项目都要重复一遍的工作。一个能直接复用的脚本如下import json import os from PIL import Image def convert_coco_to_yolo(coco_json_path, image_dir, output_dir): # 读取COCO格式的JSON文件 with open(coco_json_path, r, encodingutf-8) as f: coco_data json.load(f) # 建立类别ID到索引的映射这里按category_id排序 categories coco_data[categories] cat_id_to_idx {cat[id]: idx for idx, cat in enumerate(categories)} os.makedirs(output_dir, exist_okTrue) # 以图ID为索引收集每张图的标注信息 img_id_to_annos {} for ann in coco_data[annotations]: img_id ann[image_id] if img_id not in img_id_to_annos: img_id_to_annos[img_id] [] img_id_to_annos[img_id].append(ann) for img_info in coco_data[images]: img_id img_info[id] file_name img_info[file_name] width img_info[width] height img_info[height] # 生成与图片同名的txt文件 txt_name os.path.splitext(file_name)[0] .txt txt_path os.path.join(output_dir, txt_name) with open(txt_path, w) as out_file: annos img_id_to_annos.get(img_id, []) for ann in annos: cat_idx cat_id_to_idx[ann[category_id]] bbox ann[bbox] # COCO格式: [x_min, y_min, width, height] x_min, y_min, w, h bbox # 归一化到[0,1]区间YOLO格式要求的核心操作 x_center (x_min w / 2) / width y_center (y_min h / 2) / height w_norm w / width h_norm h / height # 防止归一化后数值越界 x_center min(max(x_center, 0), 1) y_center min(max(y_center, 0), 1) w_norm min(max(w_norm, 0), 1) h_norm min(max(h_norm, 0), 1) # 写入一行: class_id x_center y_center width height out_file.write(f{cat_idx} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}\n) print(f[转换] {file_name} - {txt_name}, 类别: {cat_idx}) if __name__ __main__: # 替换为你的实际路径 convert_coco_to_yolo( coco_json_pathtomato_dataset/annotations/instances_train.json, image_dirtomato_dataset/images/train, output_dirtomato_dataset/labels/train )这段代码的执行逻辑很直接先从JSON里读出类别和标注然后对每一张图生成一个txt文件将COCO的bbox从“左上角宽高”转成“中心点宽高”最后归一化。需要注意两个容易忽略的参数一个是图片的实际宽高值不要用文件读取而直接用JSON里的width和height因为高度不一致的图片在转换时会出错另一个是归一化后的数值一定要做边界约束有些标注框边界溢出图片范围不约束的话训练时会出现NaN损失。3.2 YOLOv8训练番茄数据集的目录结构与最小命令转换完标注后目录结构要按YOLO系列约定摆放。一个最小可跑的目录长这样tomato_yolo/ ├── images/ │ ├── train/ # 训练图像 │ └── val/ # 验证图像 ├── labels/ │ ├── train/ # 与训练图像同名的txt标注 │ └── val/ # 与验证图像同名的txt标注 ├── data.yaml # 数据配置文件 └── runs/ # 训练输出目录data.yaml文件内容如下注意路径不要写成绝对路径使用相对路径时训练机移动目录不会失效# 类别名称顺序要与前面转换时的索引一致 names: 0: tomato_ripe 1: tomato_unripe # 数据集路径以tomato_yolo目录作为根 train: images/train val: images/val # 类别数量 nc: 2目录和配置就绪后训练命令只需要一行。我一般会在训练前先用小批量测试一次链路是否通畅# 先验证数据加载是否正常不实际训练 yolo detect train datatomato_yolo/data.yaml modelyolov8n.pt epochs1 batch2 # 确认没有报错后再正式训练 yolo detect train datatomato_yolo/data.yaml modelyolov8n.pt epochs100 batch16 imgsz640 patience20参数里epochs设100对单类别番茄检测已经够用因为公开番茄数据集的类别通常只有两到三类成熟番茄、未成熟番茄、背景收敛速度比COCO那80类快得多。batch16是在12GB显存下的常用值如果显存不够就降到8。imgsz640是速度和精度的平衡点想追求小目标召回可以抬到768或960但训练时间会按平方增长。patience20的意思是验证集指标连续20轮不提升就自动停止这可以避免无效训练占用时间。3.3 训练结果怎么看与mAP偏低时先查哪里训练结束后跑一次验证脚本看指标yolo detect val datatomato_yolo/data.yaml modelruns/detect/train/weights/best.pt屏幕会输出mAP50、mAP50-95、precision、recall四组指标。番茄数据集的正常水平是mAP50大于0.9mAP50-95在0.75左右。如果你的结果明显低于这个区间不要急着调模型结构先查三件事标注框有没有错位、图像是不是有大量重复、训练集和验证集是不是来自同一批视频帧。很多时候mAP虚高或偏低都是这三件事造成的而不是模型问题。4. 番茄目标检测的避坑清单反光、重叠与标注口径4.1 表面反光带来的漏检误检现象训练时loss正常下降推理时在强光照下的番茄表面动不动就漏检或者在反光处出现一个多余的框。原因番茄表皮光滑露水和棚膜反光会形成高光区域这个区域的颜色接近白色和目标特征差异极大。如果训练图像里反光样本不够模型会把高光部分当成背景。很多人第一次跑番茄数据集都会在这个问题上翻车这算是这类数据集典型的“玄学”问题。解决核心是增广而不是换模型。在训练配置里把HSV变换的饱和度增强拉大同时加上随机亮度和对比度变化。用Ultralytics的配置方式就是在data.yaml里加一段增广参数把hsv_s调高再把scale和flip打开。另一个实用技巧是采集数据时不要只挑光线好的时候拍把逆光、侧光、阴天中午的样本都放进去让模型见过反光的变体。4.2 果实重叠与遮挡导致标注边界不清晰现象mAP50看起来不差但实例分割或框的定位精度很低尤其在果实重叠区域框整体偏移。原因番茄是簇生果实一束里面三五个果子挤在一起互相遮挡严重。标注人员在画框的时候对“该框住整个果实还是只框可见部分”的理解不一致导致同一批数据里既有框完整果实的标注又有框可见部分的标注。模型在两种标注口径之间摇摆自然学不准。解决在标注前定一个硬规则——统一按“可见部分框住严重遮挡的不标”。被遮挡超过80%的果实直接放弃标注这样能减少噪声。如果你用的是公开数据集要看它的标注文档里是否说明了遮挡处理方式。没有说明的情况下训练时打开YOLOv8的overlap mask选项可以缓解但对框类任务作用有限。用YOLOv8做实例分割时这个问题影响更大。4.3 成熟度类别判断受光照色温影响现象验证集里未成熟番茄的召回率明显低于成熟番茄误把青色番茄漏掉。原因未成熟番茄的颜色偏绿在暖色棚膜和早晚低色温光照下颜色会偏移到灰黄和枯叶背景区分度下降。成熟番茄是红色色温漂移后依然是红色系里鲁棒性天然高一些。解决做类别均衡重采样。计算训练集中成熟与未成熟的样本比例如果比例超过3比1按比例做欠采样或过采样让模型见到足够多的未成熟样本。同时针对青色果实手工增加绿色背景的负样本不带果实的叶片图像防止模型把整片绿叶误判成未成熟果实。4.4 数据划分不当导致指标虚高现象训练时mAP很好测试自己拍的视频时完全拉胯。原因很多人下载公开数据集后按文件顺序切分训练验证集但很多番茄公共数据集的图片是从连续视频里抽帧的。连续帧之间高度相似按顺序切分会造成“训练集见过验证集的邻居帧”指标好看但没有泛化意义。解决按视频片段或田块切分不要按帧顺序随机切。如果数据集没有提供视频分组信息就用图像的文件名或聚类方法把相似帧归到同一组再按组划分。躺平一点的做法是每个文件夹里前80%做训练、后20%做验证保证同一个文件夹内的连续帧不跨集合。这样才能避免“数据集指标好看实际场景翻车”的尴尬。5. 高光谱与多模态方向番茄数据集的上限在哪里5.1 高光谱番茄数据集从检测到品质分析如果说RGB番茄数据集解决的是“果实在哪里”的问题高光谱番茄数据集要解决的则是“果实状态怎么样”的问题。常见做法是用高光谱相机采集400~1000nm波段范围内的番茄光谱曲线配套标注成熟度、含水率或糖度。这类数据集的格式很多是.mat或HDF5读法上跟处理icvl高光谱数据集mat的思路类似。一个读取.mat格式的高光谱番茄样本的最小Python示例如下import h5py import numpy as np # 读取HDF5格式的高光谱数据 with h5py.File(tomato_hs.mat, r) as f: # 打印顶层结构看看key是什么 print(list(f.keys())) # 假设数据存在hypercube这个key下维度是(高度, 宽度, 波段数) hypercube f[hypercube][:] print(f高光谱数据形状: {hypercube.shape}) # 通常还需要读取波长信息用于后续波段选择 wavelengths f[wavelengths][:] if wavelengths in f else None高光谱数据量极大直接放进YOLO训练不现实。常规做法是先做波段降维比如用PCA或选择特征波段把几十上百个波段压缩成3个通道再转成伪RGB图送到检测网络。数据增强上注意高光谱数据不能像RGB那样随便做色相偏移因为波段值反映物理属性任意扭曲会破坏光谱曲线。你可以对空间维度做翻转和裁剪但光谱维度的扰动要极其谨慎。5.2 多模态融合番茄采摘机器人的视觉方案这里再提一下“多模态数据集”对番茄场景的启发。采摘机器人常见的做法是把RGB图像和深度图对齐生成RGB-D数据有时还会加入近红外通道来识别被叶片遮挡的果实。做这类方案时数据集的模态对齐是最大的坑RGB和深度图的坐标系、分辨率、拍摄时间必须严格对齐否则融合后特征错位。如果你只做目标检测先只在RGB通道上训练把深度通道作为辅助监督信号来用会少踩很多标定上的坑。5.3 从数据到模型的常规路径一张清晰的流程图在整个番茄数据集的落地流程里各步骤的数据流关系如下原始图像采集 - 图像清洗(去模糊去重复) - 标注(检测框/分割掩膜) - 格式统一(COCO/VOC/YOLO) - 数据集划分 - 增广 - 模型训练/验证 - 导出TensorRT/ONNX - 部署这里面最容易被忽略的是“格式统一”和“数据集划分”两步它们不产生直接收益但决定了后续所有步骤是否稳定。很多开源项目里预处理脚本和数据文件是一起打包的拿到手第一件事就是检查脚本里的路径和类别顺序有没有被改过。这不算技术难点但绝对是血泪经验。6. 用番茄数据集做算法验证三个能直接复用的技巧第一个技巧是做一个类别热量图。训练完成后把所有验证集图像过一遍模型把漏检的目标位置标在热图上。番茄的漏检位置往往集中在图像边缘和果实密集区域你可以快速判断是增广不足还是NMS阈值不合适。这个方法比只看mAP直观得多。第二个技巧是利用混淆矩阵判断成熟度分级精度。YOLO训练日志里会输出混淆矩阵图对番茄数据集你重点关注成熟番茄和未成熟番茄之间的误分情况。如果误分集中在特定颜色阶段比如半成熟果说明你的类别定义太细得考虑把半成熟并入未成熟类或者增加过渡态样本。第三个技巧是把训练好的RGB检测权重当作预训练模型在另一个小规模番茄分类数据集上微调。因为番茄的颜色和纹理特征相似迁移后只需要很小的数据量就能获得高准确率这比每次从ImageNet预训练从头训练省不少时间。从我做过的项目来看番茄数据集最有价值的用法不是追求在公开榜单上刷点而是作为检测算法在抗反光、抗遮挡能力上的磨刀石。每次在番茄上效果好其他作物场景里也不会差太多。这是我反复用这组数据验证算法的原因。希望这些做法帮你在下一个项目里少走几步弯路。本文还有配套的精品资源点击获取