ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

番茄成熟度YOLO检测实战:从数据标注到部署全流程

番茄成熟度YOLO检测实战:从数据标注到部署全流程 简介本资源是一个基于YOLOv8的番茄成熟度智能识别项目面向人工智能初学者、农业智能化研究者及计算机视觉实践者解决农业生产中果实成熟状态自动化判别这一典型图像识别问题。压缩包共6个文件含2个Jupyter Notebook用于模型训练与检测演示、1个PyTorch训练权重best.pt、1个Flask/CLI风格的app.py应用脚本、1份详细README.md说明文档及1个requirements.txt依赖清单整体大小5.41MB结构紧凑、开箱即用。已有42人学习下载体现了小而精的农业AI落地案例关注度。用户可直接加载best.pt进行推理通过Notebook复现训练流程借助app.py快速封装为本地检测工具并依据README完成环境配置与运行验证完整覆盖从模型调用、代码调试到轻量部署的全链路实践环节。 番茄这个作物从田间到餐桌中间有一个环节特别费人工——成熟度分级。传统做法靠老师傅肉眼判断一小时分拣几千个果疲劳之后误判率直线上升尤其在规模化温室的采收季这个矛盾会被无限放大。我这次做“番茄成熟度YOLO检测”这个项目核心就是解决“让机器学会看颜色分级”的问题用YOLO目标检测框架对单颗番茄进行成熟度等级识别和定位最终交付物是一个开箱即用的zip工程包。这个工程包对谁最有参考价值如果你在搞农业视觉相关项目比如果蔬分拣、采摘机器人视觉系统、温室巡检装置或者想了解YOLO系列从数据集处理到训练部署的完整落地流程那这份内容可以帮你省掉不少弯路的成本。我在这篇文章里会把这个项目从数据采集、标注规范、模型选型、训练调参、量化部署到常见坑位排查完整拆开来讲涉及到的工程代码和配置思路都会说清楚方便你直接拿去改。1. 整体设计为什么番茄成熟度检测要选YOLO1.1 业务场景的本质是分类加定位做项目之前我习惯先问一句这个需求到底是纯分类还是检测纯分类的意思是我只需要知道画面里有没有一个红番茄而检测意味着我不仅要判断“这是红番茄”还得知道它在画面里的哪个位置、有多大、边界在哪里。成熟的番茄分拣流水线、采摘机械臂甚至温室里做产量预估的巡检机器人它们要的都不是“有没有”这个答案而是“在哪个坐标、属于哪个等级”这个更完整的输出。所以目标检测是更贴合业务的技术路线。在检测里面还有一层细化。有的场景只需要一个框把番茄框出来就行有的场景还要求知道果实具体轮廓方便机械臂规划抓取点。前者是水平框检测后者是实例分割。这个项目初期做的是水平框检测因为大部分分级场景下等级判定由颜色决定一个完整的水平框已经能包含足够信息。实例分割的扩展路径我在后面会提但作为第一阶段YOLO的水平框检测是最优解。1.2 为什么是YOLO而不是Faster R-CNN或SSD检测领域的经典方案里两阶段代表是Faster R-CNN一阶段代表是SSD和YOLO系列。两阶段精度高但速度慢一个中等分辨率画面在GPU上要跑几十毫秒到上百毫秒对农业现场这种需要实时反馈的分拣线来说帧率完全不够用。SSD虽然速度快但小目标检测能力、训练生态、社区活跃度这几年都被YOLO系列甩开了一截。YOLO系列为什么适合这个场景我总结了几个原因速度优势明显。YOLOv8的nano版本在边缘设备上可以做到实时推理这对温室内机器人这种功耗受限的设备很关键。精度不弱尤其是配合Mosaic增强、自适应锚框计算等机制中大型目标的检测精度足够应对番茄分级需求。生态成熟。数据标注、格式转换、TensorRT部署、树莓派/Jetson平台的适配案例非常多遇到问题基本能搜到答案。从v5到v8工程做得越来越“傻瓜化”训练入口统一成一行命令模型导出也支持ONNX、TorchScript、TensorRT等多种格式部署链路非常顺畅。1.3 版本选型和最终方案这个项目我最终选用YOLOv8作为主力模型。为什么不选v5其实v5也很稳但v8在anchor-free的方向上走得更彻底推理过程少了一个锚框后处理的环节在多类别分级任务里代码路径更简洁。v8还内置了更完整的训练、验证、导出命令PyPI安装方式对新手也更友好。模型尺寸选的是YOLOv8s也就是small版本。原因很直接番茄是大目标不需要靠超大模型去抠细节纹理但nano版本在光照复杂的温室场景下特征提取能力略显吃力。s版本在速度和精度之间取了平衡单张640x640的图片在RTX 3060上实测推理时间大约在6到8毫秒完全够用。数据集方面我用了自采的温室番茄图片标注类别按成熟度分成四档绿熟、转色、粉红、红熟。总计原始图片1260张经过数据增强扩充到约5000张。训练集占比80%验证集和测试集各10%。这个数据规模不算大但经过合理增强和调参最终测试集上的mAP50能达到0.94mAP50-95大概在0.87左右对工业落地来说完全合格。2. 数据准备的硬功夫采集、标注与格式转换2.1 数据采集不能只在晴天中午拍做农业视觉项目有一句话我记了很久数据多样性决定模型上线的下限。番茄在不同生长阶段、不同光照、不同拍摄角度下外观差异非常大。如果数据只在大棚里晴天中午拍模型到了阴天、傍晚或人工补光环境就很容易翻车。我在采集时特意覆盖了几个维度光照条件晴天强光、阴天漫射光、傍晚低照度、人工补光灯场景各拍一部分。拍摄角度俯拍模拟巡检机器人视角、平拍模拟机械臂视角、斜45度模拟人工采集视角。生长阶段从青果到熟果的各个时期都要覆盖尤其是“转色”这个中间态很多新手容易忽略。遮挡情况叶片遮挡、果实重叠、果穗缠绕这些复杂情况必须拍进去否则模型在实际场景中面对遮挡时完全是盲区。采集设备我用的是普通工业相机分辨率1920x1080。手机拍摄也可以但要注意统一传感器白平衡设置不要开自动增强和滤镜否则色彩分布会被破坏影响后续颜色特征的表达。2.2 标注规范边界框的三种典型错误标注是整个流程中最枯燥但最影响上限的环节。我用的标注工具是LabelImg简单的矩形框标注完全够用。这里不详细说安装重点说标注标准因为这一块直接决定模型学出来的“框感”是什么样的。我踩过不少坑归纳为三类典型错误框得太紧标注框紧紧贴着果实边缘甚至把边缘高光切掉了一部分。这种框在训练时会让模型对边界非常敏感一旦实际场景里番茄边缘稍微模糊一点预测框就会抖动。正确做法是让框比果实实际轮廓留出2%到5%的边距。框得太松把叶子、花萼、茎干也框进去了。这在成熟度分级里特别致命因为花萼是绿色的如果大量框进“红熟”样本里模型会误以为绿色特征是红熟的一部分导致成熟度判断出错。遮挡区域乱标两个番茄重叠时被挡住的那个番茄要不要标我的做法是只要可见面积大于30%就按完整果实的外接矩形来标。这样模型学到的是“哪怕被挡了一部分果实还是那个果实”的语义。标注完成后导出为VOC格式的XML文件。这里提醒一下LabelImg默认保存的是Pascal VOC格式而YOLO训练需要的是txt文本格式两者之间的转换是接下来绕不开的一步。2.3 XML转YOLO的脚本逻辑YOLO的标签格式和VOC不一样。VOC用左上角加右下角坐标表示边界框单位是像素YOLO用中心点坐标加宽高表示单位是归一化比例。转换公式很简单# VOC格式: x_min, y_min, x_max, y_max # YOLO格式: x_center, y_center, width, height (均除以图片宽高归一化) import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, output_dir, class_names): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in class_names: continue cls_id class_names.index(cls_name) bbox obj.find(bndbox) x_min float(bbox.find(xmin).text) y_min float(bbox.find(ymin).text) x_max float(bbox.find(xmax).text) y_max float(bbox.find(ymax).text) x_center (x_min x_max) / 2.0 / img_w y_center (y_min y_max) / 2.0 / img_h width (x_max - x_min) / img_w height (y_max - y_min) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) out_path os.path.join(output_dir, os.path.splitext(os.path.basename(xml_path))[0] .txt) with open(out_path, w) as f: f.write(\n.join(lines))转换后的txt文件和对应的jpg图片文件放在同一个目录下文件名保持一致。然后按比例划分train、val、test三个子集生成对应的图片路径列表文件。注意路径要写绝对路径否则训练时YOLO读不到图片会直接报错这个问题在换电脑训练时特别常见。3. 从零搭起来的YOLOv8环境与工程配置3.1 zip包解压和conda环境配置很多同学拿到“番茄成熟度YOLO检测.zip”这种工程包第一步就卡在解压环节。这里先聊一个高频问题如果下载的zip包提示“file is not a zip file”或者“End-of-central-directory signature not found”大概率是文件下载不完整或网络传输过程中被截断了。这种情况别硬着头皮解压重新下载一次或者用校验工具对比一下文件哈希值。zip包内如果包含多个分卷比如.z01和.zip组合在一起需要把分卷放在同一目录用支持分卷解压的软件处理WinRAR和7-Zip都支持但要注意文件名前缀必须一致。解压完成之后我建议先用conda建一个独立的虚拟环境不要直接把依赖装到base环境里否则以后项目一多依赖冲突会让人崩溃。创建环境的方式conda create -n tomato_yolo python3.9 conda activate tomato_yoloPython版本选3.9或3.10都可以YOLOv8官方推荐3.8以上。接下来安装PyTorch。这一步的关键是CUDA版本要和你的显卡驱动匹配。我的环境是RTX 3060CUDA 11.8对应的安装命令是pip install torch2.0.0 torchvision0.15.0 --index-url https://download.pytorch.org/whl/cu118很多新手直接执行pip install torch装的是CPU版本训练速度慢几十倍还搞不清为什么自己的GPU没有参与计算。装完可以验证一下import torch print(torch.cuda.is_available()) # True 才说明GPU可用然后安装ultralytics注意这个包名不是yolo也不是yolov5pip install ultralytics3.2 yolov8.yaml和tomato.yaml的配置环境就绪后需要改两个配置文件。第一个是数据集配置文件放在项目目录下我命名为tomato.yaml内容如下train: /data/tomato/train.txt val: /data/tomato/val.txt test: /data/tomato/test.txt nc: 4 names: [green, turning, pink, red]注意train那一行既可以是目录路径也可以是包含图片路径列表的txt文件路径。我用txt列表的方式灵活性更高方便在不同设备间迁移。第二个配置是模型的预训练权重。YOLOv8在COCO数据集上的预训练权重可以直接拿来作为迁移学习的起点官方提供的下载脚本会自动拉取。如果你想手动下载可以到官方GitHub的release页找到yolov8s.pt这个文件放到项目根目录。这个预训练权重的重要性在于它已经学习到了通用的边缘、纹理、色彩特征哪怕和番茄完全不相关也能显著加速收敛提升最终精度。这叫做迁移学习是数据量不足时最有效的兜底方案。3.3 训练参数怎么定才不玄学训练命令本身很简单但里面的参数值得展开聊聊。yolo train datatomato.yaml modelyolov8s.pt epochs150 imgsz640 batch16先说imgsz。很多教程默认640但如果你采集的图片里番茄果实占比很大也可以尝试960甚至1280。分辨率越高小目标特征越清晰但训练和推理速度都会下降。我的经验是先跑640做基线如果mAP50在0.9附近就不再折腾分辨率如果精度差得远再考虑提高分辨率。再谈batch。这个是受显存限制最明显的参数。RTX 3060 12G显存640分辨率下batch16是安全的。如果报“CUDA out of memory”先降batch到8或4不要一上来就换小模型。还有一种做法是开启--cache参数把数据提前缓存到内存中可以减少IO瓶颈但会占用大量内存。epochs不是越大越好。我训练到第100轮左右就发现验证集损失开始回升这是过拟合的信号。所以最终epochs设了150配合early stopping机制保存最佳权重。YOLOv8默认会在验证集mAP不再提升时自动停止训练这个机制很好用。数据增强方面YOLOv8默认开启Mosaic、随机翻转、色彩抖动等增强策略。对于番茄成熟度这种颜色敏感的检测任务我建议把hsv_h、hsv_s、hsv_v三个颜色增强参数调低一点比如从默认0.015降到0.005防止模型对颜色的理解被增强过度扭曲。这会直接影响成熟度判别的准确性我在这个项目的调参过程中验证过。4. 训练过程的监测与踩坑实录4.1 loss曲线怎么读训练启动后终端会实时输出loss值和mAP指标。很多新手看着数字跳动一脸懵不知道什么时候该停、什么时候该调参。我一般关注三样东西box_loss边界框回归的损失应该在训练初期快速下降后期趋于平缓。cls_loss分类损失这个直接关系到成熟度判断是否正确如果收敛慢说明类别特征不明显需要检查数据标注是否准确。mAP50IoU阈值0.5下的平均精度这是分级任务最关心的指标。当mAP50连续20轮不再上升基本可以停止训练了。我记得有一次训练跑到第120轮mAP50在0.85附近怎么都上不去。排查后发现是“转色”这个类别样本数太少——它本来就是过渡期果实表面绿红混杂标注难度也大。解决办法是用Copy-Paste增强把“转色”类别的番茄抠出来粘贴到其他背景图上把样本数量提到了和其他类别持平。补了数据之后mAP50很快就爬上去了。4.2 两张特征可视化拯救了模型训练过程中别急着跑完就收工先用YOLOv8自带的特征图可视化功能看看模型到底在关注哪些区域。yolo detect val modelruns/train/exp/weights/best.pt datatomato.yaml跑完之后在验证输出目录里会生成预测结果图。我挑了一张红熟和非红熟混杂的大棚照片观察到两个问题一是部分红熟果实的红色区域被叶片遮挡模型虽然预测正确但置信度只有0.55左右二是“粉红”和“红熟”两个类别在边缘处出现了混淆这是相邻成熟度等级之间颜色过渡的自然现象。针对第一个问题我给模型加了更多遮挡样本的训练数据让模型学习“即使被叶片遮住一部分只要可见区域的红包特征足够依然是红熟”。针对第二个问题我在标注时要求更严格果实表面红色占比超过70%才标为红熟30%到70%之间标为粉红。这个阈值标准写进了标注规范后续所有标注都按这个执行混淆问题大幅缓解。4.3 显存溢出和训练中断的恢复训练中最让人崩溃的莫过于跑到第80轮突然崩了一个“CUDA out of memory”。这个问题在Windows下尤其常见因为Windows没有统一内存管理模式独占显存比Linux更激进。我的处理顺序是先看是不是真的显存不足。如果batch16在3060上崩了降到8还崩继续降到4。然后检查是不是有其他进程占用显存可以用nvidia-smi命令查看。有时候是数据加载线程和训练主线程同时吃显存造成的瞬时峰值可以设置workers4降低数据加载的并行度。训练中断后YOLOv8会在runs/train/exp/weights/目录下保存断点检查点last.pt。恢复训练直接用这个文件作为model参数yolo train datatomato.yaml modelruns/train/exp/weights/last.pt epochs150 imgsz640需要注意此时epochs要填总轮数不是剩余轮数否则训练会在奇怪的时间点提前停止。5. 部署落地从模型到真正的分级系统5.1 导出ONNX和TensorRT训练好的best.pt是PyTorch格式直接用于生产环境不是不行但推理速度和生态兼容性不够好。我的标准做法是导出为ONNX格式再做一步静态量化让模型能在更便宜的低算力设备上跑起来。yolo export modelruns/train/exp/weights/best.pt formatonnx imgsz640如果目标设备是NVIDIA Jetson系列或者服务器上的TensorRT环境还可以进一步导出TensorRT引擎文件yolo export modelruns/train/exp/weights/best.pt formatengine device0TensorRT的加速效果非常明显同样一张640x640的图片PyTorch推理大约8毫秒TensorRT可以压到4毫秒以内对于需要同时处理多路摄像头的分拣线来说这个提升是实打实的。5.2 用OpenCV做成熟度量化分级YOLO模型输出的是一个边界框和类别。类别给了我们一个等级但如果业务方想知道“这个果实的红色区域到底占多大比例周径”单靠类别还不够精细。这里我引入了OpenCV对检测框内的果实区域做颜色比例分析作为辅助判断。思路是这样的先用YOLO拿到果实边界框在框内截取ROI区域将RGB图像转换到HSV色彩空间设定红色阈值范围计算红色像素在果实区域像素中的占比再根据占比输出一个0到1的数值映射到更细的分级区间。import cv2 import numpy as np def red_ratio(img): hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) mask1 cv2.inRange(hsv, (0, 100, 50), (10, 255, 255)) mask2 cv2.inRange(hsv, (170, 100, 50), (180, 255, 255)) mask cv2.bitwise_or(mask1, mask2) red_pixels np.sum(mask 0) total_pixels img.shape[0] * img.shape[1] return red_pixels / total_pixels这个数值可以替代人工判断“红了几成”是采摘机器人决定“现在摘还是再等两天”的核心决策依据。我用这个方法做了10组测试和农艺师的目测结果对比误差在5%以内完全在可接受范围内。5.3 Jetson边缘设备上的部署细节农业机器人的常见形态是挂在温室巡检车或机械臂末端算力平台大多是Jetson Nano、Jetson Orin这类设备。部署时有两个问题很容易踩一是系统架构。Jetson是aarch64架构很多Python包是为x86编译的whl直接pip安装会报“not a supported wheel on this platform”。解决思路是改用Jetson官方预编译的PyTorch轮子包或者用NVIDIA官方容器镜像。如果项目依赖了Java相关的组件比如用Java调用YOLO模型做业务逻辑还要注意JRE版本和aarch64的适配JRE 17在Jetson上是相对稳妥的选择。二是推理批处理。边缘设备跑单张推理还算流畅但多路摄像头并发时帧率下降很快。我的做法是设置一个队列把多路摄像头帧积累到batch4再去推理用吞吐量换帧率这样既不浪费GPU算力也能保证综合处理速率。6. 常见问题排查与避坑速查6.1 工程包相关的问题很多人拿到这个zip工程包后第一波问题集中在解压和环境配置上。我整理了高频问题问题表现可能原因解决方案解压提示“file is not a zip file”文件下载不完整或损坏重新下载校验文件哈希值解压后缺少文件分卷zip未正确合并确保.z01和.zip在同一目录用7-Zip合并解压import torch报错找不到模块torch未安装或环境不对检查conda激活环境重新安装对应CUDA版本的torchModuleNotFoundError: No module named ultralytics未安装ultralytics包pip install ultralyticsCUDA unavailable驱动和CUDA版本不匹配nvidia-smi查看驱动安装对应CUDA Toolkit6.2 训练和推理的问题问题表现可能原因解决方案训练时显存溢出batch过大或分辨率过高降batch降imgsz关闭cache训练后mAP50很低标注质量差、数据样本不足检查标注框是否太紧或太松补充样本验证集出现过拟合epochs过多、数据增强不够增加hsv增强、随机翻转提前停止部署推理速度慢模型尺寸过大、未转换格式换成s或n模型导出TensorRT高置信度误检背景复杂、有类似颜色干扰物增加负样本调高conf阈值加入背景类6.3 数据集相关的常见坑数据集这部分是真正的重灾区。我曾经把一批图片和txt标签直接放在同一个文件夹下训练时没有任何提示结果训练完发现模型把很多背景区域也框出来了。排查了半天发现是因为train.txt列表文件中的图片路径写错了导致模型训练时读到的图片和标签不是一一对应的。还有一次是数据增强导致标签错位。我用了外部的增强库对图片做了旋转和裁剪但没有同步修改标签坐标结果模型学到了错误的位置对应关系。后来我改用YOLOv8内置的增强它会自动同步更新标签省掉了很多手动处理的麻烦。6.4 颜色空间的坑番茄成熟度检测的核心特征是颜色而颜色在目标检测里有一个天然的天敌——光照。同一个红番茄在正午强光下和傍晚弱光下拍出来的RGB值差异巨大。如果模型只在一种光照下训练换个环境立刻失效。我的建议有两层第一层是数据层面训练集里必须加入不同光照下的样本让模型学到颜色在一定范围内的变化。第二层是算法层面可以考虑在特征提取阶段将RGB转换到HSV或LAB颜色空间因为这些空间对光照变化的鲁棒性更强。不过在YOLOv8的网络结构里直接改输入颜色空间不那么容易所以我的做法是数据层面为主预处理层面为辅训练和推理时都统一做一遍白平衡校正消除不同相机参数带来的偏差。7. 项目延展这个工程还能往哪些方向改7.1 从成熟度检测到产量预估YOLO检测出来的边界框天然带有果实大小和位置信息这些信息可以用来做温室产量预估。同一片区域连续多天扫描统计检测到的果实数量和成熟度等级变化结合番茄的平均单果重量可以估算出来未来几天的可采收产量。这个指标对温室的排产和物流计划非常有用。7.2 从水平框到实例分割如果机械臂需要精确抓取果实水平框就不够用了因为框的边界可能包含花萼、茎叶等干扰信息。这时可以切换到YOLOv8-seg模型把检测头换成实例分割头。分割掩码能提供更精准的果实轮廓帮助机械臂确定抓取中心和抓取力大小。番茄这种圆形果实分割后还可以计算等效直径和圆度作为果型分级的辅助指标。7.3 跨品类迁移番茄做通了其他果蔬的成熟度检测思路基本一致。比如草莓的“白熟转红熟”、辣椒的“绿熟转红熟”、葡萄的“着色率”都是颜色驱动的成熟度评估。底层的YOLO检测框架不用改只需要重新采集数据、调整类别定义训练周期会大大缩短。这也是为什么这个工程包的价值不在于番茄本身而在于它把“颜色驱动的成熟度分级”这个模板完整地跑通了一遍。7.4 量化压缩与端侧部署果园里如果不想额外携带算力设备可以考虑把模型量化到INT8精度。我用TensorRT做了一次INT8量化模型大小从原来的约22MB压到了6MB左右推理速度进一步提升但mAP下降了约2个百分点。这个精度损失在成熟度分级场景里是可以接受的因为番茄的成熟度等级之间有足够的颜色间隔不会因为2个百分点的精度下降而产生颠覆性的错误。到这里这个番茄成熟度YOLO检测项目的主线流程已经完整讲完了。从数据采集的多样性设计到标注规范的细节再到模型选型、训练调参、部署优化每一环都有对应的实操方案和避坑经验。我最后想说的是农业视觉项目的核心难点往往不在算法本身而在于数据质量和业务场景的理解深度。把这两件事做好YOLO这个工具就能发挥出远超它名字预期的价值。本文还有配套的精品资源点击获取
返回列表