
简介本资源是面向农业AI开发者、计算机视觉研究者及高校教学实践的番茄叶子实例分割专用数据集聚焦植物病害识别、生长监测与农业机器人视觉感知等实际需求解决作物器官级精细分割建模的数据瓶颈问题。压缩包共1436个文件含717张高清晰度JPG图像真实农田场景采集、717个YOLO格式TXT标注文件含多边形顶点坐标支持Mask R-CNN、YOLOv8-seg等主流实例分割模型、1个类别定义YAML配置文件及1份详细说明DOCX文档整体体积仅23.42MB轻量易部署。已有94人学习下载适用于从入门到进阶的实例分割项目实战可直接用于模型训练与评估配套文档明确标注规范与使用路径图像文件名采用IMxxx-1_JPG.rf.xxxxxx统一命名便于批量处理与数据增强YAML与TXT结构严格对齐降低预处理门槛显著提升农业视觉算法开发效率。 我在整理实验资料的时候翻出一个老压缩包文件名写着“番茄叶子实例分割数据集_20251117_005928.zip”。这个命名看起来就是自动打包时带的时间戳但里面其实藏着一整套从数据采集、标注到训练验证的完整流程。当时做这个数据集是为了解决温室番茄叶片的精细识别问题不是简单的框选定位而是要精确到每一片叶子的轮廓。今天就把这个项目从头到尾拆开讲一遍包括数据集结构、标注规范、格式转换、YOLOv8-seg训练参数以及我踩过的那些坑。如果你是做农业视觉、植物表型分析或者正在准备用实例分割训练自己的数据集这篇内容可以直接照着抄作业。我会把每一个环节的设计思路和参数选择逻辑都讲清楚免得你走弯路。1. 番茄叶子实例分割为什么值得做一套专用数据集1.1 从目标检测到实例分割农业视觉到底卡在哪先聊一个基础问题为什么做叶片识别要用实例分割而不是普通的目标检测框目标检测输出的是矩形框对于番茄叶子这种极度不规则的物体矩形框天生就有两个问题。一是背景占比太高一框下去可能一半是泥土、滴灌带或者其他叶片后续做病害分级、叶面积估算时会被严重干扰。二是叶片之间挨得太近尤其番茄复叶结构复杂相邻叶片互相遮挡检测框大量重叠后处理做非极大值抑制时很容易把相邻叶片的框错误合并或者漏掉。实例分割就不一样它输出的是每个叶片的像素级掩膜。你可以精确计算单叶面积、叶片周长、叶倾角这些形态参数可以判断叶片边缘的黄化、枯斑范围可以在遮挡严重时通过掩膜重叠面积分析遮挡比例。这些是目标检测完全做不到的。当时我需要的核心指标是单叶面积和病斑占比所以从一开始就锁定了实例分割路线。实例分割和语义分割也要区分清楚。语义分割只区分“哪些像素是叶子、哪些像素是背景”但把所有叶子当成同一类不同叶片之间没有区分。实例分割则要求把每一片叶子都当成独立个体同一张图里10片叶子就要输出10个独立掩膜。这在植物表型分析里尤其重要因为你要统计的是单株叶片数、单片叶面积而不是总面积。1.2 数据集名字里藏着哪些关键信息先解码这个文件名“番茄叶子实例分割数据集_20251117_005928.zip”“番茄叶子”确定了目标类别不是整株番茄也不是果实就是叶片个体“实例分割”确定了任务类型这意味着标注格式是像素级多边形掩膜而不是矩形框“20251117_005928”是打包时间戳说明当时已经做到数据版本化管理的阶段“.zip”是整个数据集的最终交付形态内部应该包含图像、标注、配置文件、划分脚本这里有个值得借鉴的细节数据集命名一定要带上时间戳和版本。实验过程中数据集会反复迭代今天加了几张图明天修正了一批错误标注如果没有版本管理训练完模型后你根本说不清楚这批权重是在哪版数据上训出来的。我在这个项目里的习惯是每轮修订后重新打包文件名带上日期时间旧包不删除但用目录区分。《番茄叶子实例分割数据集_v2》《番茄叶子实例分割数据集_v3》这种命名方式在后续回溯实验时帮了大忙。回到这个数据集本身。整个数据集的构建思路也贯穿了“先设计后采集”的原则目标类别只有一类“leaf”叶子。但为了后续扩展我在设计标注类别时就留好了扩展位比如“leaf_disease”病叶、“leaf_wilting”萎蔫叶只是第一版没启用。这个设计在后面扩展数据集时省了很多事。2. 数据采集与标注从温室到像素级标注2.1 采集方案设计不是随便拍几张就完事数据采集是整个数据集构建中最容易被低估的环节。很多人直接从网上爬一批图片就开始标注结果训练出来的模型在真实温室里完全不可用。场景单一、光照条件覆盖不足、叶片形态分布不均是三大主因。我在这个项目里采用了分场景采集的方案。目标温室包含三个独立种植区日光温室自然光照为主、连栋温室顶部遮阳网覆盖散射光多、人工光源温室LED补光红蓝光成分高。三个场景各采集了总数据量的一半左右保证模型在不同光照条件下都有足够的泛化样本。采集设备用的是普通工业相机加定焦镜头分辨率统一设为1920x1080。这里说明一下为什么不用手机拍。工业相机的色彩还原更稳定不会像手机一样自动开启HDR、美颜、场景优化这类影响图像一致性的功能。图像一致性对最终模型的影响非常大你想象一下训练集里一半图片色彩偏暖、一半色彩偏冷模型会浪费大量参数在适应色彩差异上而不是学习叶片形状。拍摄角度上俯拍和斜45度角各占约50%。纯俯拍对于叶面积计算最友好因为透视形变小但实际应用中手持设备拍摄多多少少会有倾斜角度所以需要混入斜视角度的样本。另外每个角度拍摄时都会把相机稍微上下左右平移一下制造一定的视角多样性相当于一个小小的数据增强。采集时间覆盖上午9点到下午5点这样阳光入射角度不同叶片阴影方向不同模型不会过拟合某一种光照方向。需要注意的是不要为了图省事只在正午采正午顶光条件下叶片反光最严重而且阴影最短标出来的掩膜边界会有系统性偏差。最终采集数量是1826张原始图像。筛选掉严重过曝、失焦、遮挡超过70%的图片后保留并标注了1560张。这个数量做单类别实例分割是够用的前提是类别单一、形态一致性尚可。如果你的目标类别有好几种比如除了叶子还要标果实、茎秆、病斑那数据量至少需要翻一倍。2.2 标注工具选型与标注规范标注工具我对比过LabelMe、CVAT、X-AnyLabeling和Roboflow最终选定了LabelMe。原因有三条LabelMe是纯本地运行数据不用上传第三方服务器。农业数据虽然没有特别敏感的隐私问题但野外采集的图片可能包含地块位置信息本地处理最稳妥。LabelMe的标注格式是JSON每个文件对应一个标注结果这种松散结构方便脚本批量处理。LabelMe标注多边形时可以直接在图上看到线条贴合程度对于叶片这种边缘不平整的目标比较友好。CVAT其实更适合团队协作多人同时标注有任务分配和审核流程。但当时参与标注的只有我和一个师弟协调成本不高用LabelMe足够了。如果你的项目有3个以上标注人员我建议直接用CVAT审核和一致性管理会轻松很多。标注规范是整个项目中最关键的环节没有之一。实例分割标注的难度在于同一片叶子不同人标出来的轮廓可能相差很大。我定了几条硬性规则第一叶柄怎么处理。番茄是复叶结构一个叶柄上排出多片小叶。我的方案是只标注小叶片的叶身部分叶柄和叶轴不标。这样标注语义统一为“叶身”后续做叶面积分析时数据口径一致。第二重叠叶片怎么标。两片叶子叠在一起时被遮挡的叶片只标可见部分不依据先验知识脑补被遮挡的轮廓。这一点非常重要脑补出来的轮廓边界处是不准确的会让模型在遮挡区域的预测产生系统偏差。第三边缘模糊的叶片怎么处理。叶片边缘如果因为景深或者运动模糊不确定精确边界位置就沿着可见边缘的外侧勾边。宁可略微外扩不要内缩因为外扩几个像素对面积计算的相对误差影响不大但内缩会造成明显的面积低估。第四标注完必须统一跑一遍“最小面积”过滤。小于50个像素的掩膜直接删除。这种极小目标对训练几乎没有贡献而且会给损失函数引入额外的噪声让模型在不重要的区域浪费拟合能力。标注过程平均每张图耗时3到5分钟复杂遮挡场景可能到8分钟。1560张图两个人分工大约用了两周时间完成第一版标注。如果你预计自己的数据量大可以算一下这个时间成本提前规划好人力。3. 数据集整理与格式转换从LabelMe到YOLO格式3.1 标准目录结构与文件说明标注完成后数据集还不能直接用需要整理成标准目录结构并转换格式。这是整个流程中最容易出错、但也是最值得标准化的环节。我采用的最终目录结构如下tomato_leaf_seg/ ├── images/ │ ├── train/ # 1092张 │ ├── val/ # 312张 │ └── test/ # 156张 ├── labels/ │ ├── train/ # 对应的.txt标注文件 │ ├── val/ │ └── test/ ├── data.yaml ├── labelme_json/ # 原始LabelMe标注备份 └── scripts/ ├── labelme2yolo_seg.py └── verify_dataset.py为什么要把原始LabelMe JSON保留一份因为YOLO格式的标签是归一化坐标的纯文本可读性差而且一旦后续要改类别名、合并类别、或者转换成其他格式如COCO没有原始标注就得重新标一遍。原始JSON就是数据资产的本体其他格式都是为了适配训练框架的派生品。train/val/test的划分比例是70%/20%/10%。有人习惯只用train和val测试集用val替代但我建议保留独立的test集。因为你在训练过程中会反复看val集结果来调参model selection过程本质上是“对着val集做优化”最后用test集评估才能反映模型见到全新数据时的真实表现。如果只有val集你评估出来的指标会偏乐观。划分前要先按图像来源场景做分层抽样。也就是说三个温室的图片在train/val/test中都要按比例出现不能让test集恰好全是人工光源温室的数据那样测试结果会剧烈波动。3.2 LabelMe JSON转YOLO分割格式的脚本实现LabelMe JSON的核心结构是一个多边形点列表每个标注对象包含label字段和points字段points是按顺序排列的多边形顶点。转换到YOLO分割格式时需要做三步将每个顶点坐标除以图像宽高归一化到0到1之间将类别名映射为数字ID写入txt文件每行格式为class_id x1 y1 x2 y2 ... xn yn这里有一个值得特别注意的坑LabelMe保存的points坐标可能带有小数但归一化之前务必确认坐标参考的图像尺寸。LabelMe的JSON里没有保存图像宽高需要在转换脚本里用OpenCV读取原始图像的尺寸而不是依赖你“记忆”里的尺寸。如果记错了尺寸所有坐标都会偏移而且这种偏移肉眼很难直接发现。核心转换脚本如下import json import cv2 import os def labelme2yolo_seg(json_path, img_dir, out_txt_path, class_map): with open(json_path, r, encodingutf-8) as f: data json.load(f) # 用原始图像尺寸做归一化基准 img_name data[imagePath] img_path os.path.join(img_dir, os.path.basename(img_name)) img cv2.imread(img_path) h, w img.shape[:2] lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue class_id class_map[label] points shape[points] # 归一化坐标 norm_points [] for pt in points: x pt[0] / w y pt[1] / h norm_points.extend([f{x:.6f}, f{y:.6f}]) lines.append(f{class_id} .join(norm_points)) with open(out_txt_path, w, encodingutf-8) as f: f.write(\n.join(lines))这个脚本看着简单但有几个细节容易出问题。一是归一化精度。建议保留6位小数训练时imgsz如果是6406位小数的精度约对应1个像素足够用但如果只有4位小数640分辨率下坐标误差最多可达640/100000.064像素虽然不大但累计多次增强后可能产生0.5像素以上的边界偏移对精分割任务不友好。二是多边形点顺序。YOLO格式要求多边形顶点按顺序连接如果LabelMe导出时顺序乱了掩膜会出现交叉扭曲。我加了校验计算多边形面积时用鞋带公式当面积方向为负时反转顶点顺序。三是空标注文件处理。如果一张图没有任何有效标注比如全部是背景生成的txt文件为空。训练时YOLO会把它当作背景样本这是允许的。但如果所有背景样本过多比如超过20%模型会偏向预测背景需要适当剔除或补充标注。我当时保留约8%的背景图实测对训练效果有正面帮助。3.3 数据验证与质量检查别让错误标注悄悄喂给模型格式转换完成后我强烈建议跑一遍自动化验证脚本而不是急着开训练。数据质量问题在训练早期几乎不会暴露等训完一轮才发现标注错了几小时GPU时间就白费了。验证脚本至少要做这三件事第一坐标越界检查。归一化坐标应该在0到1之间但因为标注时手滑或者转换脚本bug偶尔会出现大于1的坐标。这种情况必须报错因为YOLO训练时边界外的点会导致掩膜计算异常。第二掩膜面积检查。读取每个txt文件用鞋带公式计算原始像素面积过滤掉面积小于50像素的掩膜打印统计信息。面积异常大的掩膜也要检查可能是标注时把整株番茄都圈进去了。第三可视化抽查。写一个脚本把标注掩膜叠加回原图上保存为图片随机抽取50张人工检查。这一步不要省。我做过一次批量标注有个切片边界画反了自动检查查不出来人工抽查发现3张图的掩膜错位重新标注后训练精度涨了2个点。data.yaml的内容也需要特别小心path: /path/to/tomato_leaf_seg train: images/train val: images/val test: images/test nc: 1 names: 0: leafpath字段建议写绝对路径或者至少保证相对路径与你当前工作目录一致。YOLOv8对路径的处理比较灵活但相对路径一旦因为工作目录切换导致找不到图片训练会直接报错排查起来浪费时间。另外类别ID必须从0开始连续编号不能跳号否则模型矩阵维度不匹配。4. YOLOv8-seg训练番茄叶片数据集完整实操4.1 环境准备与数据放置训练框架我选了YOLOv8ultralytics原因很简单实例分割训练开箱即用配置文件干净社区活跃度高出问题容易搜到答案。而且对于单类别叶片分割这种任务YOLOv8-seg的精度和速度平衡已经足够好不需要上更重的两阶段模型如Mask R-CNN。安装方式pip install ultralytics如果服务器上有现成的CUDA环境这行命令就够了。训练前先用yolo predict跑一张测试图确认推理链路正常避免后续训练时才发现环境问题。数据放置我采用的方式是软链接而不是物理复制。训练脚本里data.yaml指向数据集目录数据集目录通过软链接链到实际存储位置这样不会因为路径不一致导致配置需要反复修改。ln -s /data/datasets/tomato_leaf_seg /workspace/tomato_leaf_seg4.2 训练参数详解imgsz、batch、增强项怎么设这是我花了最多时间调参的部分直接讲结论。imgsz我设置为640。番茄叶子在原始1920x1080图像中占的面积不小缩到640以后单叶仍然有足够的像素。如果你用更大的imgsz比如1280精度会提升但显存占用和训练时间都会成倍增长。对于第一版模型640是性价比最高的选择。batch的大小取决于显存。以RTX 309024GB为例yolov8s-seg模型batch可以开到16。batch太小比如4以下BatchNorm统计量不稳定训练震荡明显batch太大单卡显存放不下就只能用梯度累积反而拖慢迭代速度。epochs我设为300。这里有一个关键点YOLOv8默认的训练策略里有早停机制patience一般默认值是100。如果100个epoch内val集指标不再提升训练自动停止。我的实际训练在第230轮左右达到最佳val mAP50-95约0.74之后指标不再上升自动早停。数据增强参数方面YOLOv8默认的增强策略已经很强大但有几个参数需要根据你的数据特性调整mosaic: 1.0 # 马赛克增强默认开启 mixup: 0.0 # 建议关闭叶片重叠场景混合后语义混乱 copy_paste: 0.1 # 实例复制粘贴增强对分割有效 degrees: 10.0 # 旋转角度番茄叶片方向各异不需要太大旋转 translate: 0.1 scale: 0.5 fliplr: 0.5mixup我直接关了。mixup是把两张图按透明度混合成一张新图对于物体边缘模糊的实例分割任务混合后的掩膜边界会产生大量错误监督信号。copy_paste恰好相反它把一张图里的实例复制到另一张图这对单个实例的形状保持是有利的所以我只开了一点点0.1就够了。另外训练时如果想统计叶片形态参数建议关闭hsv_h、hsv_s和hsv_v的色彩增强。或者至少把强度调低。色彩增强会让模型对叶色变化更鲁棒但如果后续要基于颜色做病害分级色彩变化过强的增强可能掩盖真实叶色差异。训练命令如下yolo segment train \ modelyolov8s-seg.pt \ datadatasets/tomato_leaf_seg/data.yaml \ imgsz640 \ batch16 \ epochs300 \ patience100 \ optimizerAdamW \ lr00.002 \ lrf0.01 \ workers8预训练权重选择上我建议从yolov8s-seg.pt开始而不是yolov8n-seg.pt。n模型参数量少训练快但分割掩膜质量明显粗糙尤其是叶片边缘这种不规则的精细轮廓n模型的输出多边形化之后锯齿感严重。s模型的精度/速度平衡在农业场景下表现最好推理速度在GPU上依然能达到几十毫秒一帧。优化器我用AdamW在实例分割效果上普遍比SGD收敛更稳尤其数据集规模不大时AdamW不容易因为学习率设置不当而发散。如果你用SGD需要把lr0调高到0.01左右同时做好warmup但效果依然不如AdamW稳定。4.3 训练过程与结果解读loss曲线和mAP怎么看训练开始后你会看到ultralytics打印每个epoch的loss和mAP。对于初学者来说这里最容易焦虑的点是loss不往下降或者mAP波动很大。我自己训练时的情况是这样前50个epochbox_loss从1.2快速降到0.4左右seg_loss从1.5降到0.6mAP50还在一个比较低的水平大概0.2到0.4之间波动。这在分割任务比较正常因为seg_loss主要优化的是每个像素的类别置信度这个loss会先快速收敛但mAP评价的是实例级掩膜IoU比像素级loss要严格得多。第50到150个epochmAP50-95会开始稳步上涨从0.3涨到0.6左右速度明显变缓。这时候不要随意中断训练看到mAP还在涨就继续等。第150到230个epochmAP50-95涨到0.7以上每轮的提升幅度小于0.01基本就到平台期了。训练结束后ultralytics会保存best.pt和last.pt。测试时一定用best.pt它是val集上指标最好的权重。last.pt是最后一个epoch的权重由于早停机制last不一定比best差但一般best更可靠。在test集上我最终跑出来的指标是指标数值mAP500.893mAP50-950.748precision0.912recall0.876这个水平对单类别叶片分割来说已经不错了。比较能说明问题的是模型在温室A的数据上mAP高于温室C约5个百分点说明不同光照条件确实存在分布偏差。如果你的模型在某个子集上明显下降考虑在数据集里多补充该场景的样本。4.4 模型推理与部署从验证到实际可用模型训练完成后我用下面的命令对test集做预测同时输出带掩膜的可视化结果yolo segment predict \ modelruns/segment/train/weights/best.pt \ sourcedatasets/tomato_leaf_seg/images/test \ save_txtTrue \ save_confTrue \ saveTruesave_txtTrue会输出每个目标的类别、置信度和归一化掩膜坐标这个文件就是后续计算叶面积、病害占比的原始数据。如果要部署到生产环境还需要把模型从PyTorch权重导出为更高效的格式。我实测了ONNX和TensorRT两种导出方式yolo export modelbest.pt formatonnx imgsz640 yolo export modelbest.pt formatengine device0 imgsz640TensorRT导出的engine文件在GPU上推理速度大约是PyTorch的1.8倍对于实时监测场景很有价值。如果你在边缘设备上跑比如Jetson Nano可能还需要进一步量化。5. 常见问题与排查技巧实录5.1 标注数据常见问题与修复问题1掩膜坐标出现乱序导致训练loss异常现象训练时seg_loss掉不下去可视化发现掩膜呈“蝴蝶结”状交叉。原因LabelMe中同一对象的点顺序被打乱转成YOLO格式时多边形自相交。修复在转换脚本里增加鞋带公式面积符号校验面积符号为负则反转坐标顺序。这个是转换脚本最值得加的一行代码。问题2不同标注人员对叶片边界把握不一致现象同一个温室的两批数据混在一起训模型输出掩膜整体偏大或偏小边缘粗糙。修复没有完美的自动修复方式。建议在标注规范里加入“边缘外扩2像素”的约定并且标注完成后由一个人统一复查。我实际复查了20%的标注统一的力度已经足够。5.2 训练阶段的问题排查问题val集指标不错但真实场景表现差这个问题的本质是过拟合或者场景分布偏差。我当时的一个教训是最初只用了日光温室的数据训练val指标看起来挺好拿到人工光源温室一测掩膜边界明显变形。原因是人工光源的红蓝光谱占比高叶片在图像里颜色偏暗偏蓝模型没见过这种分布。解决方法有两个一是补充不同场景的数据二是训练时把色彩增强参数适当调大。我建议这两个都做数据多样性是根本色彩增强是补偿。问题训练时显存不足如果你的显存不够第一选择是降batch而不是降imgsz。因为imgsz降太多会直接降低模型对叶片边界的感知精度。如果batch降到4还不够再用梯度累积ultralytics里可以用accumulate4参数。另外关闭cacheTrue缓存图像到内存也可以减少显存占用但会拖慢数据读取。5.3 数据版本管理与后续扩展数据集的版本管理我用的是最朴素的文件目录加大文件命名没有引入DVC或者Git LFS。原因很简单数据集是定期打包的每次打包就是一个新版本不需要细粒度的版本追踪。但有一个注意事项每次打包前一定要写一个CHANGELOG记录这次改动内容比如新增图像数量、修正了哪几张图的标注、删除了哪些模糊样本。否则三个月后你根本不知道新旧版本的区别。后续扩展方向我目前在做的是把数据集从单类别扩展到多类别加入“病斑”和“黄化叶片”两个类别。这里有一个重要的实操建议在同一套坐标系上新增标注时原类别标注不要重新标只新增类别标注这样训练时新旧标注可以无损共存。另外如果要引入新类别类别ID不要重排直接在尾部追加避免历史标签全部失效。写在最后的心得这个番茄叶子实例分割数据集前前后后经历了三次完整迭代。第一次标注规范不统一掩膜质量参差第二次补充了光照场景多样性模型泛化能力明显提升第三次引入了严格的格式校验和可视化抽查训练时几乎没再因为数据问题返工。每次迭代都让模型mAP涨了几个点但这些提升最大的来源不是模型结构或者调参而是数据质量的改善。如果你也在做类似的数据集项目我的建议是在数据采集和标注阶段多花一倍时间后面训练和调参阶段就能省出三倍时间。实例分割模型性能的上限很大程度上在标注完成那一刻就已经决定了。模型结构和训练技巧只是在逼近这个上限而不是突破它。希望这份完整的项目拆解能帮你避开我踩过的坑做出一套真正可用的数据集。本文还有配套的精品资源点击获取