智慧农业这几年喊得响,但真正能落地的场景里,番茄成熟度识别绝对算一个刚需。不管是大棚里挂满枝头的樱桃番茄,还是连栋温室里的串收大果,采摘自动化要解决的第一件事,就是让机器知道“哪个该摘、哪个不该摘、该摘的位置在哪”。这篇文章我会从项目实战的角度,把基于深度学习的番茄成熟度识别和采摘点识别整个链路拆开讲一遍,包括数据怎么准备、模型怎么选、训练有哪些坑、部署到嵌入式设备上怎么提速、最后怎么把检测框变成机械臂能用的三维坐标。适合正在做农业视觉项目的人、想入门智慧农业的学生,以及想把自己的算法真正装到采摘机器人上的开发者。我前期做过一个模拟项目X,目标就是在大棚环境里实时识别番茄成熟度,并给出果柄上的采摘点。过程中踩了不少坑,也总结了一些相对可靠的思路。下面不绕弯子,直接按实操顺序聊。1. 项目整体拆解:番茄成熟度识别到底在解决什么问题1.1 从采摘自动化倒推视觉需求很多人以为采摘机器人最难的是机械臂,实际做下来你会发现,视觉感知才是真正的瓶颈。机械臂再灵活,你得先告诉它“摘哪里”,它才能动。一个完整的采摘流程是:摄像头采集图像 → 识别出番茄的位置和成熟度 → 定位果柄采摘点 → 计算三维坐标 → 机械臂规划路径 → 末端执行器剪切或夹持。这里面每一步的输入都依赖视觉算法给出准确结果。所以成熟度识别不只是做个分类,它是整个自动化采摘链条的入口。如果模型把绿番茄当成红番茄,机械臂过去一把抓,轻则抓空,重则把还没熟的果拽下来,损失就大了。更麻烦的是,番茄是成串生长的,果实之间遮挡严重,一个框里往往有多个番茄,而且成熟度各不相同。这就要求模型不仅要能分类,还得具备较强的空间感知能力。1.2 成熟度分级标准与业务定义在动手写代码之前,先把业务标准定清楚。农业上番茄成熟度一般分绿熟期、转色期、粉红期、浅红期、红熟期。但直接按这个来做多分类,落地时会发现标注难度大、类别之间边界模糊。我实际用下来更推荐按“可采摘/不可采摘”二分类,或者按“未熟/半熟/成熟”三分类,业务目标更明确。这里有个关键经验:不要为了追求技术上的精细分类而增加模型负担。很多团队喜欢把成熟度做成6档,结果标注员累死,模型准确率还提不上去。采摘逻辑很简单——能不能摘。所以我最终采用的是三分类:未熟(绿色)、半熟(偏黄或粉)、成熟(红色),同时设定成熟占比超过70%才判定为“可采摘”。这个阈值可以根据实际品种调整,比如串收番茄要求更红,那就把阈值提到80%。采摘点识别是另一个独立任务。所谓采摘点,就是果柄上适合剪切的位置,通常靠近果实顶部与果柄连接处。这里要注意,采摘点不是果实中心,而是果柄关节处。传统目标检测算法只能给一个矩形框,无法直接给出果柄位置,所以需要单独做关键点检测或小目标检测。2. 数据采集与标注:模型效果的真正天花板2.1 数据采集的几个要点和很多朋友聊项目时,大家一上来就纠结模型结构,结果第一版数据就几百张,跑出来效果自然不行。我得说,农业场景的数据采集,难度比公开数据集高一个量级,因为环境太复杂了。番茄生长在大棚里,光从侧面和顶部同时照下来,果实表面会有反光,叶片阴影会挡住半个果子,不同时段的光线色温也不一样。如果只在晴天中午采数据,模型一到阴天就歇菜。所以采集时要刻意覆盖多种条件:晴天上午、下午、阴天、雨天(棚内)、补光灯开启时、遮阳网拉上时。角度上,除了平视,还要有俯拍和仰拍,模拟机械臂不同高度的视野。设备方面,用工业相机或者普通手机都可以。关键是保证图像清晰,不要有运动模糊。如果是RGB-D相机,比如常见的深度相机,还能同时拿到深度图,对后面算三维坐标有好处。分辨率建议不低于1280×720,原始图片太小的目标很难检出。采集数量上,我建议单类别至少1000个标注实例。比如“成熟番茄”这个类别,要保证图像里有1000个成熟的果实,而不是1000张图。因为一张图里通常有多个番茄,所以2000张图像一般够用。如果品种特别多,比如有大红番茄、粉红番茄、樱桃番茄,那每个品种都要单独覆盖。2.2 标注细节与工具选择标注工具我用过不少,最顺手的组合是LabelImg处理目标检测,compatible配合一些半自动工具做分割标注。但实际项目里,番茄成熟度识别用矩形框就够用了,不一定非要实例分割。矩形框标注速度快,训练成本低,而且结合接下来的关键点标注,完全能满足采摘需求。标注规范上,我建议这样定:每个可见的、面积大于某阈值的番茄都标注,类别按成熟度标。被遮挡超过50%的可以不标,避免给模型传递太多模糊信息。若有疑问,宁可漏标不要错标,因为错标直接教坏模型。采摘点标注是另一个标签维度。我会在每张图里给成熟的番茄标一个“采摘点”,点的位置放在果柄与果实连接处的中心。可以把它当作一个关键点,用Point的形式标在图像坐标上。如果用的是支持多标签的工具,可以在同一份标注文件里既有检测框又有关键点。我用的是自定义脚本,把LabelImg的XML转成训练需要的格式,再做关键点标注,效果还不错。数据增强方面,随机翻转、亮度调整、对比度调整、随机裁剪都常用。但有一个必须注意——不能随意改变番茄的颜色通道。比如把红色混入绿色成分,或者做较强的色调偏移,会把“成熟度”这个核心特征破坏掉,导致模型学到的颜色语义错乱。所以增强时色相(Hue)的扰动幅度要控制在很小范围,只对亮度、饱和度和几何变换下手。3. 模型选型与训练技巧:从准确率到实时性3.1 目标检测模型怎么选当前目标检测领域可选方案很多,YOLO系列、Faster R-CNN、CenterNet,还有分割模型。我实际测试下来,YOLOv8是最合适的起点。原因很直接:代码生态成熟,中文资料多,推理速度快,支持嵌入式部署。Faster R-CNN精度不差但速度太慢,在大棚里一秒钟处理不了几帧,机械臂根本没办法实时跟踪。CenterNet这类无锚框模型稍显冷门,新手调参难度大。YOLOv8提供n/s/m/l/x几个版本,模型大小依次增加。我个人推荐从YOLOv8m起步,Reason在于n和s对小目标的检测能力偏弱。如果你有足够算力,可以直接用m,后面部署到嵌入式设备再降级或者量化压缩。这里补充一个经验:训练和部署用同一个模型结构,不要训练时用m,部署时换个更小的结构,会导致精度损失很大。最好是训练时就以最终部署的模型规模为准,或者至少做知识蒸馏。如果是做实例分割,可以用YOLOv8-seg,但这会引入额外的计算量。番茄采摘点识别不需要分割出果实轮廓,只要框和关键点就够。所以检测+关键点回归是性价比最高的方案。3.2 关键点回归的实现思路采摘点识别可以单独用一个关键点检测模型,也可以和检测任务合在一起。YOLOv8自带姿态估计模型(YOLOv8-pose),它是为人体关键点设计的,但你可以迁移到果柄点上。简单做法是把采摘点当作单关键点,在检测框头部增加一个坐标回归分支。但实际训练时我发现,单独靠回归分支精度不稳定。后来我改了个更实用的策略:把果柄和采摘点当作一个细长的小目标检测框,用带方向的角度框(或简化为垂直的窄框)来检测,取框的中心作为采摘点。这种方式的好处是,利用检测的anchor机制去捕捉细长的果柄,比直接回归坐标更稳。你们也可以试一下。3.3 训练参数与调参细节我反复强调,迁移学习在农业视觉里太重要了。农业场景数据量无论怎么加,都远少于通用数据集,所以要加载COCO预训练权重。训练时,前10个epoch冻结backbone,只训练detection head;之后解冻全部微调。这样能避免初始阶段把学好的特征破坏掉。输入分辨率我设定为640×640,但番茄目标在整幅图里经常比较小,尤其是行距大的棚里,果实可能只有二三十像素。直接训练会漏检严重。这个问题的解法有几个:一是采集时尽量凑近,二是在原图上做瓦片切分,三是使用更高分辨率输入。我最后选了瓦片切分,把一张1920×1080的图切成4块960×1080,分别推理再合并结果,小目标召回率明显提升。代价是推理时间变长,需要根据实际部署平台权衡。优化器选AdamW,初始学习率1e-4,batch size尽量调大。学习率调度我用Cosine Annealing,配合线性warmup。权重衰减设0.05。类别不平衡问题在番茄成熟度里也存在,未熟番茄远多于成熟番茄(采摘期前),所以我在Loss里给成熟类加了1.5倍的权重。训练时,我用的是随机四分之一到一半概率去预测果柄,但可能效果一般。关键还是数据质量和数量。3.4 评估指标怎么看算法工程师习惯看mAP,但农业项目必须结合业务看指标。mAP是一个整体指标,而到采摘场景,漏检率才是致命的。一个成熟番茄漏检,机械臂就错过它;如果误检率高,机械臂可能对着一片叶子空抓。所以我在验证集上会同时统计每类AP、召回率、精确率,还专门统计“成熟番茄漏检率”和“未熟番茄误检为成熟”的错误率。实践中我定了一个门槛:成熟番茄的recall达到90%以上才算可用,精确率可以放到85%左右,因为误检了机械臂还可以二次判断,但漏检就彻底丢了收益。4. 部署与采摘点计算:从模型输出到机械臂动作4.1 嵌入式平台与模型加速模型训练好了,最终要跑到机器人上。常见的嵌入式平台有Jetson Nano、Jetson Orin NX、RK3588等。我用的是Jetson Orin NX,算力足够跑YOLOv8m。推理加速方面,TensorRT是绕不开的工具。把PyTorch模型导出为ONNX,再转成TensorRT FP16,通常能带来2~3倍速度提升。INT8量化能更快,但对番茄成熟度识别这种颜色敏感任务,INT8容易让红色和黄色的边界变模糊。我试过,INT8成熟度准确率至少掉5个百分点,最终保留了FP16。TensorRT转换有几个坑:一是自定义后处理算子(如NMS)最好放到TensorRT外面,用Python或C++写,不然转换容易失败;二是动态输入尺寸导出会降低性能,尽量固定640×640输入;三是如果模型有自定义层,ONNX导出时要手动映射算子,建议先跑通CPU推理再上TensorRT。4.2 采摘点三维坐标怎么算二维图像里的采摘点只是像素坐标,机械臂要抓取,必须得到三维坐标。这里要用RGB-D相机。我用的是深度相机,它同时输出彩色图和对齐后的深度图。计算流程:先把采摘点的像素坐标映射到相机坐标系,公式就是常规的反投影,用相机内参矩阵。然后从深度图上取该位置的深度值,得到相机坐标系下的三维点。注意深度图要提前配准对齐到彩色图,很多相机的SDK直接提供aligned depth。但光有单目反投影不够,因为番茄是圆的,相机看到的采摘点可能在果实背面被遮挡。一个可靠的做法是,在三目标检出之后,用深度图聚类或者点云分割,把果实表面点云拟合出球体,再结合彩色图上的关键点,估算真正的三维采摘点。这一步会用到简单的几何拟合,效果比直接取单点深度好很多。强烈建议不要跳过。4.3 手眼标定与坐标变换有了相机坐标系下的采摘点,还要把坐标转到机械臂基座坐标系。手眼标定方案一般有两种:eye-in-hand(相机装在机械臂末端)和eye-to-hand(相机固定在外侧)。采摘机器人常用eye-to-hand,相机固定在大棚顶部或机器人侧面。手眼标定就是求相机到机械臂基座的变换矩阵。用标定板(比如棋盘格或者ArUco板)在相机视野里移动几个位置,同时记录机械臂末端的位姿,然后用现有的OpenCV标定函数求解。这一步看上去简单,但实际误差特别容易踩坑。我遇到的典型问题是标定板没有完全在相机视野内、或者机械臂末端读数不准、或者标定板不平整,三步下来误差直接超过10mm。经验是:标定板要够大,保持平整,贴好防反光;机械臂移动范围尽量覆盖采摘工作区域;最后一定要在真实番茄上验证,确定连续面积的位置,不要只在标定板上做。5. 常见问题与坑:真实环境中的翻车实录5.1 光照变化导致的成熟度误判这是我在棚里遇到的最大问题。大棚顶部光照充足时,红色番茄高光溢出,相机拍出来变成粉色,模型就认为是半熟。反过来,遮阳网下光线暗,成熟番茄颜色发暗,可能被误判为未熟。应对办法分三条腿走路:一是在数据采集时加入不同光照时段和各方向补光条件;二是做光照增强预处理,比如限制对比度直方图均衡;三是在模型输入端采用色彩归一化,把LAB色彩空间转换后仅使用A、B通道(颜色通道),减少亮度干扰。实测下来第三条路效果最明显,能够把黄昏时段误判率降很多。5.2 遮挡和果实簇生导致的漏检番茄一簇一簇长,果实互相遮挡严重,模型经常只检出最外侧的果,漏掉里层的。这种情况对采摘自动化很致命,因为里层果同样成熟,如果不摘就浪费了。我试过几种后处理:软NMS比硬NMS强一点;但对严重重叠的框还是无能为力。后来改用实例分割+YOLO检测混合方案,Seg模型能把被遮挡果实的轮廓也还原一部分。为了不过多牺牲速度,我只在遮挡严重的部分区域跑Seg,整体流程是Detector粗筛,如果有密集区域则切出来二次分割。速度能接受,漏检率大幅下降。还有一个思路是把“可采摘区域”作为检测目标,而不是完整果实。比如只检测番茄表面暴露的红色区域,区域面积达标则认为有可采摘果实。这种方法牺牲了审美,但实用,可以作为备选。5.3 目标尺寸过小且模糊果柄采摘点细长模糊,在图像里可能只有几个像素。直接检测花开点效果很差。我用的改进是:在上采样后的高分辨率特征图上做检测,或者将采摘点检测放到单独的放大区域。具体流程是:第一步检测果实,拿到成熟果实的框;第二步把框外扩一定比例裁剪出来;第三步把裁剪图放大到224×224,再在这个放大图上跑一个小的关键点检测模型。这样采摘点识别的精度能得到保证。代价是多一次小模型推理,但整体算力占用不大。5.4 模型在实测环境中的性能波动模型在测试集上做得不错,到场地上效果变差,这是几乎所有农业AI项目的通病。主要原因是训练集与实测环境之间存在domain gap。解决办法:快速采集现场图片做半自动标注,微调模型,或者用大量现场图片做无监督域自适应(如果用得上的话)。我给的建议是,只要条件允许,预留一天时间做现场数据采集和微调,比在实验室里调半天参数更管用。部署之后还要定期巡检数据分布。番茄从青到红颜色一直在变,不同生长期环境背景也在变,所以模型最好每周或每两周用新的现场图片做一次在线更新。如果算力有限,可以只微调最后几层。5.5 如何量化采摘点定位误差采摘点误差很难直接用mAP衡量。我的做法是:先定义一个GT点,标注人员手工点果实与果柄连接点;模型预测点与GT点之间的距离,在图像上小于某像素(如8px)就算正确。但要真正验证,必须在机械臂上进行抓取测试,看成功率。我会记录每一次机械臂末端位置与实际果柄的距离,积累几十次数据后,算出平均定位误差和标准差。这个指标是采摘系统能否稳定的核心。一定要重视相机与机械臂的坐标系标定精度。我踩过最大的坑就是模型识别完美、输出坐标也准,但机械臂就是抓偏,后来检查发现手眼标定时机械臂读数误差累积了15mm。所以标定做完必须用已知点验证,而每个机器人安装环境都需要重新标定。写在最后的一点体会这个项目做到后面,我越发觉得,农业AI的难点不在算法,而在工程。数据要贴合大棚实际,标注要定义清楚,部署要处理光照和遮挡,坐标转换要精确到毫米级。这些活看起来琐碎,但每一项都在决定项目能不能落地。我自己的体会是:先解决“数据是否够真实、标注是否够清楚”,再谈“模型结构是否够新、精度是否够高”。很多人一上来就缠着模型刷点,反而忽略了数据清洗和前端后端配合,最后往往事倍功半。如果你也想做番茄成熟度识别相关项目,不妨先花两周把数据根打牢。有问题欢迎随时交流,也希望能听到你们在棚里踩坑的经验,共同把这个方向做扎实。
智慧农业这几年喊得响,但真正能落地的场景里,番茄成熟度识别绝对算一个刚需。不管是大棚里挂满枝头的樱桃番茄,还是连栋温室里的串收大果,采摘自动化要解决的第一件事,就是让机器知道“哪个该摘、哪个不该摘、该摘的位置在哪”。这篇文章我会从项目实战的角度,把基于深度学习的番茄成熟度识别和采摘点识别整个链路拆开讲一遍,包括数据怎么准备、模型怎么选、训练有哪些坑、部署到嵌入式设备上怎么提速、最后怎么把检测框变成机械臂能用的三维坐标。适合正在做农业视觉项目的人、想入门智慧农业的学生,以及想把自己的算法真正装到采摘机器人上的开发者。我前期做过一个模拟项目X,目标就是在大棚环境里实时识别番茄成熟度,并给出果柄上的采摘点。过程中踩了不少坑,也总结了一些相对可靠的思路。下面不绕弯子,直接按实操顺序聊。1. 项目整体拆解:番茄成熟度识别到底在解决什么问题1.1 从采摘自动化倒推视觉需求很多人以为采摘机器人最难的是机械臂,实际做下来你会发现,视觉感知才是真正的瓶颈。机械臂再灵活,你得先告诉它“摘哪里”,它才能动。一个完整的采摘流程是:摄像头采集图像 → 识别出番茄的位置和成熟度 → 定位果柄采摘点 → 计算三维坐标 → 机械臂规划路径 → 末端执行器剪切或夹持。这里面每一步的输入都依赖视觉算法给出准确结果。所以成熟度识别不只是做个分类,它是整个自动化采摘链条的入口。如果模型把绿番茄当成红番茄,机械臂过去一把抓,轻则抓空,重则把还没熟的果拽下来,损失就大了。更麻烦的是,番茄是成串生长的,果实之间遮挡严重,一个框里往往有多个番茄,而且成熟度各不相同。这就要求模型不仅要能分类,还得具备较强的空间感知能力。1.2 成熟度分级标准与业务定义在动手写代码之前,先把业务标准定清楚。农业上番茄成熟度一般分绿熟期、转色期、粉红期、浅红期、红熟期。但直接按这个来做多分类,落地时会发现标注难度大、类别之间边界模糊。我实际用下来更推荐按“可采摘/不可采摘”二分类,或者按“未熟/半熟/成熟”三分类,业务目标更明确。这里有个关键经验:不要为了追求技术上的精细分类而增加模型负担。很多团队喜欢把成熟度做成6档,结果标注员累死,模型准确率还提不上去。采摘逻辑很简单——能不能摘。所以我最终采用的是三分类:未熟(绿色)、半熟(偏黄或粉)、成熟(红色),同时设定成熟占比超过70%才判定为“可采摘”。这个阈值可以根据实际品种调整,比如串收番茄要求更红,那就把阈值提到80%。采摘点识别是另一个独立任务。所谓采摘点,就是果柄上适合剪切的位置,通常靠近果实顶部与果柄连接处。这里要注意,采摘点不是果实中心,而是果柄关节处。传统目标检测算法只能给一个矩形框,无法直接给出果柄位置,所以需要单独做关键点检测或小目标检测。2. 数据采集与标注:模型效果的真正天花板2.1 数据采集的几个要点和很多朋友聊项目时,大家一上来就纠结模型结构,结果第一版数据就几百张,跑出来效果自然不行。我得说,农业场景的数据采集,难度比公开数据集高一个量级,因为环境太复杂了。番茄生长在大棚里,光从侧面和顶部同时照下来,果实表面会有反光,叶片阴影会挡住半个果子,不同时段的光线色温也不一样。如果只在晴天中午采数据,模型一到阴天就歇菜。所以采集时要刻意覆盖多种条件:晴天上午、下午、阴天、雨天(棚内)、补光灯开启时、遮阳网拉上时。角度上,除了平视,还要有俯拍和仰拍,模拟机械臂不同高度的视野。设备方面,用工业相机或者普通手机都可以。关键是保证图像清晰,不要有运动模糊。如果是RGB-D相机,比如常见的深度相机,还能同时拿到深度图,对后面算三维坐标有好处。分辨率建议不低于1280×720,原始图片太小的目标很难检出。采集数量上,我建议单类别至少1000个标注实例。比如“成熟番茄”这个类别,要保证图像里有1000个成熟的果实,而不是1000张图。因为一张图里通常有多个番茄,所以2000张图像一般够用。如果品种特别多,比如有大红番茄、粉红番茄、樱桃番茄,那每个品种都要单独覆盖。2.2 标注细节与工具选择标注工具我用过不少,最顺手的组合是LabelImg处理目标检测,compatible配合一些半自动工具做分割标注。但实际项目里,番茄成熟度识别用矩形框就够用了,不一定非要实例分割。矩形框标注速度快,训练成本低,而且结合接下来的关键点标注,完全能满足采摘需求。标注规范上,我建议这样定:每个可见的、面积大于某阈值的番茄都标注,类别按成熟度标。被遮挡超过50%的可以不标,避免给模型传递太多模糊信息。若有疑问,宁可漏标不要错标,因为错标直接教坏模型。采摘点标注是另一个标签维度。我会在每张图里给成熟的番茄标一个“采摘点”,点的位置放在果柄与果实连接处的中心。可以把它当作一个关键点,用Point的形式标在图像坐标上。如果用的是支持多标签的工具,可以在同一份标注文件里既有检测框又有关键点。我用的是自定义脚本,把LabelImg的XML转成训练需要的格式,再做关键点标注,效果还不错。数据增强方面,随机翻转、亮度调整、对比度调整、随机裁剪都常用。但有一个必须注意——不能随意改变番茄的颜色通道。比如把红色混入绿色成分,或者做较强的色调偏移,会把“成熟度”这个核心特征破坏掉,导致模型学到的颜色语义错乱。所以增强时色相(Hue)的扰动幅度要控制在很小范围,只对亮度、饱和度和几何变换下手。3. 模型选型与训练技巧:从准确率到实时性3.1 目标检测模型怎么选当前目标检测领域可选方案很多,YOLO系列、Faster R-CNN、CenterNet,还有分割模型。我实际测试下来,YOLOv8是最合适的起点。原因很直接:代码生态成熟,中文资料多,推理速度快,支持嵌入式部署。Faster R-CNN精度不差但速度太慢,在大棚里一秒钟处理不了几帧,机械臂根本没办法实时跟踪。CenterNet这类无锚框模型稍显冷门,新手调参难度大。YOLOv8提供n/s/m/l/x几个版本,模型大小依次增加。我个人推荐从YOLOv8m起步,Reason在于n和s对小目标的检测能力偏弱。如果你有足够算力,可以直接用m,后面部署到嵌入式设备再降级或者量化压缩。这里补充一个经验:训练和部署用同一个模型结构,不要训练时用m,部署时换个更小的结构,会导致精度损失很大。最好是训练时就以最终部署的模型规模为准,或者至少做知识蒸馏。如果是做实例分割,可以用YOLOv8-seg,但这会引入额外的计算量。番茄采摘点识别不需要分割出果实轮廓,只要框和关键点就够。所以检测+关键点回归是性价比最高的方案。3.2 关键点回归的实现思路采摘点识别可以单独用一个关键点检测模型,也可以和检测任务合在一起。YOLOv8自带姿态估计模型(YOLOv8-pose),它是为人体关键点设计的,但你可以迁移到果柄点上。简单做法是把采摘点当作单关键点,在检测框头部增加一个坐标回归分支。但实际训练时我发现,单独靠回归分支精度不稳定。后来我改了个更实用的策略:把果柄和采摘点当作一个细长的小目标检测框,用带方向的角度框(或简化为垂直的窄框)来检测,取框的中心作为采摘点。这种方式的好处是,利用检测的anchor机制去捕捉细长的果柄,比直接回归坐标更稳。你们也可以试一下。3.3 训练参数与调参细节我反复强调,迁移学习在农业视觉里太重要了。农业场景数据量无论怎么加,都远少于通用数据集,所以要加载COCO预训练权重。训练时,前10个epoch冻结backbone,只训练detection head;之后解冻全部微调。这样能避免初始阶段把学好的特征破坏掉。输入分辨率我设定为640×640,但番茄目标在整幅图里经常比较小,尤其是行距大的棚里,果实可能只有二三十像素。直接训练会漏检严重。这个问题的解法有几个:一是采集时尽量凑近,二是在原图上做瓦片切分,三是使用更高分辨率输入。我最后选了瓦片切分,把一张1920×1080的图切成4块960×1080,分别推理再合并结果,小目标召回率明显提升。代价是推理时间变长,需要根据实际部署平台权衡。优化器选AdamW,初始学习率1e-4,batch size尽量调大。学习率调度我用Cosine Annealing,配合线性warmup。权重衰减设0.05。类别不平衡问题在番茄成熟度里也存在,未熟番茄远多于成熟番茄(采摘期前),所以我在Loss里给成熟类加了1.5倍的权重。训练时,我用的是随机四分之一到一半概率去预测果柄,但可能效果一般。关键还是数据质量和数量。3.4 评估指标怎么看算法工程师习惯看mAP,但农业项目必须结合业务看指标。mAP是一个整体指标,而到采摘场景,漏检率才是致命的。一个成熟番茄漏检,机械臂就错过它;如果误检率高,机械臂可能对着一片叶子空抓。所以我在验证集上会同时统计每类AP、召回率、精确率,还专门统计“成熟番茄漏检率”和“未熟番茄误检为成熟”的错误率。实践中我定了一个门槛:成熟番茄的recall达到90%以上才算可用,精确率可以放到85%左右,因为误检了机械臂还可以二次判断,但漏检就彻底丢了收益。4. 部署与采摘点计算:从模型输出到机械臂动作4.1 嵌入式平台与模型加速模型训练好了,最终要跑到机器人上。常见的嵌入式平台有Jetson Nano、Jetson Orin NX、RK3588等。我用的是Jetson Orin NX,算力足够跑YOLOv8m。推理加速方面,TensorRT是绕不开的工具。把PyTorch模型导出为ONNX,再转成TensorRT FP16,通常能带来2~3倍速度提升。INT8量化能更快,但对番茄成熟度识别这种颜色敏感任务,INT8容易让红色和黄色的边界变模糊。我试过,INT8成熟度准确率至少掉5个百分点,最终保留了FP16。TensorRT转换有几个坑:一是自定义后处理算子(如NMS)最好放到TensorRT外面,用Python或C++写,不然转换容易失败;二是动态输入尺寸导出会降低性能,尽量固定640×640输入;三是如果模型有自定义层,ONNX导出时要手动映射算子,建议先跑通CPU推理再上TensorRT。4.2 采摘点三维坐标怎么算二维图像里的采摘点只是像素坐标,机械臂要抓取,必须得到三维坐标。这里要用RGB-D相机。我用的是深度相机,它同时输出彩色图和对齐后的深度图。计算流程:先把采摘点的像素坐标映射到相机坐标系,公式就是常规的反投影,用相机内参矩阵。然后从深度图上取该位置的深度值,得到相机坐标系下的三维点。注意深度图要提前配准对齐到彩色图,很多相机的SDK直接提供aligned depth。但光有单目反投影不够,因为番茄是圆的,相机看到的采摘点可能在果实背面被遮挡。一个可靠的做法是,在三目标检出之后,用深度图聚类或者点云分割,把果实表面点云拟合出球体,再结合彩色图上的关键点,估算真正的三维采摘点。这一步会用到简单的几何拟合,效果比直接取单点深度好很多。强烈建议不要跳过。4.3 手眼标定与坐标变换有了相机坐标系下的采摘点,还要把坐标转到机械臂基座坐标系。手眼标定方案一般有两种:eye-in-hand(相机装在机械臂末端)和eye-to-hand(相机固定在外侧)。采摘机器人常用eye-to-hand,相机固定在大棚顶部或机器人侧面。手眼标定就是求相机到机械臂基座的变换矩阵。用标定板(比如棋盘格或者ArUco板)在相机视野里移动几个位置,同时记录机械臂末端的位姿,然后用现有的OpenCV标定函数求解。这一步看上去简单,但实际误差特别容易踩坑。我遇到的典型问题是标定板没有完全在相机视野内、或者机械臂末端读数不准、或者标定板不平整,三步下来误差直接超过10mm。经验是:标定板要够大,保持平整,贴好防反光;机械臂移动范围尽量覆盖采摘工作区域;最后一定要在真实番茄上验证,确定连续面积的位置,不要只在标定板上做。5. 常见问题与坑:真实环境中的翻车实录5.1 光照变化导致的成熟度误判这是我在棚里遇到的最大问题。大棚顶部光照充足时,红色番茄高光溢出,相机拍出来变成粉色,模型就认为是半熟。反过来,遮阳网下光线暗,成熟番茄颜色发暗,可能被误判为未熟。应对办法分三条腿走路:一是在数据采集时加入不同光照时段和各方向补光条件;二是做光照增强预处理,比如限制对比度直方图均衡;三是在模型输入端采用色彩归一化,把LAB色彩空间转换后仅使用A、B通道(颜色通道),减少亮度干扰。实测下来第三条路效果最明显,能够把黄昏时段误判率降很多。5.2 遮挡和果实簇生导致的漏检番茄一簇一簇长,果实互相遮挡严重,模型经常只检出最外侧的果,漏掉里层的。这种情况对采摘自动化很致命,因为里层果同样成熟,如果不摘就浪费了。我试过几种后处理:软NMS比硬NMS强一点;但对严重重叠的框还是无能为力。后来改用实例分割+YOLO检测混合方案,Seg模型能把被遮挡果实的轮廓也还原一部分。为了不过多牺牲速度,我只在遮挡严重的部分区域跑Seg,整体流程是Detector粗筛,如果有密集区域则切出来二次分割。速度能接受,漏检率大幅下降。还有一个思路是把“可采摘区域”作为检测目标,而不是完整果实。比如只检测番茄表面暴露的红色区域,区域面积达标则认为有可采摘果实。这种方法牺牲了审美,但实用,可以作为备选。5.3 目标尺寸过小且模糊果柄采摘点细长模糊,在图像里可能只有几个像素。直接检测花开点效果很差。我用的改进是:在上采样后的高分辨率特征图上做检测,或者将采摘点检测放到单独的放大区域。具体流程是:第一步检测果实,拿到成熟果实的框;第二步把框外扩一定比例裁剪出来;第三步把裁剪图放大到224×224,再在这个放大图上跑一个小的关键点检测模型。这样采摘点识别的精度能得到保证。代价是多一次小模型推理,但整体算力占用不大。5.4 模型在实测环境中的性能波动模型在测试集上做得不错,到场地上效果变差,这是几乎所有农业AI项目的通病。主要原因是训练集与实测环境之间存在domain gap。解决办法:快速采集现场图片做半自动标注,微调模型,或者用大量现场图片做无监督域自适应(如果用得上的话)。我给的建议是,只要条件允许,预留一天时间做现场数据采集和微调,比在实验室里调半天参数更管用。部署之后还要定期巡检数据分布。番茄从青到红颜色一直在变,不同生长期环境背景也在变,所以模型最好每周或每两周用新的现场图片做一次在线更新。如果算力有限,可以只微调最后几层。5.5 如何量化采摘点定位误差采摘点误差很难直接用mAP衡量。我的做法是:先定义一个GT点,标注人员手工点果实与果柄连接点;模型预测点与GT点之间的距离,在图像上小于某像素(如8px)就算正确。但要真正验证,必须在机械臂上进行抓取测试,看成功率。我会记录每一次机械臂末端位置与实际果柄的距离,积累几十次数据后,算出平均定位误差和标准差。这个指标是采摘系统能否稳定的核心。一定要重视相机与机械臂的坐标系标定精度。我踩过最大的坑就是模型识别完美、输出坐标也准,但机械臂就是抓偏,后来检查发现手眼标定时机械臂读数误差累积了15mm。所以标定做完必须用已知点验证,而每个机器人安装环境都需要重新标定。写在最后的一点体会这个项目做到后面,我越发觉得,农业AI的难点不在算法,而在工程。数据要贴合大棚实际,标注要定义清楚,部署要处理光照和遮挡,坐标转换要精确到毫米级。这些活看起来琐碎,但每一项都在决定项目能不能落地。我自己的体会是:先解决“数据是否够真实、标注是否够清楚”,再谈“模型结构是否够新、精度是否够高”。很多人一上来就缠着模型刷点,反而忽略了数据清洗和前端后端配合,最后往往事倍功半。如果你也想做番茄成熟度识别相关项目,不妨先花两周把数据根打牢。有问题欢迎随时交流,也希望能听到你们在棚里踩坑的经验,共同把这个方向做扎实。