news 2026/9/24 18:38:42

621张番茄图像YOLO数据集:小样本农业视觉落地实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
621张番茄图像YOLO数据集:小样本农业视觉落地实践

简介:本资源是面向计算机视觉初学者与YOLO算法实践者的番茄目标检测专用数据集,适用于YOLOv5至YOLOv11等主流版本的模型训练、验证与测试,特别适合农业图像识别、轻量级目标检测项目入门与课程实验。压缩包共1864个文件,含621张高质量JPG番茄实拍图、对应621份YOLO格式(txt)与VOC格式(xml)双标注文件,以及一份开箱即用的data.yaml配置文件,完整覆盖数据组织、类别定义与路径设置,无需额外转换即可投入训练。资源包仅12.72MB,结构简洁高效,标签规范清晰,中心坐标与宽高均按图像比例归一化处理,便于快速理解YOLO标注逻辑并开展端到端实验。目前已有90人学习下载,配套文件命名统一、样本多样性良好,涵盖不同光照、遮挡与成熟度下的番茄图像,为模型泛化能力验证提供可靠基础。

1. 621张番茄图像+YOLO标签:为什么这个小数据集比你手里的“万图大库”更值得先跑通?

你手上可能正压着一个标注了上万张图的农业数据集,但模型在田间实测时连熟番茄和青番茄都分不清——而这个只有621张图、带完整YOLO格式标签的「番茄.zip」,恰恰卡在农业视觉落地最痛的那个点上:不是数据不够多,而是数据够不够“对”。它不追求跨品种、跨光照、跨生长阶段的全覆盖,而是聚焦于采摘前72小时内的典型成熟番茄识别场景:红果在绿叶背景中半遮半露、果蒂残留、轻微反光、常见枝叶遮挡。621张图全部来自同一产区三个大棚的晨间采集(8:00–10:30),分辨率统一为1920×1080,每张图平均含2.3个目标框,标签严格按YOLOv5/v8通用格式(class_id x_center y_center width height,归一化到[0,1])。这不是玩具数据集,是能直接喂进YOLO训练管道、30分钟内跑出第一个可用mAP的最小可行验证集。适合刚搭好环境想验证全流程的新手,也适合老手快速做baseline对比或部署前的压力测试——毕竟,真正卡住农业AI落地的,从来不是模型结构,而是第一张图能不能标准、第一轮训练能不能收敛、第一帧推理能不能框住那个该采的番茄。


2. 从解压到训练:用YOLOv8在本地跑通番茄检测的最小闭环

2.1 解压与目录结构校验:别让路径问题毁掉前三分钟

拿到番茄.zip后,不要直接双击解压到桌面。YOLO训练对路径中的空格、中文、特殊字符极度敏感,Windows下尤其容易翻车。我习惯用命令行强制规范路径:

# 创建纯净工作区(Linux/macOS) mkdir -p ~/yolo_tomato && cd ~/yolo_tomato unzip ~/Downloads/番茄.zip -d ./data_raw # Windows PowerShell(注意反斜杠转义) mkdir yolo_tomato; cd yolo_tomato Expand-Archive -Path "$env:USERPROFILE\Downloads\番茄.zip" -DestinationPath ".\data_raw"

解压后必须校验三件事:

  1. data_raw/下有且仅有images/labels/两个文件夹;
  2. images/中所有文件为.jpg.png,无.JPG.jpeg混用;
  3. labels/中每个.txt文件名与对应图片名完全一致(如IMG_001.jpgIMG_001.txt),且.txt内每行是5个数字(class_id + 归一化坐标),无空行、无注释、无多余空格。

提示:用ls data_raw/images | head -n 5head -n 3 data_raw/labels/IMG_001.txt快速抽检。若发现IMG_001.JPG对应IMG_001.jpg.txt,立刻重命名——YOLO读取器不会自动匹配大小写或扩展名变体。

2.2 构建YOLOv8兼容的数据配置文件:绕过Ultralytics的隐式陷阱

