简介:这份资源是面向计算机视觉学习者与智能农业开发者的西红柿成熟度目标检测数据集,可直接用于YOLO系列算法的训练与验证,帮助解决果蔬成熟状态自动分类的识别难题。压缩包共2000个文件,以1267个xml标注文件和733个txt标签文件为主,xml记录目标框与类别信息,txt适配YOLO训练格式,整体约303.56MB,覆盖半熟、绿色、完全成熟三个阶段的1267张图像。目前已有233人学习下载,适合课程设计、科研实验与农业监测项目练手。数据集对成熟度划分细致,能帮助模型学习绿红过渡斑点与全红外观之间的色彩和形态差异,提升泛化能力与检测精度,为收获效率与品质管理提供数据支撑。
1. 西红柿成熟度分级:从 1267 张带标签图像到可用的 YOLO 检测器
温室采摘线上,最让人头疼的不是有没有西红柿,而是这颗到底该不该摘。半熟、绿色、完全成熟三个状态混在一批果子里,靠人眼分拣,一个班次下来眼睛发花,标准还会漂移。这个标题指向的就是把这件事交给 YOLO:用 1267 张已经打好标签的西红柿图像,训练一个能区分半熟、绿色、完全成熟三个成熟度的目标检测模型。它适合两类人:一类是手里有类似农业图像数据、想跑通 YOLO 训练全流程的算法工程师;另一类是做智能采摘、分拣设备,需要先验证视觉方案可行性的产品与硬件同学。数据集规模不大,单卡就能训,但小数据集恰恰最考验标签质量、类别定义和增强策略,这也是后面要重点拆的部分。
2. 先想清楚三分类的边界:半熟、绿色、完全成熟到底怎么标
2.1 成熟度是连续量,但检测器只认离散框
西红柿从青到红是一个渐变过程,可 YOLO 输出的是离散类别加边界框。标题里给的三个类别——半熟、绿色、完全成熟——本质上是把连续的颜色变化切成了三段。切分点定在哪里,直接决定模型能不能学。常见做法是看果面转色比例:绿色指整体青绿、无红晕;半熟指出现明显橙红转色但未覆盖大部分果面;完全成熟指大面积红色、达到可采摘状态。如果标注时三个人三套标准,模型学到的就是噪声,mAP 会卡在一个不高不低的位置上不去,这种玄学问题十有八九出在标注一致性上。
提示:动手训练前,先随机抽 50 张图,让两个标注同学各自复核一遍类别,统计不一致率。超过 10% 就先统一标准,别急着开训。
2.2 1267 张够不够,取决于类别分布和场景多样性
1267 张在目标检测里属于小数据集,但农业场景往往背景相对固定,够不够用要看两点:一是三个类别的实例数是否均衡,二是光照、遮挡、拍摄角度是否覆盖了实际工况。如果完全成熟占了七成,绿色只有几十个实例,模型会强烈偏向多数类。这时候要么补采,要么在损失和采样上做平衡。YOLO 的损失函数本身对类别不平衡没有特殊照顾,分类分支用的是交叉熵类损失,少数类样本少,梯度贡献就小,这是小数据集翻车的常见原因。
2.3 标签格式与目录组织:先统一成 YOLO 能吃的结构
标题说“带标签”,但标签可能是 VOC XML、COCO JSON,也可能是已经转好的 YOLO txt。不管原始是什么,训练前都要统一成 YOLO 格式:每张图对应一个同名 txt,每行是类别索引 中心x 中心y 宽 高,坐标全部归一化到 0 到 1。目录一般组织成 images 和 labels 两个平行文件夹,再各分 train、val。下面这段脚本把常见的一图一 txt 标签做一次合法性检查,能提前揪出越界框和空标签。
import os import glob # labels 目录下所有 txt,逐行检查 YOLO 格式合法性 label_dir = "datasets/tomato/labels/train" bad_files = [] for txt_path in glob.glob(os.path.join(label_dir, "*.txt")): with open(txt_path, "r") as f: lines = [l.strip() for l in f if l.strip()] if not lines: bad_files.append((txt_path, "空标签")) continue for line in lines: parts = line.split() # YOLO 每行必须是 5 个值:cls x y w h if len(parts) != 5: bad_files.append((txt_path, f"字段数异常: {line}")) continue cls, x, y, w, h = parts vals = [float(x), float(y), float(w), float(h)] # 归一化坐标必须落在 0~1,宽高必须为正 if any(v < 0 or v > 1 for v in vals) or vals[2] <= 0 or vals[3] <= 0: bad_files.append((txt_path, f"坐标越界: {line}")) print(f"检查完成,问题文件 {len(bad_files)} 个") for p, reason in bad_files[:20]: print(p, reason)这段逻辑很直白:逐文件读标签,先排除空标签,再检查每行字段数和归一化坐标范围。参数上,label_dir换成你自己的路径即可;判断阈值用的是 0 和 1 的硬边界,实际中如果发现大量框贴边,可能是标注时框到了图像外,需要回原图确认。跑完这个检查再进训练,能省掉很多“loss 不降但也不报错”的排查时间。
3. 用 YOLOv8 跑通训练:配置文件、命令与三个必调参数
3.1 数据配置文件怎么写
YOLO 系列训练入口通常是一个 YAML 数据配置,指明训练集、验证集路径和类别名。类别顺序必须和标签里的索引严格对应,否则模型会把绿色学成完全成熟,这种错误在混淆矩阵上表现为两类互相大量误判。下面是一个最小可用的配置示例,路径按你的实际目录改。
# tomato.yaml path: datasets/tomato # 数据集根目录 train: images/train # 训练图,相对 path val: images/val # 验证图,相对 path names: 0: green # 绿色 1: half_ripe # 半熟 2: fully_ripe # 完全成熟这里names的键就是标签 txt 第一列的类别索引。很多人从 VOC 转过来时索引从 1 开始,直接喂进去会整体错位一位,训练 loss 看着在降,实际全错。转换脚本里务必确认索引从 0 开始。
3.2 训练命令与关键参数
假设用 YOLOv8 的 nano 或 small 版本起步,命令行训练最省事。小数据集不建议一上来就用大模型,参数量大、更容易过拟合,nano 或 small 先跑基线更稳。
# 从预训练权重起步,小数据集微调 yolo detect train \ data=tomato.yaml \ model=yolov8s.pt \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=30 \ project=runs/tomato \ name=exp1参数逐个说:epochs=150给小数据集留足收敛轮次,配合patience=30做早停,验证指标 30 轮不升就停,避免无效训练。imgsz=640是通用起点,如果西红柿在图中占比很小,可以提到 960 甚至 1280,但显存和速度要权衡。batch=16按显存调,显存不够就降到 8 并适当调小学习率。lr0=0.01是初始学习率,微调预训练模型时这个值通常够用,若 loss 前期震荡明显,降到 0.005 再试。model=yolov8s.pt是预训练权重,用迁移学习能显著缓解小数据集的过拟合。
3.3 三个最该盯的参数:imgsz、batch、增强强度
第一个是imgsz。西红柿检测里,果实相对整图往往偏小,分辨率直接决定小目标召回。640 下如果绿色小果经常漏检,优先提分辨率而不是加数据。第二个是batch。它和lr0是联动的,batch 翻倍时学习率可以适当上调,反之亦然,盲目改一个容易训崩。第三个是增强强度。YOLO 默认开启 mosaic、HSV 抖动等增强,对农业图像,HSV 的色调抖动要小心:成熟度本身就是靠颜色区分的,色调抖太狠会把绿色和半熟搅在一起,模型学不到稳定颜色特征。常见做法是把hsv_h调小甚至关掉,保留亮度和饱和度抖动来模拟光照变化。
注意:增强参数不是越多越好。成熟度分类任务里,颜色是核心判别特征,任何破坏颜色一致性的增强都要谨慎。
4. 小数据集训练避坑:从 loss 不降到类别混淆的排查清单
4.1 现象:训练 loss 正常下降,但验证 mAP 一直很低
原因通常有两个。一是训练集和验证集分布差异大,比如验证集全是逆光或遮挡严重的图,训练集却都是顺光清晰图。二是标签类别定义在训练集内部就不一致。解决方式是先做数据分布统计,把验证集按光照、遮挡分组看指标,再回头抽查标签。如果分组后某一组指标特别差,说明模型没学到该场景,需要补这类样本或针对性增强。
4.2 现象:绿色和半熟两类互相大量误判
这是成熟度检测最典型的坑。原因多半是标注边界模糊,绿色和半熟之间没有清晰判据,标注同学凭感觉标。解决分两步:先重新定义判据,比如用转色面积占比给出可量化标准;再对边界样本做复核,必要时合并成两类或增加一个过渡类。如果业务上确实需要三分类,就要接受边界样本的天然难度,在评估时单独看这两类的混淆情况,而不是只看总体 mAP。
4.3 现象:模型对完全成熟召回高,对绿色几乎检不到
典型的类别不平衡。绿色实例少,分类损失里贡献小。解决办法有三:一是在数据层面过采样绿色样本,复制或做针对性增强;二是在损失层面给少数类加权,YOLO 部分版本支持类别权重配置;三是降低置信度阈值看召回,但会引入更多误检。实操中优先补数据,权重和阈值是补救手段。
4.4 现象:训练到后期验证指标剧烈波动
小验证集导致的评估方差大。1267 张如果按 8:2 分,验证集只有两百多张,指标对个别样本敏感。解决方式是做交叉验证,或者把验证集扩大、训练集相应缩小,用更多轮次换更稳的评估。另一个原因是学习率后期没降下来,确认余弦退火或步进衰减是否生效。
4.5 现象:推理时框重叠严重,同一颗果子出多个框
NMS 阈值没调好,或者模型对同一目标输出了多个高置信框。先确认 NMS 的 IoU 阈值,默认 0.7 偏松时可以降到 0.5 左右。如果降了还重叠,说明模型本身没学好,回到训练环节查标签是否有重复框。标注时同一颗果子被标了两次,模型就会学出重复检测。
5. 把模型用起来:验证指标怎么读、推理脚本怎么写、阈值怎么定
5.1 别只看 mAP,分类别看混淆矩阵
训练完先看混淆矩阵,它直接告诉你哪两类在互相误判。成熟度任务里,绿色和半熟的混淆往往占大头。再看每一类的 precision 和 recall:如果绿色 recall 很低,说明漏检多,采摘线上会漏摘;如果 precision 低,说明误检多,会把没熟的当成熟的摘下来。业务上漏摘和误摘的代价不同,阈值就要跟着调。下面这段推理脚本把置信度阈值暴露出来,方便你按业务调。
from ultralytics import YOLO # 加载训练好的权重 model = YOLO("runs/tomato/exp1/weights/best.pt") # conf 是置信度阈值,iou 是 NMS 的 IoU 阈值 results = model.predict( source="test_images", conf=0.35, # 低于此置信度的框丢弃 iou=0.5, # 重叠框合并阈值 imgsz=640, save=True, save_txt=True # 同时输出 YOLO 格式结果,便于后续统计 ) # 统计每类检出数量,快速看分布是否合理 for r in results: names = r.names for cls_id in r.boxes.cls.tolist(): print(names[int(cls_id)])conf=0.35是偏保守的起点,漏检多就降到 0.25,误检多就提到 0.5。iou=0.5比默认 0.7 更严格,能压掉重叠框。save_txt=True输出的结果可以直接拿去做采摘决策的输入,比如统计一帧里完全成熟的数量。
5.2 阈值不是拍脑袋,用验证集画一条曲线
把验证集跑一遍,取不同 conf 下的 precision 和 recall,画 PR 曲线,选业务上可接受的平衡点。如果采摘设备对误摘零容忍,就选高 precision 对应的阈值,接受漏摘;如果先求覆盖,就选高 recall。这个决策要和业务方一起定,不是算法单方面拍。
5.3 一个提升小数据集效果的具体技巧:分阶段解冻训练
小数据集直接全量微调容易过拟合。我一般分两阶段:第一阶段冻结骨干网络,只训检测头,学习率可以稍大,让头先适配新类别;第二阶段解冻全部,用小学习率精调。这样既利用了预训练特征,又避免早期大梯度破坏骨干。YOLO 命令行里可以通过 freeze 参数控制冻结层数,先冻结前若干层跑几十轮,再解冻跑剩余轮次。血泪经验是,第二阶段学习率一定要比第一阶段小一个量级,否则前面学的头会被冲掉,指标不升反降。
这套流程跑下来,1267 张图在单卡上几个小时就能出基线。值不值得做,取决于你的场景是否稳定、标注能否统一。如果采摘环境光照变化剧烈、遮挡严重,先补数据比调模型更有效。希望帮到你。
本文还有配套的精品资源,点击获取