YOLOv5实战:草地冬虫夏草检测的数据准备、训练与部署全解析

发布时间:2026/10/1 21:44:01
YOLOv5实战:草地冬虫夏草检测的数据准备、训练与部署全解析
简介基于YOLOv5的冬虫夏草检测项目包含完整数据集、可直接运行的代码和训练好的权重面向农业智能检测、中药材识别等目标检测场景。压缩包共1552个文件、约129MB主要含748张jpg图片、615个txt标注、Python脚本、YAML配置、pt权重、训练日志等。数据集由训练集491张图片与491个txt标签文件、验证集122张图片与122个txt标签文件组成均为640×480 RGB草地环境图片每图含多个完整边界框已测试20个epoch最佳mAP0.5为0.96mAP0.5:0.95为0.51尚可增加epoch提升精度。同时附带混淆矩阵、PR/F1曲线及两个权重文件便于继续训练与推理目前已有271人学习适合毕业设计、算法对比或农业检测项目参考。1. 草地里的冬虫夏草为什么非用 YOLOV5 不可冬虫夏草检测和常见的行人、车辆检测完全是两回事。它长在草地里颜色和枯草几乎一样体积又小一株完整的虫草可能只有几厘米长在画面里往往只占几十个像素。用传统图像处理去做颜色分割、边缘检测基本是六位数的数据集也救不回来的黑匣子。而 YOLOV5 在这种情况下反而成了最稳妥的选择它足够轻单张 1080p 图片在普通显卡上能跑到 30 帧以上它足够成熟网上有大量训练好的权重和踩坑记录可以借鉴它足够灵活从数据标注到模型导出全流程的代码都是开源的改起来不费劲。这篇文章不是讲论文而是讲怎么把这个项目真正跑起来。你会拿到一套完整可复用的落地路径数据集怎么准备、训练参数怎么调、训练好的权重怎么部署到实际场景里。整个过程围绕“草地中的冬虫夏草检测”这一具体目标展开带你把每一步的参数和坑都摸清楚。2. 数据集准备草地虫草检测的第一步是让模型“看对”东西2.1 数据从哪来自采图片还是公开数据集冬虫夏草不是常见目标公开数据集基本找不到对口的。常见做法是自己去草地拍或者用网络检索收集图片。但这里要先说清楚一个现实草地场景的复杂度远高于实验室环境虫草的颜色、姿态、遮挡程度、光照条件变化非常大如果只拍几十张图片YOLOV5 的训练效果会非常差。我一般建议至少采集 500~1000 张原始图片而且要有意识地去覆盖不同条件不同光照晴天直射、阴天散射、早晚低角度光不同背景茂密草丛、稀疏草地、有枯叶覆盖的地面不同姿态直立、倾斜、被草部分遮挡、只露出子座不同距离近景大目标、中景中等目标、远景小目标采集时用手机或普通相机即可但要注意分辨率尽量不低于 1280×720。如果图片尺寸太小虫草在画面中只占十几个像素后面标注和训练都会很吃力。图片格式统一为 JPG 或 PNG命名不要带中文和空格避免后续脚本处理时报错。2.2 标注格式转换从 LabelMe 的 JSON 到 YOLO 的 TXT标注工具方面LabelMe 和 LabelImg 都可以。比较常见的是用 LabelMe 做多边形标注因为虫草的轮廓不规则矩形框会框进大量背景草叶影响模型学习。但 LabelMe 导出的是 JSON 文件YOLOV5 训练需要的是每个图片对应一个 TXT 文件每行格式为类别id 中心点x 中心点y 宽度 高度这里的坐标都是归一化到 0~1 之间的浮点数。所以要写一个转换脚本把 LabelMe 的 JSON 转成 YOLO 格式的 TXT。转换脚本的核心逻辑是读取每个 JSON 文件中的多边形顶点坐标计算其外接矩形的中心点和宽高再除以图片的宽高做归一化。import json import os from PIL import Image def convert_labelme_json(json_path, output_dir, class_map): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_path data[imagePath] img_full_path os.path.join(os.path.dirname(json_path), img_path) img Image.open(img_full_path) img_width, img_height img.size txt_filename os.path.splitext(os.path.basename(img_path))[0] .txt txt_path os.path.join(output_dir, txt_filename) with open(txt_path, w, encodingutf-8) as f: for shape in data[shapes]: label shape[label] if label not in class_map: continue class_id class_map[label] points shape[points] # 多边形顶点坐标 xs [p[0] for p in points] ys [p[1] for p in points] x_min min(xs) x_max max(xs) y_min min(ys) y_max max(ys) box_width (x_max - x_min) / img_width box_height (y_max - y_min) / img_height center_x ((x_min x_max) / 2) / img_width center_y ((y_min y_max) / 2) / img_height f.write(f{class_id} {center_x:.6f} {center_y:.6f} {box_width:.6f} {box_height:.6f}\n) print(fConverted: {json_path} - {txt_filename}) # 使用示例类别名到ID的映射只有一类就设为0 class_map {cordyceps: 0} convert_labelme_json(labelme_output/1.json, yolo_labels/, class_map)这段逻辑不复杂但有两个参数需要特别注意。第一是归一化的精度。上面用了:.6f保留六位小数这个精度对于 1280×720 的图片来说足够但如果你的图片是 4K 分辨率建议改成.8f否则框的定位误差会被放大。第二是class_map的维护。如果你的数据集里有多类目标比如除了冬虫夏草还有“其他真菌”“杂物”等这个映射表一定要保证和训练配置里的data.yaml中类别顺序完全一致否则训练出的模型会张冠李戴。转换完后检查一下生成的 TXT 文件是不是和图片一一对应。一个常见翻车点是 JSON 中的imagePath写的是相对路径但脚本里拼接时多了一层目录导致图片打开失败。2.3 数据集划分训练集、验证集、测试集的比例与随机种子YOLOV5 的训练脚本需要指定训练集和验证集的图片路径。常见做法是把所有图片和对应的 TXT 标注放在同一个目录下然后用脚本按比例划分成train.txt和val.txt两个文件每行是一个图片的绝对路径。import os import random def split_dataset(image_dir, train_ratio0.8, seed42, output_dir./): random.seed(seed) images [f for f in os.listdir(image_dir) if f.endswith(.jpg) or f.endswith(.png)] random.shuffle(images) train_count int(len(images) * train_ratio) train_images images[:train_count] val_images images[train_count:] with open(os.path.join(output_dir, train.txt), w) as f: for img in train_images: f.write(os.path.join(os.path.abspath(image_dir), img) \n) with open(os.path.join(output_dir, val.txt), w) as f: for img in val_images: f.write(os.path.join(os.path.abspath(image_dir), img) \n) print(fTrain: {len(train_images)}, Val: {len(val_images)}) split_dataset(images/, train_ratio0.8, seed42)这里的seed42很关键。如果你反复训练调试不固定随机种子的话每次划分的数据集都不同导致两次训练的结果无法公平对比。固定种子后前后两次实验的差异就只来自超参数调整排查问题时有依据。train_ratio0.8是常见经验值。冬虫夏草数据集通常规模不大如果训练集比例太低模型学不到足够的特征如果验证集太少评估指标的波动会很大。一般不建议低于 0.7也不建议高于 0.9。另外测试集在训练阶段不要动用等模型训练完做最终评估时再用这是防止对测试集过拟合的基本纪律。2.4 数据增强草地上最有效的三个 trickYOLOV5 内置了 Mosaic、MixUp、HSV 扰动、随机翻转等增强策略这些在训练时自动生效。但对于草地场景我强烈建议额外做两件事。第一是 Copy-Paste 增强。冬虫夏草的分布往往很稀疏一张图里可能只有一两株模型难以学到“多个目标共存”的场景。人工截取一些虫草区域随机粘贴到草地背景图上可以有效增加每张图的目标数量。import cv2 import numpy as np import random def copy_paste_paste(background_img, object_img, object_mask, max_objects5): background_img: 草地背景图 (BGR) object_img: 虫草前景图 (BGR) object_mask: 虫草的二值mask, 白色为前景 bg background_img.copy() h, w bg.shape[:2] for _ in range(random.randint(2, max_objects)): obj_h, obj_w object_img.shape[:2] # 随机缩放0.5~1.2倍 scale random.uniform(0.5, 1.2) new_w int(obj_w * scale) new_h int(obj_h * scale) if new_w w or new_h h: continue resized_obj cv2.resize(object_img, (new_w, new_h)) resized_mask cv2.resize(object_mask, (new_w, new_h)) x random.randint(0, w - new_w - 1) y random.randint(0, h - new_h - 1) roi bg[y:ynew_h, x:xnew_w] mask (resized_mask / 255.0)[:, :, np.newaxis] bg[y:ynew_h, x:xnew_w] (mask * resized_obj (1 - mask) * roi).astype(np.uint8) return bg这段代码的关键在于mask的计算。resized_mask是 0 和 255 的灰度图除以 255 后变成 0 和 1 的浮点型 mask再扩展成三通道用于加权融合。mask * resized_obj (1 - mask) * roi实现了只有虫草区域覆盖到背景上其他区域保留原背景。注意缩放后如果虫草变得太小比如小于 16×16 像素直接跳过因为YOLOV5对极小目标的学习效果很差。第二是光照扰动。草地的光照变化极大阴天和晴天的颜色分布差异显著。除了 YOLOV5 自带的 HSV 扰动我会在离线阶段额外生成一批亮度降低 30%~50% 的暗光图片模拟清晨和傍晚的检测场景。具体做法就是对整张图做灰度变换后与原图混合。3. YOLOV5 训练从环境搭建到权重落地的完整过程3.1 环境配置conda 创建虚拟环境并安装依赖YOLOV5 的环境配置是新手翻车率最高的环节问题主要集中在 PyTorch 版本和 CUDA 版本不匹配。建议直接用 conda 创建独立环境不要动系统原有的 Python。conda create -n yolov5 python3.8 -y conda activate yolov5 pip install torch1.13.1 torchvision0.14.1 --index-url https://download.pytorch.org/whl/cu117 pip install -r requirements.txt注意三点。第一python3.8是兼容性最好的版本。YOLOV5 官方仓库对 Python 3.9、3.10 也能跑但某些第三方库如 pycocotools在 3.10 上会出现编译问题浪费大量时间。3.8 是最稳的选择。第二PyTorch 的安装方式决定了能不能用 GPU。--index-url https://download.pytorch.org/whl/cu117指定了 CUDA 11.7 版本如果你的显卡驱动较老可能要降到 cu113 或 cu116。安装完成后用以下命令验证 GPU 是否可用python -c import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))如果输出False不要继续往下走先排查驱动或 PyTorch 版本问题。强行训练只会让 CPU 跑十几个小时最后还没结果。第三requirements.txt里包含的是 YOLOV5 运行所需的依赖包括opencv-python、pandas、matplotlib等。但要注意这个文件是官方仓库的不同版本的 YOLOV5 对依赖的版本要求有细微差异。如果后面报错提示某个库版本问题优先按报错信息里的要求调整不要盲目升级。3.2 数据集配置文件data.yaml 的写法与类别映射YOLOV5 训练时需要一个 YAML 文件描述数据集信息。这个文件放在 YOLOV5 仓库的data/目录下内容很简单train: /path/to/train.txt val: /path/to/val.txt nc: 1 names: [cordyceps]train和val指向之前生成的 TXT 文件。nc是类别数量这里只有冬虫夏草一类所以是 1。names是类别名列表顺序要和标注时class_map里的映射一致。这里有一个容易被忽略的细节YOLOV5 也支持直接写图片目录路径而非 TXT 文件。但写 TXT 文件更可控因为你已经用随机种子划分好了数据集目录方式会让 YOLOV5 重新扫描目录可能导致验证集混入训练集图片。我始终建议用 TXT 方式。3.3 训练启动调好这几个参数再点回车训练命令是 YOLOV5 项目里最核心的一行几乎每个参数都直接影响模型表现。python train.py \ --data data/cordyceps.yaml \ --weights yolov5s.pt \ --epochs 150 \ --batch-size 16 \ --img 640 \ --workers 4 \ --device 0 \ --project runs/train_cordyceps \ --name v1 \ --hyp data/hyp.scratch-low.yaml逐段拆解。--weights yolov5s.pt表示用 COCO 预训练的 YOLOV5s 做初始权重。这里有个经验如果冬虫夏草和 COCO 中的任何类别都不相似不要用--weights 从零训练。从零训练需要极多的数据才能收敛而 COCO 预训练模型已经学到了通用的边缘、纹理、形状特征迁移到虫草检测上可以大幅减少训练时间和数据需求。--img 640是训练分辨率。640 是速度和精度的平衡点。因为虫草很小可以考虑用--img 960或--img 1280提升小目标检测能力但这会增加显存占用和训练时间。如果你的显卡是 8GB 显存batch-size 16 img 640 已经接近极限了。我一般先跑 640 看效果如果小目标漏检严重再调高分辨率。--epochs 150不是越多越好。冬虫夏草数据集的规模通常不到 1000 张训练到 100 轮左右 mAP 基本就稳定了后面可能出现过拟合。建议先设 150训练过程中观察验证集 loss 曲线如果 80 轮后验证集 loss 不再下降甚至回升说明开始过拟合了可以提前终止。--hyp data/hyp.scratch-low.yaml是 YOLOV5 的超参数文件。这个文件里的lr0初始学习率 0.01、mosaic启用 Mosaic 增强的概率、copy_pasteEnable Copy-Paste 增强等都对训练结果有显著影响。草地场景建议把mosaic保持在 1.0 开启状态它对小目标的训练很有帮助copy_paste默认是 0.0如果你的数据集目标数稀少建议改成 0.3~0.5。# data/hyp.scratch-low.yaml 中几个值得改的参数 lr0: 0.01 # 初始学习率数据量小可以降到0.005 mosaic: 1.0 # Mosaic增强概率 copy_paste: 0.3 # Copy-Paste增强概率默认是0 fl_gamma: 0.0 # 类别不平衡的focal loss参数单类目标设为0即可训练启动后YOLOV5 会在runs/train_cordyceps/v1目录下保存训练日志、loss 曲线和每个 epoch 结束后的验证集结果。训练过程中关注两个关键指标验证集的mAP0.5和mAP0.5:0.95。前者是主要评估指标后者更严格。草地场景如果 mAP0.5 能到 0.9 以上基本就能用了。3.4 训练好的权重best.pt 和 last.pt 选哪个训练结束后runs/train_cordyceps/v1/weights/目录下会出现两个文件best.pt和last.pt。last.pt是最后一个 epoch 的权重best.pt是验证集 mAP 最高的权重。实际部署毫不犹豫选best.pt因为它是全训练过程中泛化能力最强的快照。还有一个容易忽略的重点YOLOV5 的 .pt 权重不仅包含模型结构参数还包含训练时的超参数配置、类别名、模型结构定义等信息。所以单靠一个best.pt文件就可以完成推理不需要额外记住当时用的data.yaml内容。这也是 YOLOV5 相对其他框架最方便的地方之一。4. 推理与部署把训练好的权重用起来不只在测试集上自嗨4.1 用 detect.py 跑一批图片看效果训练完的权重很快就到验证环节了。YOLOV5 官方提供了detect.py可以直接对图片目录做批量推理。python detect.py \ --weights runs/train_cordyceps/v1/weights/best.pt \ --source ./test_images/ \ --conf-thres 0.25 \ --iou-thres 0.45 \ --img 640 \ --save-txt \ --save-conf \ --project runs/detect_cordyceps \ --name test_v1这段命令里--save-txt会把检测结果保存为和图片同名的 TXT 文件内容格式和训练标注一样类别id、置信度、归一化坐标。--save-conf让 TXT 中额外保存置信度分数方便后续做统计分析和筛选。这里要特别强调--conf-thres和--iou-thres的调参逻辑。conf-thres是置信度阈值低于这个值的检测结果会被过滤掉。0.25是 YOLOV5 的默认值但在草地场景下我一般先设0.1跑一遍看看模型在低阈值下到底能检出多少目标然后再根据误检情况逐步提高。直接设0.5可能让漏检问题被掩盖你会以为模型没检出实际上是分数不高被阈值滤掉了。iou-thres是 NMS 的 IoU 阈值用于去掉同一目标上的重复框。0.45是通常值如果检测框之间重合度很高且虫草之间挨得很近可以调高到0.5~0.6如果目标密集且容易互相重叠调低到0.3~0.4可以减少重复检测但也可能把相邻的多个目标合并成一个。4.2 用 Python 接口做二次开发控制后处理流程detect.py适合批量验证但如果你要把模型嵌到自己的巡检程序或采集系统里直接用 Python 加载权重更灵活。import torch import cv2 model torch.hub.load(yolov5, custom, pathruns/train_cordyceps/v1/weights/best.pt, force_reloadTrue) img cv2.imread(test_images/field_001.jpg) results model(img, size640, augmentFalse) boxes results.xyxy[0].cpu().numpy() # x1, y1, x2, y2, conf, class_id for box in boxes: x1, y1, x2, y2, conf, cls_id box if conf 0.3: continue cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(img, f{results.names[int(cls_id)]} {conf:.2f}, (int(x1), int(y1)-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) cv2.imwrite(test_images/field_001_result.jpg, img)torch.hub.load(yolov5, ...)的第一个参数是 YOLOV5 仓库的本地路径也可以写ultralytics/yolov5从 GitHub 在线加载但本地加载更可靠不依赖网络。size640是推理分辨率取augmentFalse可以保证推理速度augmentTrue会做多尺度推理提升精度但速度会慢很多倍。这段代码里我自己加了一层conf 0.3的判断这和detect.py里的conf-thres是同一个作用。为什么要再写一遍因为在某些场景下你希望在同一个进程里对不同区域用不同阈值。比如画面中心区域置信度要求高边缘区域要求低就不能只依赖模型默认输出需要手动控制。这里的xyxy输出是像素坐标直接映射到原始图像上。4.3 在树莓派或 Jetson 上部署的取舍草地巡检经常有边缘设备的部署需求树莓派 4B 或 Jetson Nano 是比较常见的平台。但 YOLOV5 原本是为 GPU 设计的在这些设备上跑起来需要注意几点。先说你最关心的速度问题。树莓派 4B 上跑 YOLOV5s 640 分辨率大概只有 2~4 帧每秒基本不具备实时性。Jetson Nano 会好一些但也就 10 帧左右。如果要做实时检测我建议做三步优化第一把模型导出为 TensorRT 格式。Jetson 上 TensorRT 对 YOLOV5 有专门优化推理速度能提升 2~3 倍。YOLOV5 仓库里有export.py脚本支持导出 TensorRT 引擎文件但需要自己装 TensorRT 环境。第二降低推理分辨率。从 640 降到 416 或 320速度提升明显但小目标的漏检率会上升。草地虫草检测不建议低于 416否则一整株虫草可能只有几个像素。第三跳帧处理。比如每 3 帧取 1 帧做检测其他帧直接复用上一帧结果适合运动速度不快的巡检场景。5. 草地虫草检测避坑指南这些问题我都踩过5.1 mAP 很高但实际检测效果差现象验证集 mAP0.5 达到 0.95看起来模型表现极好。但拿一批新的实地拍摄图片去检测漏检率非常高。原因数据划分时 train.txt 和 val.txt 中的图片来自同一批采集背景相似度极高。验证集里可能只覆盖了同一片草地、同一光照条件。模型学到的不是“虫草长什么样”而是“这片草地长什么样”本质上是过拟合到采集场景了。解决在数据准备阶段就把不同时间、不同地点、不同天气下采集的图片分开按批次划分训练集和验证集不要随机打乱后划分。用split_dataset脚本时手动指定按目录划分而不是全局随机。5.2 训练 loss 一直在降但验证集 mAP 迟迟不涨现象训练集 loss 下降正常甚至降到了很低的水平但验证集 mAP 在某个值附近剧烈波动没有上升趋势。原因最可能是标注质量出了问题。冬虫夏草在草地里非常难辨认标注时容易把草茎误标为虫草或者把虫草的子座和菌体分开标成了两个目标。模型学习了错误的边界和不一致的标注导致泛化失败。解决检查标注的 IoU 一致性。随机抽 20 张图用训练好的模型做预测把预测框和人工标注框画在同一张图上对比。如果发现同类目标人工标注的框形状差异很大需要重新规范标注标准。建议标注规范里写清楚框包含虫草的整体子座菌体不包含周围杂草。5.3 小目标完全检测不到现象近距离拍摄的虫草检测正常但远距离拍摄的图片中虫草只占很小区域时检测框几乎找不到目标。原因YOLOV5 在 640 分辨率下对小目标的检测能力有限小于 16×16 像素的目标基本无法学习到足够特征。另外训练时没有做针对性增强。这和模型结构有关YOLOV5 的检测头包含多个尺度但小目标的分配主要靠 P3 特征层它对浅层特征的利用还不够充分。解决首先提高训练和推理分辨率。用--img 960或--img 1280重训一版其次在数据增强里增加近景大图和远景小图的配比让模型在训练时看到不同尺度的目标最后可以手动从大图中裁剪出包含虫草的小图块把它们和原图混合训练相当于告诉模型“远处的虫草长这样”。5.4 训练时显存溢出现象启动训练后很快报错CUDA out of memory。原因batch-size 太大或分辨率太高显卡装不下。冬虫夏草数据集不大的情况下batch-size 设置 8~16 就够用了不需要追求大 batch。解决按顺序尝试三条路——调低 batch-size16 降到 8、调低分辨率640 降到 512、开启梯度累积。梯度累积参数在train.py中没有直接暴露需要修改train.py中accumulate变量的逻辑但操作较复杂一般建议前两步解决。如果还是溢出考虑用一个更大的显卡或更换为 YOLOV5n 模型。5.5 训练好的权重在另一台电脑上无法加载现象在 A 电脑上训练完的best.pt在 B 电脑上执行detect.py报错提示 KeyError 或模型结构不匹配。原因YOLOV5 版本不一致。不同版本的 YOLOV5 在模型定义上有差异你在 A 电脑上用的是 7.0 版本训练在 B 电脑上用的是 6.1 版本推理权重文件的 key 对应不上。解决保持训练和推理环境版本严格一致。最稳妥的办法是把整个 YOLOV5 仓库打包连同一个虚拟环境的requirements.txt一起交付到推理机器上。不要只传权重文件那是最容易翻车的做法。6. 进阶用多尺度推理和背景建模提升草地场景的检测上限如果你已经跑通了基础训练和推理想进一步提升准确率我建议从两个方向入手多尺度推理和背景消解。多尺度推理的原理很简单同一张图用 640、960、1280 三种分辨率分别做推理再把结果合并。虫草在 640 分辨率下可能只有 20×20 像素放大到 1280 后变成 40×40检测置信度会明显提高。YOLOV5 的detect.py和model()接口都支持augmentTrue参数来启用多尺度推理代价是每张图的推理时间变成原来的 3~5 倍。results_small model(img, size640, augmentFalse) results_large model(img, size1280, augmentFalse) # 合并两轮推理结果 combined results_small.xyxy[0].cpu().numpy() if results_large.xyxy[0].shape[0] 0: combined np.vstack([combined, results_large.xyxy[0].cpu().numpy()]) # 重新做NMS from torchvision.ops import nms boxes_tensor torch.tensor(combined[:, :4], dtypetorch.float32) scores_tensor torch.tensor(combined[:, 4], dtypetorch.float32) keep nms(boxes_tensor, scores_tensor, iou_threshold0.5) combined combined[keep.numpy()]这段代码中的关键在于尺寸对齐。640 的和 1280 的推理结果在同一坐标系下但 1280 推理输出的坐标是基于 1280 分辨率下的像素坐标。如果原始图片本来就是 1280那没问题如果原始图是 640做了缩放后再推理的 1280 结果需要把坐标重新缩回到原始尺寸。我在实际处理中一般是让推理尺寸直接等于原始图片的短边这样省去坐标变换的麻烦。背景消解针对的是另一类问题。草地背景高度复杂模型会把某些纹理像虫草的区域误检出来。一个实用的技巧是做一个简单的背景差分连续拍摄同一位置的多张图片如果某区域在多张图片中都被检出了大概率是真目标——因为背景的误检往往受光照影响不同时刻拍摄的结果会变化而真正的虫草只要不移动会稳定地被检出。我的习惯是每批新环境拍摄的图片先跑一遍conf-thres0.1的低阈值检测把模型的所有可能检出都画出来人眼扫一遍看哪些区域是稳定命中的。这个步骤能帮你快速了解模型在新环境下的误检模式比盲目调阈值有效得多。如果你想把准确率再推一步还可以考虑训练一个二分类小网络对 YOLOV5 检出的每个候选框做二次判别过滤背景误检。但这一步的收益取决于你的应用场景是否允许额外的推理时间。如果你做的是离线巡检图片分析完全值得如果做的是实时巡检建议先把多尺度推理和阈值调优用好。这套方案把训练、验证、部署、调优的路径都覆盖了。冬虫夏草检测是一个很垂直的方向YOLOV5 给了一套足够灵活的框架让个人开发者也能在有限的数据和算力条件下做出能用的模型。希望这篇文章里记下的参数和踩过坑能帮你少走几段弯路也希望你能在真实草地里收获足够好的检测效果。本文还有配套的精品资源点击获取