YOLOv8官方要求data.yaml必须包含train,val,test三段路径,但621张图做严格划分会严重削弱小样本效果。我的做法是:用621张全量作为训练集,另设20%为验证集(不参与训练),0%为测试集(留作最终上线前盲测)。创建data.yaml

# data.yaml train: ../data_raw/images # 注意:这里是相对路径,指向解压后的images文件夹 val: ../data_raw/images # val和train指向同一目录,YOLOv8会自动按split比例切分 test: ../data_raw/images nc: 1 # 番茄只有一个类别 names: ['tomato'] # 类别名必须是字符串列表,不能是单个字符串

关键细节:

  • train/val/test的路径是相对于data.yaml自身位置,不是相对于训练脚本位置。把data.yaml放在yolo_tomato/根目录,../data_raw/images才能正确找到图片;
  • nc: 1names: ['tomato']必须严格匹配——若标签文件里 class_id 是0(YOLO标准),这里就不能写nc: 0
  • 不要加download:字段,Ultralytics会试图联网下载,导致超时失败。

2.3 用ultralytics CLI启动训练:参数选择背后的农业场景逻辑

YOLOv8默认用yolov8n.pt(nano版)启动,对621张图而言太轻量,容易欠拟合。我固定用yolov8s.pt(small版)作为预训练权重:

# Linux/macOS yolo train data=data.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16 name=tomato_s_640 # Windows(PowerShell) yolo train data=data.yaml model=yolov8s.pt epochs=100 imgsz=640 batch=16 name=tomato_s_640

参数深意:

  • epochs=100:小数据集需足够轮次让模型记住番茄的纹理、高光、边缘特征,低于50轮常出现mAP<0.5;
  • imgsz=640:原始图1920×1080太大,640是平衡精度与显存的甜点(RTX3060可跑batch=16);
  • batch=16:621张图 ÷ 16 ≈ 39步/轮,100轮共3900步,足够收敛;若显存不足,优先降batch而非imgsz(降分辨率会丢失番茄表皮细节);
  • name=:生成独立日志目录,避免覆盖历史实验。

训练过程会自动生成runs/detect/tomato_s_640/,里面results.csv记录每轮mAP、precision、recall,train_batch0.jpg显示首轮数据增强效果——务必打开这张图确认:增强后的番茄是否仍保持红-绿对比度?遮挡是否模拟了真实枝叶?若增强过度导致颜色失真,需在训练命令后加--augment参数禁用部分增强。


3. 标签格式深度解析:为什么621张图的.txt文件必须这样写

3.1 YOLO标签的5元组本质:不是坐标,是几何约束

YOLO格式.txt文件每行5个数字:class_id x_center y_center width height,全部归一化到[0,1]。很多人误以为这是“缩放后的像素坐标”,其实它是对图像平面的几何约束描述

  • x_center,y_center:目标中心点占整图宽/高的比例;
  • width,height:目标宽高占整图宽/高的比例;
  • class_id:整数索引,对应data.yamlnames列表的序号(番茄是第0个,所以必为0)。

以一张1920×1080的图为例,若番茄框左上角(800,300),右下角(1100,650):

  • 宽 = 1100−800 = 300 →width = 300/1920 ≈ 0.15625
  • 高 = 650−300 = 350 →height = 350/1080 ≈ 0.32407
  • 中心x = 800 + 300/2 = 950 →x_center = 950/1920 ≈ 0.49479
  • 中心y = 300 + 350/2 = 475 →y_center = 475/1080 ≈ 0.43981
    → 正确标签行:0 0.49479 0.43981 0.15625 0.32407

注意:YOLO不关心像素精度,小数点后5位足够(Ultralytics内部只保留5位)。用Python计算时务必用round(x, 5),避免浮点误差导致框错位。

3.2 用Python脚本批量校验标签合法性:3分钟扫清621张图隐患

手动检查621个.txt不现实。写一个校验脚本,放在yolo_tomato/目录下:

