简介:基于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', path='weights/best.pt', source='local'),这种调用方式在快速验证模型时很实用,不需要显式调用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、mAP@0.5、mAP@0.5:0.95 的上升曲线。读图逻辑是:loss 曲线持续下降无剧烈反弹,说明训练稳定;P 和 R 曲线同步上升且最终稳定在高位,说明模型既准又全。
precision-recall_curve.png是 P-R 曲线,横轴是 Recall,纵轴是 Precision,反映不同置信度阈值下的均衡表现。曲线越靠近右上角,说明模型在保持高精度的同时还能召回足够多的目标。曲线下的面积(AP)就是 mAP 的前身。对于单类检测,mAP@0.5 是 IoU 阈值 0.5 时的平均精度,mAP@0.5:0.95 是更严格的综合指标,对边界框质量要求更高。
这个工程的 mAP@0.5 和 mAP@0.5:0.95 具体数值在results.txt里能看到。如果发现 mAP@0.5 很高但 mAP@0.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 用指标指导模型选型
这套评估曲线可以用来指导你决定是否需要换更大模型。如果看到 mAP@0.5 已经超过 0.9、mAP@0.5:0.95 在 0.6 以上,对单类检测来说稳定性已经不错,想追求更好的边界框质量再考虑换 YOLOv5m 或 YOLOv5l。如果 mAP@0.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', path='runs/exp_cow/weights/best.pt', source='local') 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, f'cow {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的source='local'参数表示从本地加载模型,关键代码是results.pandas().xyxy[0]获取目标框坐标、类别和置信度。
提示:实时视频推理对单帧耗时敏感,YOLOv5s 在 GPU 上每帧约 5-10ms,CPU 上约 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 时仍然空白,优先检查图片里是否有牛、图片路径是否正确。
坑三:mAP@0.5 很高但 mAP@0.5:0.95 偏低
现象:评估曲线里 mAP@0.5 超过 0.9,但 mAP@0.5:0.95 低于 0.6。原因:目标尺度变化大,模型对高 IoU 的精确框位不够好。解决:调高输入分辨率到 800,或在hyp.yaml里调低box_loss的权重让模型更侧重框位回归,但后者会牺牲一点分类性能。
坑四:onnx.py 导出后 TensorRT 推理精度和 PyTorch 不一致
现象:ONNX 结果和 PyTorch 结果出现差异。原因:导出时算子兼容性问题或opset版本不一致。解决:导出时加--opset 12参数指定版本,并在 TensorRT 转换时关闭 FP16 精度再对比。
坑五:摄像头推理时画面卡顿严重
现象:实时推理帧率明显低于预期。原因:每次循环都做预处理和 NMS,CPU 推理时开销大。解决:先把输入帧缩放成 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 相关工程都强制走一遍这套流程,发现确实能省掉不少后期排查的时间。希望这个工程能帮你把牛识别检测的落地路径走通,少走一些我当时走过的弯路。
本文还有配套的精品资源,点击获取