
1. 项目缘起从“看”到“摘”的智能农业跨越最近几年我一直在关注计算机视觉在农业领域的落地应用。从早期的病虫害识别到后来的作物长势监测技术迭代的速度远超想象。但有一个环节始终是“硬骨头”——那就是自动采摘。这不仅仅是识别出“有没有果实”更是要精准判断“能不能摘”、“怎么摘”。一个典型的场景就是番茄采摘果实的成熟度直接决定了其商品价值和采摘时机。过早采摘风味和糖分不足过晚采摘则可能在运输中破损或腐烂造成巨大损失。传统的人工判断和采摘不仅效率低下、成本高昂而且高度依赖经验难以标准化。随着劳动力成本的持续上升和农业精细化管理的需求基于视觉的自动化采摘系统成为了必然趋势。这个项目的核心就是利用当前工业界和学术界都非常成熟的YOLOv5目标检测框架构建一个专门用于番茄采摘场景的成熟度检测、识别与计数分析系统。我们不只是要“看见”番茄更要“看懂”它的状态为后续的机械臂抓取、路径规划提供最关键的决策依据——成熟度信息。为什么选择YOLOv5在实时性要求极高的田间或温室作业环境中检测模型必须在精度和速度之间取得最佳平衡。YOLOv5以其出色的推理速度、友好的工程化部署特性以及从轻量级到高精度全覆盖的模型系列n/s/m/l/x成为了我们这个项目的技术基座。通过它我们可以针对不同的硬件算力如嵌入式设备Jetson系列、工控机、服务器和不同的精度要求灵活选择模型实现从实验室到田间地头的平滑过渡。2. 番茄成熟度检测一个典型的多阶段分类问题很多人一听到“成熟度检测”可能会想到直接用分类模型比如ResNet、EfficientNet对裁剪出的番茄图片进行分类。但在动态、复杂的采摘场景下这种方法存在先天不足。首先你需要先定位到番茄这本身就需要一个检测模型其次直接对整图分类背景干扰极大最后一个番茄可能被枝叶部分遮挡分类模型难以处理。因此更合理的架构是“检测分类”的两阶段模式而YOLOv5本身就能很好地承载这个任务。我们不是要做两个独立的模型而是将成熟度作为目标检测任务中的一个属性进行联合训练和预测。具体来说我们把不同成熟度的番茄视为不同的类别。例如可以定义为类别0未成熟绿色类别1转色期绿中带红类别2成熟红色类别3过熟深红/开始软化这样一来YOLOv5模型在输出边界框Bounding Box和置信度的同时还会直接输出该番茄所属的成熟度类别。这种端到端的方式效率远高于两阶段模型更适合实时系统。2.1 数据标注的精细化管理这个项目的成败一半以上取决于数据质量。番茄成熟度的标注比普通的目标检测标注要求更高。首先标注工具的选择。推荐使用Roboflow、CVAT或LabelImg。对于团队协作和版本管理Roboflow的在线平台非常方便。它支持自动预处理、数据增强和格式一键导出为YOLO格式。其次标注规范的制定。这是最容易产生歧义的地方必须统一标准。边界框紧密度框体应紧紧包裹住番茄果实尽量减少背景区域但必须包含整个可见部分即使被轻微遮挡。遮挡处理对于被枝叶遮挡超过50%的番茄通常不建议标注因为在实际采摘中可能也无法操作。低于50%的遮挡需要根据可见部分判断其最可能的成熟度并标注。重叠果实当两个番茄重叠时应尽量为每个可见的独立实体绘制单独的框。如果完全重叠无法区分则标注最前面的一个。成熟度判定准则未成熟果实通体为绿色无任何红色或黄色显现。转色期果实表面出现明显的红色或黄色斑块面积10%但底色仍以绿色为主。这是最需要统一判定的阶段建议团队内部用色卡或标准图进行校准。成熟果实表面绝大部分80%变为红色或品种特有的成熟色色泽均匀鲜亮。过熟果实颜色变为深红或暗红表面可能出现皱缩、光泽暗淡或伴有轻微裂痕。注意成熟度阶段划分可以根据实际业务需求调整例如加工用番茄和鲜食番茄的标准就不同。标注前务必与农艺专家或下游采摘设备团队确认。最后数据分布的平衡。在自然场景中成熟番茄的比例可能远高于未成熟或过熟的。直接训练会导致模型对少数类别不敏感。必须在数据集层面进行重采样Oversampling或使用类别权重Class Weight来平衡。3. YOLOv5全系列模型选型与针对性调优YOLOv5提供了n/s/m/l/x五个预定义模型它们的深度和宽度依次增加。选择哪一个不是简单地选精度最高的而是要综合考虑部署环境、实时性要求和精度容忍度。3.1 模型特性对比与选型决策我们可以用一个简单的表格来对比其核心差异这决定了我们的选型方向模型变体参数量 (M)计算量 (GFLOPs)特点与适用场景YOLOv5n~1.9~4.5极致轻量。适合算力极其有限的嵌入式设备如树莓派4B可达到很高的FPS但精度牺牲较大适合对漏检有一定容忍度的实时监控场景。YOLOv5s~7.2~16.5轻量高效。在精度和速度间取得了很好的平衡是移动端和边缘设备如Jetson Nano/TX2的首选起点模型。我们的项目若需部署到移动采摘机器人上应优先从s模型开始实验。YOLOv5m~21.2~49.0平衡之选。精度显著提升速度尚可。适合拥有中等算力工控机如Intel NUC带GPU的固定式采摘站或分选线。YOLOv5l~46.5~109.1高精度。适用于服务器或高性能工控机当s/m模型精度无法满足要求如转色期识别率低时升级使用。速度较慢但为后续算法优化提供了更好的基础。YOLOv5x~86.7~205.7极致精度。参数量最大通常用于学术研究刷榜或对精度有极端要求的场景。工业部署成本高需谨慎评估其投入产出比。选型建议对于番茄采摘这个具体场景我建议的实践路径是从YOLOv5s开始。用s模型在验证集上跑出基准性能。如果转色期最关键的经济采摘期识别精度mAP0.5能达到85%以上且推理速度满足实时要求例如30 FPS那么s模型就是最佳选择。如果精度不足则升级到m模型。切忌一开始就使用l或x模型它们带来的精度提升可能无法抵消部署成本和速度下降的劣势。3.2 针对农业场景的模型调优策略直接使用预训练模型在COCO等通用数据集上训练是远远不够的。农业图像有其独特性光照变化剧烈早晨、正午、傍晚、补光灯、背景复杂泥土、绿叶、支架、目标尺度多变近处番茄大远处番茄小。因此必须进行针对性的调优。自适应锚框计算AutoAnchorYOLOv5在训练前会自动在您的数据集上重新计算锚框Anchor的尺寸。这是必须开启的步骤。番茄的宽高比与通用数据集中的人、车差异很大重新计算锚框能让模型更快、更好地收敛。在训练命令中它会自动执行。数据增强Data Augmentation的针对性强化光照与色彩必须加强HSV-Hue色调、HSV-Saturation饱和度、HSV-Value明度的增强幅度以模拟不同时段和天气下的颜色变化。在data/hyps/hyp.scratch-low.yaml中可以适当调高hsv_h,hsv_s,hsv_v的系数。遮挡与模糊使用mosaic四图拼接和mixup增强能极大地提升模型对部分遮挡和复杂背景的鲁棒性。copy-paste增强将随机的目标粘贴到图像中对于增加小目标或稀有类别如过熟番茄的样本非常有效。尺度变化由于番茄在图像中近大远小scale缩放和perspective透视变换增强很重要。损失函数微调关注cls_loss分类损失。如果发现模型在成熟度分类上特别是转色期vs成熟期混淆严重可以尝试在hyp配置文件中增加分类损失的权重cls_pw如从1.0增加到1.5或2.0迫使模型更关注分类精度。4. 从模型训练到系统集成的全链路实践有了数据和模型策略接下来就是具体的实施。这里我分享一套从训练到部署上线的完整流程和其中的关键细节。4.1 训练环境搭建与数据准备训练通常在拥有GPU的服务器或云端进行。环境配置是第一步也是最容易踩坑的地方。# 1. 克隆YOLOv5官方仓库建议使用固定版本如v6.2避免兼容性问题 git clone -b v6.2 https://github.com/ultralytics/yolov5.git cd yolov5 # 2. 创建并激活Python虚拟环境强烈推荐避免包冲突 python -m venv venv source venv/bin/activate # Linux/Mac # venv\Scripts\activate # Windows # 3. 安装依赖使用官方requirements.txt注意PyTorch版本需与CUDA版本匹配 pip install -r requirements.txt # 如果网络问题可以指定国内源并单独安装PyTorch # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118数据准备需要按照YOLO格式组织datasets/tomato/ ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── ... │ └── val/ │ ├── 101.jpg │ └── ... └── labels/ ├── train/ │ ├── 001.txt │ └── ... └── val/ ├── 101.txt └── ...每个.txt标签文件对应一张图片每行格式为class_id x_center y_center width height坐标是归一化后的值0-1之间。4.2 训练过程监控与关键指标解读启动训练的命令相对简单但理解输出日志至关重要。python train.py --img 640 --batch 16 --epochs 100 --data data/tomato.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name tomato_maturity_s--img 640: 输入图像尺寸。更大的尺寸如1280可能提升小目标检测精度但会显著增加显存消耗和降低速度。640是速度和精度的一个平衡点。--batch 16: 批次大小。根据GPU显存调整。如果出现CUDA out of memory错误首先降低batch其次降低--img。--data: 指向你的数据配置文件tomato.yaml其中定义了路径、类别数和类别名。--weights yolov5s.pt: 加载预训练权重。这是提升收敛速度和最终精度的关键务必使用。训练开始后我们需要在TensorBoard或本地生成的runs/train/tomato_maturity_s目录下的日志中关注几个核心指标损失曲线Losstrain/box_loss,train/obj_loss,train/cls_loss应平稳下降val对应的损失在后期应趋于平稳或轻微波动。如果验证损失在后期大幅上升可能是过拟合需要增加数据增强或使用早停Early Stopping。性能指标MetricsmAP0.5在所有类别上IoU阈值为0.5时的平均精度均值。这是我们评估模型整体检测精度的核心指标目标通常是0.85。mAP0.5:0.95在IoU阈值从0.5到0.95步长0.05上的平均mAP更严格关注定位精度。precision和recall精确率和召回率。高精度低召回说明模型保守只检测很确定的可能漏检多低精度高召回说明模型激进误检多。我们需要在两者间平衡。最重要的是看每个类别的AP在results.csv或验证后的日志中会输出每个类别的AP值。你必须确保转色期这个关键类别的AP值足够高例如0.8否则采摘系统将无法有效识别最佳采摘窗口。4.3 模型验证、测试与错误分析训练完成后不要急于部署先用独立的测试集从未参与训练和验证的数据进行全面评估。python val.py --weights runs/train/tomato_maturity_s/weights/best.pt --data data/tomato.yaml --task test验证会生成详细的评估报告和可视化结果。最关键的一步是错误分析。打开runs/val/exp目录下的_prediction.jpg图片观察模型在哪里出错了漏检False Negative成熟的番茄没检测出来。可能是目标太小、遮挡严重、或与背景颜色太接近。对策增加小目标数据加强mosaic和copy-paste增强。误检False Positive把红色的落叶、反光的地膜误认为成熟番茄。对策增加包含此类负样本没有目标的图片的训练数据或在后处理中提高置信度阈值--conf-thres。分类错误把转色期番茄分类为成熟或未成熟。这是最影响业务的问题。对策检查转色期样本的标注是否一致、数量是否足够尝试调整分类损失权重或者考虑将转色期和成熟期合并为一个“可采摘”类别简化问题。5. 计数分析系统构建与采摘决策逻辑检测出每一个番茄及其成熟度后下一步就是构建计数分析系统并最终为采摘机器人输出决策指令。5.1 实时视频流处理与计数逻辑在实际采摘系统中输入通常是摄像头实时视频流。处理流程如下import cv2 from pathlib import Path import torch # 加载训练好的模型 model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/tomato_maturity_s/weights/best.pt, force_reloadFalse) model.conf 0.25 # 置信度阈值过滤弱预测 model.iou 0.45 # NMS的IoU阈值 cap cv2.VideoCapture(0) # 或视频文件路径 mature_count 0 turning_count 0 while cap.isOpened(): ret, frame cap.read() if not ret: break # 推理 results model(frame, size640) # 保持与训练一致的尺寸 # 解析结果 detections results.pandas().xyxy[0] # 转换为Pandas DataFrame current_mature 0 current_turning 0 for _, det in detections.iterrows(): x1, y1, x2, y2, conf, cls int(det[xmin]), int(det[ymin]), int(det[xmax]), int(det[ymax]), det[confidence], int(det[class]) # 根据cls判断类别 if cls 2: # 假设2是成熟 current_mature 1 color (0, 0, 255) # 红色框 elif cls 1: # 假设1是转色期 current_turning 1 color (0, 165, 255) # 橙色框 else: color (0, 255, 0) # 绿色框-未成熟 # 画框和标签 cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2) label f{model.names[cls]} {conf:.2f} cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) # 更新累计计数这里使用简单累加实际可能需要去重逻辑 mature_count current_mature turning_count current_turning # 在画面上显示计数 cv2.putText(frame, fMature: {mature_count}, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2) cv2.putText(frame, fTurning: {turning_count}, (20, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,165,255), 2) cv2.imshow(Tomato Maturity Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()计数去重挑战上述简单累加会在视频每一帧都计数导致同一个番茄被重复计数无数次。在实际系统中必须引入目标跟踪Tracking算法如ByteTrack或DeepSORT为每一帧中检测到的番茄分配唯一ID只有当新ID出现时才计数从而实现跨帧的准确计数。5.2 从检测结果到采摘指令计数是宏观分析而采摘需要微观的、针对单个果实的指令。系统需要为每个检测到的、符合采摘条件的番茄生成一个“采摘任务包”通常包含果实ID跟踪算法赋予的唯一标识。成熟度状态成熟或转色期根据业务策略决定。空间位置图像坐标边界框的中心点(cx, cy)。三维世界坐标需标定通过相机标定和深度信息RGB-D相机如Intel RealSense或双目相机将(cx, cy)转换为相对于机械臂基座的(X, Y, Z)坐标。这是最核心、技术难度最高的一环。果实姿态可选通过关键点检测或实例分割升级到YOLOv5-seg或YOLOv8-seg模型估算果梗的方向引导机械手以最佳角度抓取避免损伤果实。一个简单的决策逻辑伪代码如下for detection in current_detections: if detection.class MATURE or (detection.class TURNING and business_policy include_turning): if is_reachable(detection.3d_position): # 判断是否在机械臂工作空间内 task { id: detection.track_id, class: detection.class_name, position_3d: detection.3d_position, status: PENDING } send_to_planner(task) # 发送给路径规划模块6. 部署优化与实战避坑指南将训练好的模型部署到实际生产环境如采摘机器人、固定分选机时会遇到一系列在实验室不曾遇到的问题。6.1 模型轻量化与加速推理即使选择了YOLOv5s在边缘设备上仍可能速度不达标。可以尝试以下优化手段模型量化Quantization将模型权重从FP32浮点数转换为INT8整数可以大幅减少模型体积和提升推理速度通常只有极小的精度损失。PyTorch提供了方便的API。# 动态量化示例后训练量化 import torch.quantization model_fp32 torch.load(best.pt)[model].float() model_fp32.eval() model_int8 torch.quantization.quantize_dynamic( model_fp32, # 原始模型 {torch.nn.Linear, torch.nn.Conv2d}, # 要量化的模块类型 dtypetorch.qint8 ) torch.save(model_int8.state_dict(), best_int8.pt)TensorRT部署对于NVIDIA Jetson或带NVIDIA GPU的工控机使用TensorRT能获得最大的推理加速。需要将PyTorch模型先转为ONNX格式再用TensorRT的trtexec工具或Python API生成优化后的引擎.engine文件。这个过程可能复杂但性能提升是数量级的。OpenVINO部署对于Intel的CPU或集成显卡OpenVINO工具套件是首选。它也能将ONNX模型转换为中间表示IR并进行图优化和层融合在x86架构上效率很高。6.2 环境适应性挑战与解决方案光照剧变温室内的阳光直射、阴影、补光灯交替会导致颜色识别严重失真。方案一算法层面在数据增强中极端化HSV变换让模型见过各种“离谱”的颜色。使用CLAHE等自适应直方图均衡化作为预处理增强对比度。方案二硬件层面加装偏振镜片减少反光使用主动光源如均匀的LED补光灯创造稳定光照环境。这是最有效但增加成本的方法。枝叶遮挡与密集目标番茄植株茂密果实相互遮挡严重。方案在数据标注和增强阶段就重点覆盖遮挡场景。训练时使用更大的mosaic概率和mixup。推理时可以适当降低NMS的iou阈值如从0.45降到0.3让模型能输出更多有重叠的框再通过其他逻辑如选择置信度最高的来决策。背景干扰土壤、支架、塑料膜等可能被误检。方案大量收集不含番茄但包含这些干扰物的“负样本”图片在训练时加入。YOLOv5支持在标签文件中为负样本创建只包含背景类别的条目或者直接使用不含任何标注文件的图片。模型漂移Concept Drift随着番茄品种更换、季节变化模型性能可能下降。方案建立持续学习Continual Learning管道。部署系统时设计一个“困难样本收集”机制将低置信度或分类错误的检测框图片自动保存。定期用这些新数据对模型进行微调Fine-tuning让模型适应新环境。6.3 一个真实的性能调优案例在我参与的一个项目中初期部署YOLOv5s模型到Jetson Xavier NX上发现FPS只有15无法满足实时性要求。我们通过以下步骤将其提升到了38 FPS将输入分辨率从640降至512。这带来了约1.5%的mAP下降但FPS提升了近40%。对于我们的场景精度损失在可接受范围内。使用TensorRT进行FP16精度推理。相比FP32速度提升了约2倍精度几乎无损。优化预处理和后处理代码。将OpenCV的BGR转RGB、归一化等操作与推理过程在GPU上流水线化减少了CPU-GPU之间的数据拷贝开销。使用多线程一个线程专门负责从摄像头抓取帧另一个线程负责推理和画图避免I/O阻塞。最终这个系统能够稳定地在移动平台上运行准确识别出成熟和转色期番茄并将三维坐标发送给机械臂控制器实现了单果采摘周期约7秒的自动化作业。整个过程中最大的感触是农业AI项目算法只占一半另一半是工程、数据和对于农业场景本身的深刻理解。你需要和农艺师反复沟通“成熟”的定义需要和设备工程师一起调试相机安装角度和灯光需要在泥泞的田间调试代码。但当机械臂成功摘下第一个完全由系统识别定位的番茄时那种成就感是无与伦比的。这个项目从技术上看是目标检测的一次应用但其内核是让机器拥有了“农人”的眼睛和判断力这才是最有价值的地方。