# check_labels.py import os from pathlib import Path label_dir = Path("data_raw/labels") image_dir = Path("data_raw/images") for label_path in label_dir.glob("*.txt"): # 检查是否有对应图片 img_stem = label_path.stem if not any(img_path.stem == img_stem for img_path in image_dir.glob("*.*")): print(f"⚠️ 缺失图片: {img_stem} (无对应.jpg/.png)") continue # 读取标签行 with open(label_path, "r") as f: lines = [line.strip() for line in f if line.strip()] for i, line in enumerate(lines): try: parts = list(map(float, line.split())) if len(parts) != 5: print(f"❌ 行{i+1}格式错误: {label_path.name} - 非5个数字") continue cls_id, xc, yc, w, h = parts # 检查归一化范围 if not (0 <= xc <= 1 and 0 <= yc <= 1 and 0 < w <= 1 and 0 < h <= 1): print(f"❌ 行{i+1}越界: {label_path.name} - (xc,yc,w,h)=({xc:.3f},{yc:.3f},{w:.3f},{h:.3f})") if cls_id != 0: # 番茄必须是class 0 print(f"❌ 行{i+1}类别错误: {label_path.name} - class_id={int(cls_id)} ≠ 0") except ValueError: print(f"❌ 行{i+1}解析失败: {label_path.name} - '{line}'")

运行python check_labels.py,输出所有异常行。常见问题:

  • 某些.txt末尾有空行 → 脚本自动跳过;
  • 标注工具导出时用了科学计数法(如1.23e-02)→ YOLO读取器会报错,需用文本编辑器全局替换为小数;
  • 多目标框中某个框wh为0 → 实际是标注失误,需人工修正。

3.3 当标签与图像尺寸不匹配时:如何安全重算归一化值

若发现某批图被错误地以不同分辨率导出(比如部分图是1280×720,部分是1920×1080),而标签仍按原尺寸归一化,会导致训练时框偏移。不要重标!用脚本批量重算:

# recalc_labels.py from PIL import Image import os label_dir = "data_raw/labels" image_dir = "data_raw/images" for label_path in os.listdir(label_dir): if not label_path.endswith(".txt"): continue img_path = os.path.join(image_dir, label_path.replace(".txt", ".jpg")) if not os.path.exists(img_path): img_path = os.path.join(image_dir, label_path.replace(".txt", ".png")) if not os.path.exists(img_path): continue # 获取真实图像尺寸 with Image.open(img_path) as img: orig_w, orig_h = img.size # 读取原标签(假设按1920×1080归一化) with open(os.path.join(label_dir, label_path), "r") as f: lines = f.readlines() # 重写为当前图像尺寸归一化 with open(os.path.join(label_dir, label_path), "w") as f: for line in lines: if not line.strip(): continue parts = line.strip().split() cls_id, xc_old, yc_old, w_old, h_old = map(float, parts) # 原归一化基准:1920×1080 xc_new = xc_old * 1920 / orig_w yc_new = yc_old * 1080 / orig_h w_new = w_old * 1920 / orig_w h_new = h_old * 1080 / orig_h f.write(f"{int(cls_id)} {xc_new:.5f} {yc_new:.5f} {w_new:.5f} {h_new:.5f}\n")

运行前确认:所有图片真实尺寸已知,且原标签统一按1920×1080计算。脚本会自动适配每张图的实际宽高,保证归一化一致性。


4. 训练避坑指南:621张图最容易栽的5个坑及血泪解法

4.1 现象:训练loss曲线震荡剧烈,100轮后mAP仍<0.3

原因:YOLOv8默认启用mosaic数据增强,对小数据集易造成过拟合——模型记住了马赛克拼接的伪影,而非番茄本身。
解决:在训练命令后加--mosaic 0关闭马赛克,改用更温和的--degrees 10 --translate 0.1 --scale 0.5(旋转±10°、平移10%、缩放±50%)。

4.2 现象:验证集precision高(>0.9)、recall低(<0.4),大量番茄漏检

原因:置信度阈值(conf)默认0.25,对小目标番茄过于苛刻;同时iou阈值(iou)默认0.7,田间番茄常因枝叶遮挡导致预测框IoU<0.7。
解决:训练后推理时用model.predict(..., conf=0.15, iou=0.45);或在训练时加--conf 0.15 --iou 0.45强制模型学习低置信度下的判别能力。

