简介这份西红柿成熟度检测数据集面向计算机视觉学习者、农业AI研究者与目标检测项目开发者用于训练和评估番茄成熟度分级模型可支撑智慧农业采摘机器人、果蔬分拣流水线等场景的算法验证。资源采用Pascal VOC与YOLO双格式标注包含3241张jpg图片并配有等量的xml与txt标注文件覆盖tomato_half_ripe、tomato_overripe、tomato_ripe、tomato_rotten、tomato_unripe五个类别能直接用于YOLO系列或VOC框架下的检测训练。压缩包为7z格式共约2000个文件以1999个xml标注文件和1个说明txt为主整体大小34.62MB体积轻便便于快速下载与本地部署。目前已有709人学习下载适合需要现成标注数据开展成熟度识别实验、课程设计或论文复现的读者可省去自行采集与标注的成本快速进入模型训练与效果对比环节。1. 西红柿成熟度检测数据集3241 张 VOCYOLO 双格式5 个类别到底怎么用拿到一个标注好的西红柿成熟度检测数据集第一反应往往不是「太好了」而是「这 3241 张图、5 个类别、VOC 和 YOLO 两套格式我该从哪一步开始动手」。这个数据集解决的就是西红柿采摘机器人、分拣产线、大棚巡检这类场景里最基础也最要命的问题——让模型分清哪些果子能摘、哪些还得等。它适合三类人想快速跑通目标检测全流程的新手、需要成熟度分级做分拣逻辑的工程落地者、以及拿它当 baseline 去对比自己改进模型的研究者。VOC 格式给你 XML 标注的原始信息YOLO 格式给你直接能喂进训练脚本的 txt双格式省掉了自己写转换脚本的功夫但前提是你得知道两套格式的坐标逻辑完全不同直接混用就是翻车的开始。2. 先搞懂 VOC 和 YOLO 两套标注到底差在哪2.1 VOC 的 XML 存的是绝对像素坐标VOC 格式每张图对应一个 XML 文件里面bndbox的 xmin、ymin、xmax、ymax 都是相对于原图左上角的绝对像素值。这意味着图片一旦被缩放或裁剪标注就全废了必须同步变换坐标。西红柿成熟度检测里果实大小差异明显——青果小、红果大绝对坐标能保留真实尺寸信息方便你做尺寸相关的统计分析比如统计不同成熟度果实的像素面积分布。annotation foldertomato/folder filenameimg_0001.jpg/filename size width640/width height480/height depth3/depth /size object namemature/name !-- 成熟类别 -- bndbox xmin212/xmin !-- 绝对像素坐标 -- ymin156/ymin xmax298/xmax ymax241/ymax /bndbox /object /annotation上面这段 XML 里name就是类别标签5 个类别会在这里体现。size记录原图宽高转换时必须用它做归一化分母。如果你拿到数据集发现某些 XML 缺少size那这批图基本没法自动转 YOLO得手动补或者直接丢弃。2.2 YOLO 的 txt 存的是归一化中心点坐标YOLO 格式每张图对应一个 txt每行一个目标格式是类别索引 x_center y_center width height全部是 0 到 1 之间的归一化值。类别索引从 0 开始对应一个固定的类别列表顺序。这个顺序必须和你的data.yaml里names列表严格一致错一位整个训练就全乱。# 假设类别顺序为: [green, breaker, pink, light_red, mature] # 对应索引: 0 1 2 3 4 # YOLO txt 单行示例归一化后: # 4 0.398 0.414 0.134 0.177 # 含义: 类别索引4(mature), 中心点x0.398, 中心点y0.414, 宽0.134, 高0.177归一化公式很简单x_center (xmin xmax) / 2 / img_widthwidth (xmax - xmin) / img_widthy 方向同理。但这里有个高频坑——浮点数精度。3241 张图里如果有标注框刚好贴边归一化后可能算出 1.0000001 或 -0.0000001YOLO 训练时直接报错或静默丢弃该目标。稳妥做法是转换后统一做一次 clip 到 [0, 1]。2.3 5 个类别怎么映射到索引数据集给了 5 个类别但 VOC 的 XML 里写的是类别名字符串YOLO 的 txt 里写的是数字索引。你需要自己维护一张映射表并且保证训练、验证、推理三个阶段用的是同一张表。常见做法是在数据集根目录放一个classes.txt每行一个类别名行号就是索引。类别名示例索引典型外观特征green0通体青绿无红晕breaker1果顶开始转白/淡黄pink2浅粉至粉红面积小于 50%light_red3红色面积 50%~80%mature4通体深红无青斑这张表不是让你照抄而是提醒你拿到数据集第一件事就是确认类别名和索引的对应关系。如果数据集里没有现成的classes.txt你得从 XML 里把所有name提取出来去重排序再手动定索引。排序方式一旦定了就不要改否则之前训的权重全白费。3. 从 7z 压缩包到 YOLOv8 能直接训练的目录结构3.1 解压后先别急着改文件先做完整性检查7z 包解压后通常是一个大文件夹里面可能混着 VOC 的 XML、JPEGImages、YOLO 的 labels、images 等多套目录。第一步不是转换而是数数图片总数是不是 3241XML 数量是不是和图片一一对应YOLO 的 txt 数量是不是也一一对应。数量对不上后面训练 loss 不降你都不知道是模型问题还是数据问题。# 统计图片数量常见图片后缀 find . -type f \( -iname *.jpg -o -iname *.jpeg -o -iname *.png \) | wc -l # 统计 XML 数量 find . -type f -iname *.xml | wc -l # 统计 YOLO txt 数量排除 classes.txt 之类的非标注文件 find . -type f -iname *.txt ! -iname classes.txt | wc -l # 检查是否有图片没有对应标注 for img in $(find . -iname *.jpg); do base$(basename $img .jpg) if [ ! -f ./labels/${base}.txt ]; then echo 缺失标注: $img fi done上面这段 bash 里find的-iname忽略大小写因为有些数据集里后缀混用.JPG和.jpg。最后那个循环是排查「有图无标」的经典脚本3241 张图跑一遍也就几秒钟但能帮你提前发现几十张脏数据。如果缺失比例超过 5%建议直接联系数据提供方别自己硬补。3.2 按 YOLOv8 要求重组目录YOLOv8 训练时默认按images/train、images/val、labels/train、labels/val这样的结构找数据。你需要把 3241 张图按比例划分常见是 8:2 或 7:3。划分时注意同一颗西红柿的连续拍摄帧不要跨 train 和 val否则验证集精度虚高上线就翻车。import os import random import shutil from pathlib import Path # 配置路径 src_images Path(./images) # 原始图片目录 src_labels Path(./labels) # YOLO txt 目录 dst_root Path(./tomato_dataset) # 输出根目录 val_ratio 0.2 # 验证集比例 random.seed(42) # 固定随机种子保证可复现 # 收集所有图片 stem stems [p.stem for p in src_images.glob(*.jpg)] random.shuffle(stems) split_idx int(len(stems) * (1 - val_ratio)) train_stems stems[:split_idx] val_stems stems[split_idx:] # 创建目录 for subset in [train, val]: (dst_root / images / subset).mkdir(parentsTrue, exist_okTrue) (dst_root / labels / subset).mkdir(parentsTrue, exist_okTrue) # 复制文件 for subset, stem_list in [(train, train_stems), (val, val_stems)]: for stem in stem_list: shutil.copy(src_images / f{stem}.jpg, dst_root / images / subset / f{stem}.jpg) shutil.copy(src_labels / f{stem}.txt, dst_root / labels / subset / f{stem}.txt) print(ftrain: {len(train_stems)}, val: {len(val_stems)})这段脚本的关键参数是random.seed(42)固定种子后每次划分结果一致方便你复现实验。val_ratio设 0.2 意味着 3241 张里约 648 张做验证训练集约 2593 张。如果你的场景对漏检极度敏感可以把 val_ratio 提到 0.3用更多数据评估模型边界。复制完成后tomato_dataset目录就可以直接指向 YOLOv8 的data参数了。3.3 写对 data.yaml 是训练成功的一半data.yaml是 YOLOv8 找数据和类别的入口写错一个字段就是几小时白跑。路径建议用绝对路径避免工作目录切换后找不到文件。# tomato_dataset/data.yaml path: /absolute/path/to/tomato_dataset # 数据集根目录绝对路径 train: images/train # 相对 path 的训练图片目录 val: images/val # 相对 path 的验证图片目录 nc: 5 # 类别数必须和 names 长度一致 names: 0: green 1: breaker 2: pink 3: light_red 4: maturenc和names是重灾区。nc写 5 但names只列了 4 个训练启动就报索引越界。names的顺序必须和 YOLO txt 里的索引完全对应如果你在 2.3 节定的映射表是 green0这里就不能改成 mature0。改完 yaml 后建议用一行 Python 验证一下加载是否正常。import yaml with open(tomato_dataset/data.yaml, r) as f: cfg yaml.safe_load(f) assert cfg[nc] len(cfg[names]), nc 与 names 数量不一致 print(类别映射:, cfg[names])4. 用 YOLOv8 跑通第一轮训练参数怎么设、日志怎么看4.1 最小训练命令与关键参数含义环境装好 ultralytics 后一条命令就能启动。但默认参数不一定适合西红柿成熟度检测尤其是小目标多、类别间差异细的场景。yolo detect train \ datatomato_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/tomato \ nameexp01逐项说明modelyolov8n.pt用 nano 版先跑通流程显存占用低适合快速验证数据管道有没有问题。imgsz640是输入分辨率如果你的图片原图远大于 640西红柿在图中占比又小可以提到 960 或 1280但显存和训练时间会成倍增加。batch16在 8GB 显存上比较稳爆显存就降到 8。lr00.01是初始学习率YOLOv8 默认用 SGD 时这个值常见但如果用 AdamW 建议降到 0.001。patience20表示 20 轮验证指标不提升就早停防止过拟合。4.2 训练日志里必须盯住的三个指标第一轮训练启动后控制台会滚动输出 loss 和 mAP。别只看最后一行重点盯三个box_loss、cls_loss、mAP50。box_loss降不下去说明标注框回归有问题回去检查 YOLO txt 的归一化坐标是不是算错了。cls_loss震荡或居高不下多半是类别不平衡——5 个类别里如果 mature 样本远多于 breaker模型会偏向多数类。mAP50是综合指标但别只看它要配合混淆矩阵看具体哪两类在互相误判。from ultralytics import YOLO model YOLO(runs/tomato/exp01/weights/best.pt) metrics model.val(datatomato_dataset/data.yaml, splitval) print(mAP50:, metrics.box.map50) print(mAP50-95:, metrics.box.map) print(每类 AP:, metrics.box.ap_class_index)这段代码加载训练好的 best.pt 做一次独立验证输出每类 AP。如果 green 和 breaker 的 AP 明显低于其他类说明这两个早期成熟度类别在颜色特征上太接近需要补充更多区分性样本或者调整数据增强策略。4.3 数据增强参数对成熟度检测的影响YOLOv8 默认开启 mosaic、HSV 增强、随机翻转。对西红柿成熟度检测来说HSV 增强里的色调偏移要小心——你把红色果子的色调偏移大了模型可能把 mature 学成 pink。建议在训练配置里显式调低色调增强幅度。# 在 data.yaml 同级放一个 hyps.yaml训练时用 hyphyps.yaml 加载 hsv_h: 0.010 # 色调增强幅度默认0.015成熟度检测建议降到0.01 hsv_s: 0.7 # 饱和度增强保持默认 hsv_v: 0.4 # 明度增强保持默认 mosaic: 0.5 # mosaic概率小目标多可保持但成熟度细分类建议降到0.3 flipud: 0.0 # 上下翻转关闭西红柿通常不会倒挂 fliplr: 0.5 # 左右翻转保持hsv_h从 0.015 降到 0.010 是血泪经验色调偏移过大会让浅红和粉红在增强后几乎无法区分模型学到的边界模糊验证集上这两类互相误判率飙升。mosaic降到 0.3 是因为 mosaic 会把四张图拼一起西红柿在拼接图里尺寸更小成熟度细节丢失严重。5. 避坑与排查3241 张 5 类别数据集最容易翻车的 5 个地方5.1 现象训练 loss 正常下降但 mAP 始终在 0.3 以下原因YOLO txt 里的类别索引和 data.yaml 的 names 顺序不一致。比如 txt 里 green 标的是 0但 yaml 里 0 写成了 mature。模型学到的「0」和你评估时认为的「0」不是同一个东西mAP 自然上不去。解决写一个校验脚本从 YOLO txt 里提取所有出现过的类别索引和 data.yaml 的 names 键做集合比对。不一致就停下来改别硬训。import yaml from pathlib import Path with open(tomato_dataset/data.yaml) as f: cfg yaml.safe_load(f) yaml_indices set(cfg[names].keys()) txt_indices set() for txt in Path(tomato_dataset/labels/train).glob(*.txt): for line in txt.read_text().strip().splitlines(): if line: txt_indices.add(int(line.split()[0])) print(yaml 索引:, sorted(yaml_indices)) print(txt 索引:, sorted(txt_indices)) assert txt_indices.issubset(yaml_indices), txt 中存在 yaml 未定义的类别索引5.2 现象验证集 mAP 很高但拿新拍的西红柿图片推理框全歪了原因训练时用了 letterbox 填充推理时没有保持同样的预处理。YOLOv8 默认推理也会 letterbox但如果你自己写了预处理脚本把图片直接 resize 到 640x640 而不保持宽高比坐标映射就错了。解决推理时直接用 ultralytics 的model.predict()不要自己写 resize。如果必须自己预处理确保和训练时的 letterbox 参数一致并且把预测框反映射回原图坐标。5.3 现象green 和 breaker 两类混淆严重混淆矩阵里互相误判超过 30%原因这两个类别在颜色上差异细微尤其在不同光照下。数据集里如果 green 和 breaker 的样本数量悬殊模型会偏向多数类。解决先统计各类别样本数对少数类做过采样或专门收集更多该类别图片。同时降低 HSV 色调增强幅度避免增强后两类颜色更接近。还可以在损失函数里给少数类更高权重但 YOLOv8 默认不直接暴露类别权重参数需要改源码或换用支持 class weights 的训练框架。5.4 现象训练到一半突然报 CUDA out of memory原因batch设太大或者imgsz提太高或者 mosaic 增强时四张图拼一起导致单批实际像素量翻倍。解决先把batch降到 8 或 4再考虑降imgsz。如果都不想降可以开启梯度累积用nbs参数模拟大 batch。另外检查有没有其他进程占着显存nvidia-smi看一眼再重启训练。5.5 现象7z 解压后文件名乱码图片和标注对不上原因压缩包在 Windows 下打包中文文件名编码和 Linux 解压默认编码不一致。解决用7z x -mcp936指定 GBK 编码解压或者先在 Windows 下解压再传到 Linux。解压后统一重命名成纯英文数字文件名避免后续脚本处理时再遇到编码问题。# 用指定编码解压 7z x tomato_dataset.7z -mcp936 -o./extracted # 批量重命名去掉中文和特殊字符 cd extracted/images i0 for f in *; do ext${f##*.} mv $f $(printf %05d $i).$ext i$((i1)) done6. 把 5 类别成熟度模型推到可用精度的两个进阶技巧第一个技巧是分层采样验证集。3241 张图如果随机划分可能出现验证集里某个类别只有个位数样本mAP 波动极大。我一般会按类别做分层抽样保证每个类别在验证集里至少有 50 张。实现上可以先按类别分组每组按比例抽再合并。这样得到的 mAP 更稳定也更能反映模型在各类别上的真实表现。第二个技巧是用测试时增强TTA换精度。YOLOv8 推理时加augmentTrue会做多尺度翻转推理再融合mAP 通常能涨 1 到 3 个点代价是推理时间翻倍。对分拣产线这种对延迟不敏感、但对漏检敏感的场景TTA 很划算。开启方式很简单from ultralytics import YOLO model YOLO(runs/tomato/exp01/weights/best.pt) results model.predict( sourcetest_images/, augmentTrue, # 开启 TTA conf0.25, # 置信度阈值成熟度检测建议0.25起步 iou0.5, # NMS IoU 阈值 saveTrue )conf0.25是我在成熟度检测里常用的起点因为漏检一个成熟果子比误检一个青果代价高。如果你的场景允许更多误检可以降到 0.15 再观察。iou0.5控制 NMS 合并重叠框的力度如果同一颗果子被检出多个框适当降低 iou 到 0.4。最后说个习惯每次改完数据或参数先跑 10 个 epoch 看 loss 曲线和 mAP 趋势别一上来就 300 epoch。10 轮里如果 mAP 完全不涨后面 290 轮大概率也是浪费时间。这个习惯帮我省下的 GPU 时间够多跑几十组对比实验了。希望帮到你。本文还有配套的精品资源点击获取