ARTICLE DETAIL

资讯详情

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

基于YOLOv5的牛只识别检测工程实战:从模型训练到推理部署

基于YOLOv5的牛只识别检测工程实战:从模型训练到推理部署 简介基于YOLOv5的牛只识别检测项目完整文件包面向深度学习初学者、农业视觉方向开发者及高校实验场景可用于图像/视频中牛的检测、训练与评估。包内集成源码、预训练权重及使用说明并附完整训练过程曲线能帮助快速复现检测流程并理解各阶段指标变化。压缩包共79个文件大小约42.58MB主要由Python脚本17个py及23个pyc、YAML配置文件17个、模型权重3个pt、训练与评估图表7张jpg和4张png、文本说明4个txt以及Shell脚本和Dockerfile等构成覆盖数据配置、模型训练、推理验证和部署环境搭建等环节。目前已有273人学习下载。数据侧使用4000余张图片训练标注目标“牛”超过8000个训练迭代200轮模型拟合良好从loss下降曲线、召回率、精确率与mAP曲线可清晰观察收敛情况。无论是入门目标检测实践还是基于农业场景做算法优化都能从这份资料获得可复用的代码框架、真实训练参考与使用指引。1. 牛识别检测这个资源到底能拿来干什么搞农业视觉或者智慧牧场的人大概率遇到过这样的场景监控摄像头里一群牛走来走去靠人眼数清楚有多少头、哪头牛状态异常既费人力又容易漏。这个项目就是把深度学习里的目标检测算法 YOLOv5 直接落到牛只识别上源码、训练好的模型权重、评估曲线和使用说明打包成一份 zip解压之后能跑通训练也能直接做推理检测。我拆过的目标检测工程里这个算是结构完整、自带训练产物的对想入门 YOLO 系列或者做畜牧视觉的人来说是个可以直接当模板参考的实物。项目里最值钱的部分我认为是三个一是基于 YOLOv5 的完整训练代码二是用 4000 多张图片、8000 多个牛目标训练出来的模型权重三是训练过程中记录的 loss、Recall、precision、mAP 等评估曲线。这部分能让你不用重新标注数据、从头炼丹直接看到训练结果和拟合状态。适合的人群很明确正在做动物检测、智慧农业相关项目的人或者刚学完 YOLOv5 原理、想找一个带真实数据集和训练产物的完整工程来对照学习的人。接下来我会从工程内部结构、训练参数、评估曲线解读、推理部署和踩坑几个层面把这份资源拆开讲清楚。2. 工程文件拆解每个目录和脚本分别管什么活2.1 从文件树看懂工程骨架打开解压后的目录第一眼可能会被一堆文件和文件夹搞懵但 YOLOv5 的工程结构其实非常固定。这个项目和官方 ultralytics/yolov5 的版本保持了很高的一致性核心是yolov5_code这个目录里面放着train.py、detect.py、test.py、onnx.py、sotabench.py等脚本这是整套代码的入口。models里是网络结构定义utils里是数据处理、损失计算、指标评估等工具函数data里放数据集配置。inference和weights分别是推理输入输出目录和预训练权重存放位置。关键的是runs和exp_cow这两个部分。runs是训练过程中自动生成的实验记录目录exp_cow则是对应牛检测这次实验的产物集合里面有opt.yaml、hyp.yaml、results.png、labels.png以及weights目录下的best.pt和last.pt。这些文件比代码本身更能说明问题——opt.yaml记录了训练时的所有超参和命令行参数hyp.yaml是 YOLOv5 的强化超参配置results.png是训练过程的损失和指标曲线汇总而weights下的两个权重文件分别代表最佳模型和最后一次迭代的模型。提示拿到任何训练工程我建议你第一件事不是看代码而是看opt.yaml和hyp.yaml。这两个文件把所有关键决策都记录在案省去反推参数的时间。2.2 核心脚本的功能边界train.py是训练入口负责加载数据、构建模型、执行训练循环并输出日志和权重。detect.py是推理入口输入图片或视频输出检测框和置信度。test.py在 YOLOv5 中实际是验证入口对测试集评估模型表现并生成指标。onnx.py负责把 PyTorch 模型导出为 ONNX 格式方便后续部署到 TensorRT、OpenVINO 或边缘设备。sotabench.py是用于在 sotabench 平台上提交模型评估结果的脚本本地一般用不到但不影响工程完整性。hubconf.py让模型可以通过 PyTorch Hub 方式加载比如torch.hub.load(./yolov5_code, custom, pathweights/best.pt, sourcelocal)这种调用方式在快速验证模型时很实用不需要显式调用detect.py。requirements.txt列了环境依赖包括 torch、opencv-python、matplotlib 等装环境时用pip install -r requirements.txt一把梭即可。再看数据处理部分。data目录下的数据集配置 YAML 文件定义了训练集、验证集路径以及类别名这个工程是单类检测所以nc应该为 1类别名对应 cow。标注文件格式是 YOLO 的 txt 格式每行是class x_center y_center width height坐标都是相对于图片宽高的归一化值。utils/datasets.py里实现了加载器支持 mosaic 增强、mixup 等策略。2.3 打开模型权重和推理输出weights目录下有yolov5s.pt作为官方的 COCO 预训练权重它是在 COCO 数据集上训好的作为迁移学习的起点。真正针对牛检测训练出来的是exp_cow/weights/best.pt和last.pt之前提到的yolov5s.pt是基础。best.pt是验证集上 mAP 最高的权重last.pt是最后一次迭代的权重两者可能存在差异因为训练后期可能有波动。runs/detect或inference/output里存放检测后的结果图。放在工程里的test_batch0_pred.jpg是训练过程中对测试集第一张图片的预测结果可视化框和类别标签都画上去了。test_batch0_gt.jpg是对应的真值标注可视化这两张图对比着看能快速直观判断模型学习效果——如果预测框和真值框位置高度重叠说明拟合到位。配套的使用说明.txt是整个工程最友好的部分把常用命令和注意事项都写了比如怎么安装依赖、怎么跑detect.py推理、模型文件在哪个路径。我建议拿到资源后先读这个文件能少踩很多个坑。3. 训练配置与数据分布4000 张图、8000 个目标的拟合逻辑3.1 数据规模和分布决定了模型上限摘要里提到一个关键数字4000 多张图片训练8000 多个标注目标“牛”数据分布均匀。这个“均匀”非常关键它意味着标注框没有出现严重的尺度偏差——不会全是远距离的小目标或全是特写的大目标而是覆盖了不同距离、不同姿态下的牛。在labels.png里能看到目标中心点的分布散点图和宽高尺度分布图如果目标中心点集中在画面中央、尺度集中在某个区间模型就容易被特定构图限制泛化能力受影响。这个工程数据分布均匀给训练结果提供了可靠前提。目标检测领域有个常见判断每类目标建议至少 1500 个实例这个项目单类 8000 多个目标远超这个阈值所以不会因为数据量不足导致欠拟合。这个规模配合 YOLOv5s 这种轻量模型训练时间和显存消耗都在可控范围内。地址8000 个目标支撑起一个单类检测器是够用的。3.2 opt.yaml 与 hyp.yaml 里的关键训练参数训练 200 次迭代、模型拟合较好这个结论不能靠感觉要看results.png里的曲线。但在此之前先看opt.yaml里记录的核心训练参数。# opt.yaml 示例关键字段 epochs: 200 batch_size: 16 imgsz: 640 data: data/cow.yaml weights: weights/yolov5s.pt hyp: hyp.yaml device: 0每个参数作用如下epochs是总迭代轮数200 轮对单类检测任务来说够用了通常训练后期 loss 和 mAP 已经在平台期再多轮次容易过拟合。batch_size是每批图片数量16 是 1080Ti 或 V100 这类单卡显存下的常规选择显存紧张可以调到 8。imgsz是输入分辨率640 是 YOLOv5 的默认推荐值超过 640 会提精度但明显增加计算量。weights指定了从yolov5s.pt开始做迁移学习比从头训练收敛快得多也稳定得多。device指定使用哪块 GPU默认是从 0 开始。再看hyp.yaml里的超参有几个直接影响训练效果# hyp.yaml 关键超参 lr0: 0.01 # 初始学习率 lrf: 0.01 # 最终学习率 lr0 * lrf momentum: 0.937 # SGD 动量 weight_decay: 0.0005 # 权重衰减 warmup_epochs: 3.0 # 预热轮数 mosaic: 1.0 # mosaic 增强概率 fl_gamma: 0.0 # focal loss gamma学习率策略是 cosine 衰减从 0.01 降到 0.0001。warmup_epochs前 3 轮用较小学习率稳定起步避免初期梯度爆炸。weight_decay是正则化系数防止过拟合。mosaic增强概率为 1.0每张训练图都是由 4 张图拼成的马赛克图这能大幅提升小目标和遮挡场景的检测能力是 YOLOv5 精度提升的一个重要手段。提示如果显存不够可以优先降低batch_size然后同步把imgsz从 640 降到 512。不要只降 batch 不降分辨率梯度噪声会变大训练容易不稳。3.3 训练过程的实际产物解读训练时train.py会往runs/exp_cow写入一系列文件。train_batch0.jpg、train_batch1.jpg、train_batch2.jpg是训练过程中不同批次的可视化结果带标注框方便看出数据增强后的实际情况。test_batch0_gt.jpg和test_batch0_pred.jpg则是验证集上同一批图片的真值与预测对比。results.txt记录了每一轮的 loss 值和指标明细格式类似于epoch, GPU_mem, box_loss, obj_loss, cls_loss, P, R, mAP.5, mAP.5:.95。单类检测时cls_loss通常占比不大重点关注box_loss和obj_loss的下降趋势以及 mAP 的变化。查看训练是否收敛的标准是看 loss 是否进入平台期、mAP 是否不再明显上升。这个工程 200 轮做到 loss 稳定下降、mAP 曲线趋平所以“拟合较好”是有依据的不是凭空说的。4. 评估指标曲线怎么看出模型真实水平4.1 precision、recall 与 mAP 的实际意义评估指标曲线是这份资源里含金量最高的部分之一。results.png是总览图包含 box_loss、obj_loss、cls_loss 的下降曲线以及 Precision、Recall、mAP0.5、mAP0.5:0.95 的上升曲线。读图逻辑是loss 曲线持续下降无剧烈反弹说明训练稳定P 和 R 曲线同步上升且最终稳定在高位说明模型既准又全。precision-recall_curve.png是 P-R 曲线横轴是 Recall纵轴是 Precision反映不同置信度阈值下的均衡表现。曲线越靠近右上角说明模型在保持高精度的同时还能召回足够多的目标。曲线下的面积AP就是 mAP 的前身。对于单类检测mAP0.5 是 IoU 阈值 0.5 时的平均精度mAP0.5:0.95 是更严格的综合指标对边界框质量要求更高。这个工程的 mAP0.5 和 mAP0.5:0.95 具体数值在results.txt里能看到。如果发现 mAP0.5 很高但 mAP0.5:0.95 偏低通常说明预测框和真值框的 IoU 不够好可能原因是目标尺度多样且小目标占比高或者边界框回归不够精准。4.2 从曲线判断拟合状态对 200 次迭代的拟合判断可以按下面的方法套用训练初期 3 个 loss 值快速下降P 和 R 从低位爬升说明模型在快速学习特征100 轮附近 loss 下降速度明显放缓mAP 曲线趋于稳定说明模型进入收敛区200 轮结束时曲线平稳波动没有出现 loss 先降后升的过拟合信号说明当前设置下模型拟合良好。反过来看标签质量也很重要。labels.jpg是数据集中所有目标的中心点分布散点图和宽高分布横纵比图。中心点分布均匀说明目标在画面各区域都有出现没有集中在某一块宽高比分布显示牛的框形以横向矩形为主符合牛侧边站立的物理形态。labels_correlogram.jpg展示宽高相关性如果出现极度线性相关的分布说明标注框的尺度变化太少模型在不同大小目标的泛化能力会受限。这套图通常是用来检查训练数据是否合格。注意如果labels.jpg里的中心点分布像一张全黑的图只有少量散点大概率是标注文件把坐标归一化写错了或者图片读取路径错误导致加载了大量空白图。4.3 用指标指导模型选型这套评估曲线可以用来指导你决定是否需要换更大模型。如果看到 mAP0.5 已经超过 0.9、mAP0.5:0.95 在 0.6 以上对单类检测来说稳定性已经不错想追求更好的边界框质量再考虑换 YOLOv5m 或 YOLOv5l。如果 mAP0.5 持续低于 0.8先不要急着换模型而是去检查标注质量和数据多样性模型换大了该漏检还是漏检。我之前用类似曲线调参的经验是当 P 很高但 R 偏低时说明模型预测偏保守宁可少检也不肯误检这种情况下可以调低置信度阈值来提升召回当 P 和 R 都偏低时说明特征学习不够优先加数据或换更大模型。这里项目自带的权重如果在这两个指标上表现都不错直接用作推理就够不需要额外再训练。5. 推理部署与常见问题detect.py、ONNX 导出和避坑记录5.1 用 best.pt 跑一次推理工程训练好的模型要落地使用入口是detect.py。推理流程分为单张图片、视频流两种情况。单张图片推理命令如下python detect.py --weights runs/exp_cow/weights/best.pt --source inference/input/cow_test.jpg --conf-thres 0.5 --iou-thres 0.45 --project runs/detect --name exp_cow这些参数中--weights指定权重路径--source支持单张图片、文件夹路径、视频文件或者摄像头设备号比如0--conf-thres是置信度过滤阈值低于该值的检测框全部丢弃--iou-thres是 NMS 的 IoU 阈值用于消除同一目标的重复框。--project和--name控制输出目录检测结果图会保存到runs/detect/exp_cow下。置信度阈值是调检测效果最直接的旋钮。0.5 是均衡策略适合大多数场景。如果漏检严重就降到 0.25 左右但代价是误检增加如果误检多就提高到 0.6 以上。判断依据是看检测结果的标签和置信度数字如果某个置信度低于 0.4 的框实际上是对的说明阈值设高了。5.2 视频流推理和 ONNX 导出牛识别检测在真实场景里通常不是处理静态图片而是分析监控视频流。detect.py本身支持视频文件输入把--source改成视频文件路径即可它用 OpenCV 逐帧推理然后写出到结果视频。但工程里没有直接提供摄像头实时推理脚本需要自己写一个简单的循环常见做法是import cv2 import torch # 加载本地模型 model torch.hub.load(./yolov5_code, custom, pathruns/exp_cow/weights/best.pt, sourcelocal) cap cv2.VideoCapture(0) # 0 表示第一个摄像头 while True: ret, frame cap.read() if not ret: break results model(frame) r results.pandas().xyxy[0] # 转为 DataFrame for _, row in r.iterrows(): x1, y1, x2, y2 int(row[xmin]), int(row[ymin]), int(row[xmax]), int(row[ymax]) conf round(row[confidence], 2) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, fcow {conf}, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imshow(cow detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段逻辑是整个视频分析流程最精简的实现。每一帧都做一次前向推理然后直接把坐标画在画面上。注意torch.hub.load的sourcelocal参数表示从本地加载模型关键代码是results.pandas().xyxy[0]获取目标框坐标、类别和置信度。提示实时视频推理对单帧耗时敏感YOLOv5s 在 GPU 上每帧约 5-10msCPU 上约 50-100ms。如果 CPU 跑起来卡顿先尝试把imgsz降到 416代价是精度略降。如果想部署到生产环境一般需要把模型导出成 ONNX 再转 TensorRT 或 OpenVINO。这个工程里onnx.py提供一键导出功能使用示例如下python onnx.py --weights runs/exp_cow/weights/best.pt --img 640 --batch 1完成后会生成best.onnx。ONNX 导出时要注意--dynamic参数控制是否允许动态 batch 和动态尺寸默认是固定尺寸。固定尺寸匹配了 TensorRT 生成 engine 的要求生产环境建议固定想灵活处理不同分辨率再考虑动态。5.3 避坑记录这些场景我都实际见过拿到这个工程跑通全流程不算难但有几个坑属于高频出现、排查起来费时间的列在这里供参考。坑一指定了错误路径导致模型加载失败现象执行detect.py时报错提示文件不存在或模型加载不成功。原因很多人直接写--weights yolov5s.pt但工程真正训练好的权重在runs/exp_cow/weights/best.pt路径不对。解决前面的命令里给的就是正确路径先确认best.pt所在位置用绝对路径最保险。坑二推理结果全是空白/检测不到任何牛现象输出图片存在但没有任何检测框。原因--conf-thres设置太高例如 0.8导致大量低置信度框被过滤掉。解决先降到 0.1 看看模型输出确认能检测到目标后再往上调。如果 0.1 时仍然空白优先检查图片里是否有牛、图片路径是否正确。坑三mAP0.5 很高但 mAP0.5:0.95 偏低现象评估曲线里 mAP0.5 超过 0.9但 mAP0.5:0.95 低于 0.6。原因目标尺度变化大模型对高 IoU 的精确框位不够好。解决调高输入分辨率到 800或在hyp.yaml里调低box_loss的权重让模型更侧重框位回归但后者会牺牲一点分类性能。坑四onnx.py 导出后 TensorRT 推理精度和 PyTorch 不一致现象ONNX 结果和 PyTorch 结果出现差异。原因导出时算子兼容性问题或opset版本不一致。解决导出时加--opset 12参数指定版本并在 TensorRT 转换时关闭 FP16 精度再对比。坑五摄像头推理时画面卡顿严重现象实时推理帧率明显低于预期。原因每次循环都做预处理和 NMSCPU 推理时开销大。解决先把输入帧缩放成 640x640减少缩放开销CPU 推理可以改用半精度或者换成 OpenVINO 的 IR 模型。# 导出 ONNX 时指定 opset python onnx.py --weights runs/exp_cow/weights/best.pt --img 640 --opset 126. 进阶用法校准阈值和模型量化把best.pt部署好只是第一步实际项目中让模型在特定场景下表现更好通常会做两件事校准置信度阈值和模型量化压缩。置信度阈值的校准用法是把训练集或验证集图片全部推理一遍统计每个检测框的置信度分布。如果 90% 的正确检测框置信度集中在 0.7-0.9 之间那么阈值设 0.6 是安全的如果有一部分正确目标置信度只有 0.4那就需要用 0.3 左右的阈值再通过 NMS 和后处理去掉重复框。这个工程里自带评估曲线可以对照 P-R 曲线找到 Precision 和 Recall 的交汇处那个点对应的置信度通常是个不错的起点。模型量化压缩方面PyTorch 工程里最简单的是半精度推理detect.py和hubconf.py都天然支持半精度模式。执行推理时加上--half参数GPU 上显存占用减少约一半推理速度提升明显精度损失可以忽略。如果你要部署到 CPU 上半精度不生效应该考虑把 PyTorch 模型转成 ONNX 后用 OpenVINO 工具量化为 INT8但这需要额外的工具链且对精度有轻微破坏建议先评估再实施。还有一个实用的技巧是自己扩展类别。这个工程当前是单类如果在你的场景里还需要识别“小牛”“成年牛”或者“牛羊”不需要改网络结构只需要重新标注数据和修改data目录下的 YAML 配置把nc改成新类别数然后从头训练。YOLOv5 的类别扩展成本主要集中在数据标注代码层改动很小。如果现有数据的标注信息没有类别区分就没法直接用得加标注。我从拆这个工程里学到一个习惯不管权重是谁训的拿过来第一件事永远是看results.png和labels.png而不是直接跑推理。这两个文件能告诉你能对结果抱多大信心。从那以后我每次跑 YOLOv5 相关工程都强制走一遍这套流程发现确实能省掉不少后期排查的时间。希望这个工程能帮你把牛识别检测的落地路径走通少走一些我当时走过的弯路。本文还有配套的精品资源点击获取
返回列表