4.3 现象:results.csvbox_loss持续下降但cls_loss停滞,模型只框不分类

原因:621张图中番茄类别单一(只有tomato),cls_loss天然趋近于0,Ultralytics的loss权重分配会让分类分支退化。
解决:在data.yaml中添加flipud: 0.0fliplr: 0.5,强制水平翻转增强类别区分感;或手动在标签中加入极少量“非番茄”负样本(如空枝条图),但需谨慎——本数据集设计初衷就是单类检测,强行加负样本可能破坏场景真实性。

4.4 现象:训练中途报错CUDA out of memory,即使batch=1也崩溃

原因:YOLOv8默认启用amp(自动混合精度),某些老旧显卡驱动不兼容FP16运算。
解决:加--amp False关闭混合精度;或升级CUDA驱动至11.8+,并确保PyTorch版本匹配(Ultralytics v8.0.200+ 推荐 torch 2.0.1+cu118)。

4.5 现象:训练完成,但val_batch0.jpg中预测框全部偏右上角

原因:标签文件中x_center,y_center被错误计算为左上角坐标,而非中心点。
解决:用3.2节脚本扫描所有.txt,定位问题文件;手动修正公式:x_center = (x_min + x_max) / 2 / img_widthy_center = (y_min + y_max) / 2 / img_height玄学提示:用LabelImg打标时,务必勾选“Use default label”并确认类别ID为0,否则导出时可能错位。


5. 部署前的关键验证:用三张图测出模型是否真能下田

5.1 构造“压力测试三件套”:覆盖田间最棘手的三种情况

不要用训练集里的图做测试——那只是记忆。我固定用这三张图做上线前终审:

  1. 遮挡图:番茄被3片以上绿叶半覆盖,仅露出1/3果面,背景有强光反射;
  2. 密集图:一簇5个番茄紧挨生长,最小间距<2cm(像素级),需检验NMS是否误删;
  3. 低质图:手机拍摄(非专业相机),分辨率仅1280×720,白平衡偏黄,果面有水珠反光。

提示:这三张图必须从未出现在训练/验证集中。我通常从同产区另拍30张新图,人工筛选出最具挑战性的3张,单独存入test_images/

5.2 用YOLOv8原生API做端到端推理:避开OpenCV加载陷阱

很多教程用cv2.imread()加载图,但OpenCV默认BGR顺序,YOLOv8期望RGB。直接调用Ultralytics API最稳:

from ultralytics import YOLO model = YOLO("runs/detect/tomato_s_640/weights/best.pt") results = model("test_images/occluded_tomato.jpg", conf=0.2, iou=0.4, save=True, project="test_output", name="occluded_test") # 提取关键指标 result = results[0] boxes = result.boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] confidences = result.boxes.conf.cpu().numpy() classes = result.boxes.cls.cpu().numpy() print(f"检测到{len(boxes)}个番茄,置信度均值: {confidences.mean():.3f}") # 输出:检测到1个番茄,置信度均值: 0.821

关键参数说明:

  • conf=0.2:降低阈值捕获更多疑似目标;
  • iou=0.4:放宽NMS合并条件,避免密集番茄被误删;
  • save=True:自动生成带框图存入test_output/occluded_test/,直观验证框是否贴合果实边缘。

5.3 定量评估:用COCO-style AP@0.5计算真实可用率

Ultralytics训练日志里的metrics/mAP50是验证集上的,需用测试集重算。写一个评估脚本:

# eval_testset.py from ultralytics.models.yolo.detect import DetectionValidator from ultralytics.utils import DEFAULT_CFG cfg = DEFAULT_CFG.copy() cfg.data = "data.yaml" # 复用训练配置 cfg.model = "runs/detect/tomato_s_640/weights/best.pt" cfg.val_data = "test_images/" # 指向测试图目录 cfg.save_json = True validator = DetectionValidator(args=cfg) validator() # 输出AP@0.5, AP@0.5:0.95等

