ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLOv11叶片计数实战:从数据准备到生长状态评估的全流程方案

YOLOv11叶片计数实战:从数据准备到生长状态评估的全流程方案 简介面向农业科研人员与计算机视觉开发者这份PDF文档系统讲解基于YOLOv11的多作物叶片计数与生长状态评估完整方案可有效缓解传统农业表型分析中目标检测效率低、人工成本高的痛点。文档共48页单个PDF约2.26MB支持目录章节跳转与书签定位阅读检索十分便捷。内容从YOLO系列算法演进切入逐一拆解YOLOv11的骨干网络、颈部网络、检测头设计以及损失函数与训练策略随后围绕数据集的采集、标注、增强和归一化梳理模型训练、量化剪枝与评估流程。针对叶片计数详细说明边界框解码、非极大值抑制、类别过滤等后处理步骤并讨论叶片重叠、光照变化、多作物混合等复杂场景的应对策略生长状态评估部分则覆盖生理指标选取、形态特征考量与环境因素关联。目前已有73人学习使用对希望将深度学习落地于智慧农业场景的读者颇具参考价值。1. 农业表型分析里的YOLOv11叶片计数不是数人头那么简单在农业表型分析里“数叶片”和“测生长状态”是最容易低估难度的两个任务。人眼数单株叶片可以很准但换成小区试验的几百个小区、每个小区几十株作物人工效率就完全撑不住。机器视觉方案里传统图像处理对均匀背景下的离体叶片有效一到田间就败给光照变化和叶片重叠。YOLOv11这类深度学习检测器的价值在于它把“找到叶片”从手动设计特征变成了数据驱动标记几千个框模型就能学会区分水稻、玉米、番茄等不同形态的叶片。但真正落地时训练模型只占一半工作量另一半在数据集组织、推理后处理和计数误差控制上。这篇内容面向打算用YOLOv11做多作物叶片计数和生长状态评估的开发者从数据准备、训练、推理到小目标优化给出一套可以直接跟着跑通的方案。2. 训练前的数据准备为YOLOv11构建多作物叶片检测数据集2.1 数据采集与标注YOLO格式下叶片框的边界要画到哪很多刚接触YOLOv11的人会直接拿网上现成的通用数据集训练结果在田间表现很差。原因不是模型不行而是叶片检测的标注标准和通用物体差别很大。通用检测框喜欢把完整物体包进去叶片在田间往往是倾斜、卷曲、互相遮挡的如果每片叶子的框都标准地贴住外接矩形模型学到的可能是“矩形区域内的纹理”而不是“叶片边界”。我一般建议两套标准对于完全展开的叶片框要紧凑贴合叶片最外侧像素不包含相邻叶片和茎秆对于被遮挡超过30%的叶片仍要标记但框只覆盖可视部分。这样模型输出的每个框代表一片可见叶片的证据后续计数时还能根据置信度处理遮挡。数据采集时不要只拍俯视正射图也要加入斜视角度、不同时间段的侧光、湿润和干燥叶片、土壤和地膜背景。多作物不是单纯把几种植物的图片混在一起每种作物要有独立类别否则YOLOv11学到的只是“叶片共有的绿色纹理”。类别设计建议使用下表这样的粒度类别名目标作物形态难点建议最小标注数rice_leaf水稻/小麦等禾本科狭长、弯曲、分蘖重叠2000maize_leaf玉米/高粱宽大、展开面积大1500tomato_leaf番茄/黄瓜等茄果类复叶、彼此遮挡2500soybean_leaf大豆/花生等豆科三出复叶、顶部新叶小1500这个表格不仅决定类别数也决定了后面data.yaml中的nc和names。如果试验只测单一作物类别就是1但工程上我仍然建议保留“leaf”外的背景类别因为YOLOv11会把田间杂草和工具上的绿色漆面误判为叶片。标注工具可以用LabelImg或Roboflow导出为YOLO格式即可。一个关键点是YOLO格式的txt每行是class x_center y_center width height坐标都归一化到0到1。Roboflow导出时如果选择了COCO格式还要转一下如果直接用LabelImg保存YOLO格式就省去这步。提示不要为了赶进度而把所有图像直接拖进训练。留出一部分同种植物的后期生长阶段图像做验证集否则模型只见过幼苗期到了拔节期计数就会崩。2.2 data.yaml与数据集划分先定类别再跑脚本YOLOv11训练自己的模型时数据集入口是data.yaml。它并不关心图片是放在一个目录还是多个目录只关心train、val和names是否匹配。常见的目录组织方式是把所有jpg和txt放在同一层用拍摄时间或传感器ID作为文件名前缀再用一个txt文件记录每个阶段的文件列表。下面这个脚本可以按比例切分训练和验证集并处理YOLO格式的标注是否缺失import random from pathlib import Path root Path(leaf_dataset) images sorted([p for p in root.rglob(*.jpg) if p.with_suffix(.txt).exists()]) random.seed(42) random.shuffle(images) train_num int(len(images) * 0.8) train_imgs images[:train_num] val_imgs images[train_num:] def write_lines(img_list, split_name): with open(root / f{split_name}.txt, w) as f: for img in img_list: f.write(str(img.resolve()) \n) write_lines(train_imgs, train.txt) write_lines(val_imgs, val.txt) print(ftrain{len(train_imgs)}, val{len(val_imgs)})脚本只把存在txt的图片计入避免出现全黑或相机抖动导致的空标注文件混入训练集。random.seed(42)保证每次运行划分结果一致方便复现。如果你有多个重复的试验小区需要按小区而不是按图片划分否则同一株作物会在训练和验证里各出现一次val指标会虚高。然后是data.yamlpath: /data/leaf_dataset train: train.txt val: val.txt nc: 4 names: [rice_leaf, maize_leaf, tomato_leaf, soybean_leaf]这里path是绝对路径train和val可以是相对path的路径也可以是绝对路径。注意names的顺序必须与标注txt里的class id一致样本不足的类别可以填写去重后的优先级。检查数据是否对齐最简单的命令是生成一个随机采样可视化脚本把标注框画回原图看边界是否错位。这一步如果不做YOLOv11训练时不会报错但mAP会一直上不去排查时浪费半天。3. YOLOv11环境配置与训练用自己的叶片数据跑通模型3.1 环境搭建与预训练权重选择YOLOv11依赖的ultralytics包同时支持训练、验证、导出和推理环境配置比老版本YOLOv5简单很多。建议用conda创建独立环境避免和其他项目的PyTorch版本打架。命令行如下conda create -n leaf_yolo python3.10 -y conda activate leaf_yolo pip install ultralytics yolo version如果电脑有NVIDIA GPU需要先确认CUDA版本一般pip安装ultralytics会自动拉取匹配的PyTorch。没有GPU也能用小batch训练但叶片是小目标imgsz通常要640以上CPU训练一个epoch会慢到难以接受。确认环境正常后可以直接下载官方预训练权重YOLOv11系列的模型权重名称在ultralytics中是yolov11n.pt对应nano如果你用的包版本较新也可能叫yolo11n.pt以yolo version输出的提示为准。对于多作物叶片计数我一般从yolov11n.pt或yolov11s.pt起步。nano体积小、适合移动端部署s在召回率上会好一点特别是番茄复叶这种容易被漏检的类别。注意不要一上来就选yolov11m或更大。叶片数据量通常只有几千张大模型容易过拟合而且推理慢会拖累后面的计数管线。先把nano跑通再看验证集哪些类别的AP低决定要不要换大模型。3.2 训练命令与关键参数imgsz、batch和epochs怎么配用命令行训练自己的数据集是最快的路径下面命令可以直接在leaf_yolo环境里执行yolo train modelyolov11n.pt dataleaf.yaml \ epochs200 imgsz640 batch16 device0 \ projectleaf_exp namebaseline \ optimizerAdamW lr00.001 \ close_mosaic10 cacheTrue这里每个参数都值得单独说。imgsz表示训练时图像短边会被缩放到640长边按比例缩放。如果原始图是2000x2000收缩后叶片可能只有十几个像素这就是后面要提高imgsz或做切图推理的原因。batch16受显存限制3060 12G一般能跑yolov11n16G以上可以尝试32。epochs200看起来多但ultralytics自带early stoppingpatience默认100轮模型在验证集上不再提升就会自动停。close_mosaic10表示最后10个epoch关闭马赛克增强防止模型被拼出来的假叶片干扰。cacheTrue把图像缓存到内存小数据集能明显加快epoch时间。下面是几个需要调节的参数速查表参数影响建议值imgsz小目标召回率640起步小目标多改1024lr0收敛速度与稳定性SGD用0.01AdamW用0.001batch梯度噪声与显存占用nano用16~32mosaic重叠叶片模拟0.5~1.0病害实验用0.3patienceearly stopping轮数50~100weight_decay过拟合控制默认即可训练过程中要看的不是训练loss而是验证集的mAP50和mAP50-95。田间叶片计数关注“有没有找到”多于“框得多准”所以mAP50更重要一般能到0.85以上说明模型可用。如果mAP50反复在0.6附近震荡优先检查标注是否漏标而不是调参。3.3 验证与导出用val命令看模型有没有学歪训练结束后runs/leaf_exp/baseline/weights/下会有best.pt和last.pt。接下来先用val命令验证一下yolo val modelleaf_exp/baseline/weights/best.pt dataleaf.yaml splitval验证集指标会输出到results.csv包括每类的precision、recall和mAP。这时候要看一个容易被忽略的点验证集图片如果拍摄时间与训练集相近模型可能会“背”下光照条件。可以单独准备一个异地或不同日期的图像文件夹用predict跑一遍看看计数结果跟人工数差多少。这是后续所有调优的基准。同时建议把模型导出为ONNX方便后面的推理后处理脚本脱离ultralytics环境运行或者部署到Jetson这样的边缘设备yolo export modelleaf_exp/baseline/weights/best.pt formatonnx imgsz640导出为ONNX后可以用onnxruntime做推理推理速度比PyTorch快不少。但ONNX导出时会把NMS嵌入图中如果你的后处理需要原始框信息可以在export命令里加上nmsFalse把NMS放到后处理里自己控制。4. 推理后处理实现叶片计数与生长状态评估的关键算子4.1 用predict保存推理结果并提取检测框训练完成后最常用的操作就是对一张高分辨率田间照片预测并保存结果。YOLOv11的predict接口会把带框的图保存到runs/detect/下还可以把每张图的检测明细存成txt。命令中最容易忽略的是imgsz要与训练时保持接近否则模型在低分辨率输入下对叶片的响应明显下降。下面是同时完成预测保存与结果提取的脚本from ultralytics import YOLO model YOLO(leaf_exp/baseline/weights/best.pt) results model.predict( sourcefield_plot_001.jpg, conf0.35, iou0.45, imgsz1024, saveTrue, # 保存画框后的图像到runs/detect save_txtTrue, # 保存标注结果txt save_confTrue, # 同时在txt里写置信度 projectleaf_pred, nameplot_001, )conf和iou是决定性参数。conf太高会漏掉被遮挡但可见的叶片太低会把背景纹理当成叶片。iou用于去重YOLOv11自带的NMS已经处理过同一叶片的多个候选框一般不需要调。枝叶密集的田块可以把conf降到0.25再配合第5章提到的切图推理提升召回。save_txt生成的文件每行是class conf x1 y1 x2 y2后面所有统计都可以从这个txt出发避免每次重复跑推理。4.2 重叠叶片去重与计数即使有NMS当同一株作物的叶片在图像上相互覆盖模型有时会把一个叶片拆成两个相邻的框。最直接的判断方法是用每个框的中心点做聚类距离过近的框合并成一个叶片。下面代码在predict结果基础上做中心点DBSCANimport numpy as np from sklearn.cluster import DBSCAN boxes results[0].boxes.xyxy.cpu().numpy() conf results[0].boxes.conf.cpu().numpy() cls results[0].boxes.cls.cpu().numpy() centers np.column_stack(((boxes[:, 0] boxes[:, 2]) / 2, (boxes[:, 1] boxes[:, 3]) / 2)) # eps用图像宽度的1%左右比较合适 eps results[0].orig_shape[1] * 0.01 clusters DBSCAN(epseps, min_samples1).fit(centers) leaf_count len(set(clusters.labels_))eps是判断两个中心点是否属于同一叶片的最大距离通常取图像宽度的1%到2%。如果同一叶子被切成上下两半中心点距离接近聚类后合并min_samples1保证任何框都不被当作噪声丢弃。这一步做完得到的才是叶片数。不同类别如果都代表叶片需要把counts和leaf_count分别统计比如番茄复叶上经常同时检出成叶和新叶两个类别都算作叶片数量而杂草类别要排除。提示DBSCAN里的eps不是固定值。相机高度改变后叶片在图像中的实际尺寸会变最好根据当天畸变校正后的像素尺寸标定一次不要直接照抄别人的参数。4.3 生长状态评估从框面积到叶面积指数生长状态评估可以看作计数的高阶输出。最常见的做法是用检测框面积除以图像总面积得到“相对叶面积”再结合叶片数量判断处于哪个生长阶段。下面代码把每个类别的叶片数和归一化叶面积汇总image_area results[0].orig_shape[0] * results[0].orig_shape[1] for r in results: boxes r.boxes.xyxy.cpu().numpy() cls r.boxes.cls.cpu().numpy().astype(int) names model.names counts {} leaf_area 0.0 for box, c in zip(boxes, cls): x1, y1, x2, y2 box areas (x2 - x1) * (y2 - y1) leaf_area areas name names[c] counts[name] counts.get(name, 0) 1 print(f叶片数{sum(counts.values())} {counts}) print(f归一化叶面积{leaf_area / image_area:.4f})归一化叶面积在幼苗期通常在0.05以下旺盛期会涨到0.2以上。但它只能作为相对指标因为检测框是外接矩形无法反映叶片卷曲或镂空。如果想进一步区分生长状态可以加一个“叶片紧凑度”特征即框的宽高比的中位数展开叶片的宽高比接近1卷曲叶片的宽高比会明显偏离1。把这个值与面积结合可以做成简单的健康度分级。实际项目中还可以把多天的统计结果写入CSV按时间序列看生长曲线但这需要跟踪同一小区的位置对齐这就引出了YOLOv11目标跟踪的作用。对固定摄像头视频流可以使用model.track()替换model.predict()配合ByteTrack给每个叶片分配ID从而避免帧间重复计数。这一部分在农业表型里属于高级方案但原理上与单帧计数一致。5. 小目标优化与结果验证田间场景下YOLOv11的进阶调参5.1 提高分辨率与SAHI切图田间图像动辄2000万像素直接缩到1024会让小叶片丢失大量细节。最直接的小目标优化是把预测时的imgsz提升到1280但显存占用会急剧上升。另一种更可控的办法是切图推理把大图切成512x512的小块分别送入YOLOv11再把结果坐标映射回原图。可以用SAHI实现pip install sahifrom sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction det_model AutoDetectionModel.from_pretrained( model_typeultralytics, model_pathbest.pt, confidence_threshold0.35, image_size640, ) result get_sliced_prediction( high_res.tif, det_model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2, )切片尺寸建议取训练imgsz的0.8到1倍太小会让模型看不到完整叶片的上下文太大又失去切图意义。overlap取0.2可以缓解叶片被切在边缘导致的重复计算SAHI内部会做NMS合并。切图后小目标的mAP一般能提升5到10个百分点但推理时间也会成倍增加。5.2 注意力机制与CARAFE的取舍当常规调参已经到瓶颈时才会考虑修改YOLOv11的网络结构。常见做法是在backbone输出后添加自注意力机制例如让最后一层C3k2模块变成C2PSA这样模型能更关注叶片与背景的语义关系对光照变化更鲁棒。但自注意力机制会增加参数量和推理耗时叶片数据量少时反而容易过拟合。另一个热门改进是把上采样从最近邻插值换成CARAFE它让上采样过程学习如何根据像素内容重建特征对狭长叶片边缘的检测有改善。做修改前建议先确认瓶颈确实是特征融合而不是数据。判断方法很简单把验证集里漏检的图拿出来看如果漏检的都是小于10像素的叶片说明分辨率问题占主导先做切图如果漏检的是被泥土覆盖的叶片才值得改网络结构。5.3 用计数误差指标验证改进是否有效最终要看计数误差而不是mAP。叶片计数的评价指标与检测指标不同通常用人工数出的叶片数作为真值与模型计数比较。推荐用MAE和相对误差import numpy as np manual_counts np.array([35, 42, 28, 51, 60]) auto_counts np.array([34, 44, 29, 48, 58]) mae np.mean(np.abs(manual_counts - auto_counts)) rmse np.sqrt(np.mean((manual_counts - auto_counts) ** 2)) relative_error mae / manual_counts.mean() * 100 print(fMAE{mae:.2f} leaves, RMSE{rmse:.2f}, relative error{relative_error:.1f}%)如果MAE已经小于人工计数本身的重复测量误差通常两次人工计数相差2到3片就说明模型计数已经达到可用水平。对多作物场景还应分别统计每个类别的MAE找出拖后腿的作物。比如水稻分蘖期叶片密集计数误差往往最大这时可以回到第2章补充难例标注或者单独训练一个水稻专用模型。最终建议是每次试验都保存一张带检测框的预测图和一个CSV结果表误差指标能压到多少直接决定这套YOLOv11方案能不能从试验田推向生产。本文还有配套的精品资源点击获取
返回列表