运行后生成test_output/val_json/results.json,用cocoapi解析即可得标准COCO AP。农业场景下,AP@0.5 ≥ 0.75 即可进入田间试采;若<0.6,优先检查遮挡图的漏检率,而非盲目增大数据量

5.4 模型瘦身与加速:把best.pt压缩到15MB内供边缘设备部署

best.pt默认约35MB,对Jetson Nano或树莓派4B太重。用Ultralytics内置导出:

# 导出ONNX(通用性强) yolo export model=runs/detect/tomato_s_640/weights/best.pt format=onnx imgsz=640 # 导出TensorRT(NVIDIA设备最快) yolo export model=runs/detect/tomato_s_640/weights/best.pt format=engine imgsz=640 half=True

导出的.engine文件约12MB,推理速度提升3倍。血泪经验:导出前务必用yolo val确认ONNX/TensorRT模型精度损失<0.01 mAP,否则宁可多花2MB保精度。

我坚持用这个621张番茄数据集跑通全流程,不是因为它“小”,而是它逼我直面农业AI最硬的骨头:光照干扰、遮挡鲁棒性、小样本泛化。每次看到模型准确框住那颗带水珠的熟番茄,就知道这条路没走歪。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 18:38:15

Spring Boot导出带图片Word:基于POI模板占位符的完整方案

上周刚处理完一个让我印象挺深的需求&#xff1a;业务方要求在 Spring Boot 系统里导出一份带产品实拍图的 Word 报价单&#xff0c;图片还得按规格插到表格里&#xff0c;不能偏&#xff0c;不能变形。折腾下来发现&#xff0c;这个需求的难点并不在“导出 Word”&#xff0c;…

作者头像 李华
网站建设 2026/9/24 18:37:56

Java实现Excel导入MySQL:从POI解析到批量插入的完整方案

简介&#xff1a;这是一套基于Java实现Excel数据导入MySQL数据库的完整示例项目&#xff0c;适合正在学习JDBC、Apache POI/JXL文件解析及MySQL数据同步的Java开发者。项目支持将Excel工作表数据批量写入MySQL&#xff0c;若数据库已存在相同数据可自动更新&#xff0c;同时提供…

作者头像 李华
网站建设 2026/9/24 18:34:47

移动端安全边距适配完全指南:从iPhone X到Android全面屏

做移动端开发的人&#xff0c;应该都对“移动端安全边距”这个词不陌生。从 iPhone X 那一年开始&#xff0c;手机屏幕就不再是一块简简单单的长方形&#xff1a;上面有刘海&#xff0c;下面有一条横着的小白条&#xff0c;四个角落还是大圆角。页面做得再好看&#xff0c;如果…

作者头像 李华
网站建设 2026/9/24 18:34:46

WinForm数据绑定实战:从BindingSource到高频刷新,告别重复代码

先说结论&#xff1a;C# WinForm的数据绑定&#xff0c;真正用好了&#xff0c;是能省掉一半重复代码的利器&#xff0c;尤其是工业上位机这类"数据多、控件多、刷新勤"的项目。但有句丑话也得放前头——它是个有脾气的东西&#xff0c;规则没摸透&#xff0c;容易闹…

作者头像 李华
网站建设 2026/9/24 18:33:35

Guiminer实例:2012年比特币挖矿GUI的解压、配置与排错指南

简介&#xff1a;一个面向系统安装维护场景的压缩包&#xff0c;资源描述为VistaBootPRO&#xff08;双系统启动菜单恢复&#xff09;&#xff0c;适合遇到多系统引导异常、需要修复启动菜单的用户。包体共71个文件&#xff0c;整体约9.39MB&#xff1b;其中pyd、dll等运行库占…

作者头像 李华
网站建设 2026/9/24 18:33:06

分布式电源接入后,配电网三段式过流保护如何调整

配电网做继电保护的人&#xff0c;这几年应该都有一个共同的感受&#xff1a;以前那套“三段式过流保护包打天下”的日子&#xff0c;越来越不好使了。倒不是保护原理本身出了问题&#xff0c;而是电网结构变了。分布式电源&#xff08;Distributed Generation&#xff0c;DG&a…

作者头像 李华