简介:基于YOLOv5的猪脸目标检测模型与代码,是一套利用PyTorch框架实现的深度学习目标检测方案,面向畜牧业智能化管理中的健康监测与个体识别等场景,适合目标检测学习者、算法工程师及畜牧信息化开发者参考。包内共236个文件,以53个Python脚本、49个YAML配置、5个Jupyter Notebook、2个预训练PT权重及示例图片为主,另有Dockerfile、Shell脚本、Markdown等辅助内容,整体约70.75MB,目录结构与YOLOv5官方工程保持一致,便于直接运行和二次开发。项目提供best_yolo_tiny.pt与best.pt两套权重,分别对应轻量快速与标准高精度场景;main.ipynb串联环境设置、模型加载、数据准备、目标检测与结果可视化完整流程,示例图片可立即验证效果;相关配置还涉及Focal Loss、数据增强、多尺度训练等技术,便于进一步调优和扩展。目前已有1289人学习下载,适合作为定制化猪脸检测或YOLOv5应用项目的实用起点。 我最早接触猪脸目标检测,是给一个做智慧养殖的朋友帮忙。他们猪场想搞个体识别,靠耳标成本高、容易掉,想着能不能用摄像头直接认猪。最初的需求很简单:圈舍里那么多头猪,先用目标检测把每一头猪的脸找出来,再做后续识别。那会儿yolo-v5正好成熟,我就基于它走了一遍从数据到训练再到本地部署的完整流程。这篇文章把我从零搭起来的整个方案、踩过的坑、最终沉淀的代码结构都整理出来,给打算做类似畜牧视觉识别的朋友一个可以直接参照的工程样本。
整个方案的核心就三件事:一是搞清楚yolo-v5目标检测在猪脸这种小目标、高遮挡场景下应该怎么配数据;二是把训练和评价流程跑通,能用mAP、PR曲线这些指标判断模型好坏,而不是靠肉眼猜;三是训练完怎么把模型加载进自己的代码里,完成实时推理。我会把自己实际用的参数配置和代码块都贴出来,你照着改就能跑。
1.1 YOLOv5在畜牧视觉里的生态位置
做猪脸检测之前,我其实比较过一版yolo-v8和yolo-v5。yolo-v8代码更新、结构更先进,但对硬件要求高,而且很多在v5上验证过的预训练权重和部署工具链不能直接兼容。在工业现场,很多时候不是追新,而是求稳。yolo-v5虽然是几年前的模型了,但它的检测精度在小目标和密集场景下依然能打,而且改造成本低——你从GitHub拉下来就能训,导出onnx也成熟。
选yolo-v5还有一个实际原因:它的网络结构相对直白,出了问题好排查。比如猪脸检测里常见的漏检问题,多半出在anchor尺寸和目标大小不匹配上,v5的anchor可以在训练阶段自动调整,Log数据也能看得明明白白。畜牧视觉还有一个特点——场景相对固定,变化不如自动驾驶复杂,所以不需要频繁升级模型结构,v5的泛化能力已经够用。
1.2 小猪个体检测的整体链路
顺着需求梳理,整个链路大概是这样的:
- 摄像头采集圈舍画面,按帧抽图保存本地;
- 用labelimg对猪脸位置画框,生成yolo格式的txt标注;
- 划分训练集和验证集,写data yaml文件;
- 基于yolo-v5s预训练权重开始微调训练;
- 训练完用metrics读取mAP、precision、recall等评价标准;
- 把权重导出为pt格式,写Python推理脚本加载本地模型;
- 接上摄像头或视频流,实时输出猪脸框体和置信度。
这篇文章重点放在第3到第7步,也就是“模型训练与部署”这一段。数据标注部分我会给方法,但不会展开太多工具操作,因为那把篇幅拉得太长了。
2. 猪脸数据集的构建:最耗时也最决定上限
2.1 需要多少数据才够训
这个问题的标准答案通常是“越多越好”,但实际训练中,猪脸检测对数据量要求并不像分类任务那么夸张。我这次用的是3000多张图片,每张图里至少有一头猪的正脸或侧脸。最开始只有几百张的时候,训练完mAP只有0.6左右,加了数据增强也只能勉强到0.7。后面补充到接近3000张,mAP才稳定在0.89以上。
我建议最少准备2000张标注图片。少于这个量,猪脸姿态稍微变一点就容易漏检。注意,数据要覆盖不同光线和角度——圈舍里白天和晚上的光照差异很大,如果全采集白天的图,晚上推理效果会骤降。另外就是遮挡问题,猪喜欢挤在一起,数据里必须有大量局部遮挡的猪脸,不然模型学不会“只露半张脸也算猪”。
2.2 框怎么打才不会被网络带偏
标注质量直接影响模型上限。我见过很多人做检测数据集时“框得太随意”——框的范围太大,把脖子、耳朵、料槽都框进去了,结果模型学到的是“一片粉色的区域”,而不是真正的猪脸特征。
我自己用的规则很简单:
- 猪脸区域包含双眼和鼻吻部,如果眼睛被完全挡住,这个猪脸不标;
- 框紧贴脸部轮廓,不要把耳朵根部和下颌空白区域圈进来;
- 同框多猪时,A猪的框不能吃到B猪的脸;
- 对模糊帧直接删除,不硬标。
每张图标注完,我会用labelimg挪一遍框的位置,确认没有跨猪的区域。这套标准看起来很死板,但训练出来的结果很稳定。
2.3 目录结构与train/val划分比例
这是初学者最容易翻车的地方——目录结构混乱,导致加载本地数据的时候缺文件或者路径对不上。我习惯的项目目录如下:
pig-face-detection/ ├── data/ │ ├── images/ │ │ ├── train/ # 约85% │ │ └── val/ # 约15% │ ├── labels/ │ │ ├── train/ │ │ └── val/ └── pig_face.yamlimages/train和labels/train按文件名一一对应,比如PIG001.jpg对应PIG001.txt。txt文件里每一行是:
class_id x_center y_center width height五个值都是相对于图片宽高的归一化坐标,不是像素值。网上很多教程在这块没强调清楚,导致新手复制代码后训练时Loss直接崩掉,因为坐标范围错了。
我的train/val划分直接用了yolo-v5仓库里的split_train_val.py脚本,按0.85/0.15随机分配。记得划分完之后手动抽查一下val里有没有跟train重复的图片,重复会导致评价指标虚高,看起来mAP很漂亮,实际部署完全拉胯。
2.4 yaml配置文件里容易忽略的字段
pig_face.yaml是整个训练配置的枢纽,直接决定训练器从哪里读数据、识别哪几类目标。我写了一个最小可运行版本:
# pig_face.yaml path: E:/pig-face-dataset # 数据集根目录,改成本机实际路径 train: images/train val: images/val nc: 1 names: ['pig_face']从yolo-v5的角度看,它要求的路径和项目根路径有关联,如果你把数据集放在yolo项目外面,path字段必须写成绝对路径,这个字段写错会出现训练集图片数显示为0的报错。因为只有一个目标类别,nc设为1,names只放一个类名。这里的类名不影响训练,但会影响推理时显示的文字。
另一个容易被忽略的字段是download,有的教程会写download: https://.../pig.zip,本地训练时不需要下载,留着反而不小心触发网络请求。建议直接删掉或者注释干净。
3. 训练配置与关键参数:照着填就能训
3.1 选择哪个预训练权重
yolo-v5有yolov5s.pt、yolov5m.pt、yolov5l.pt等好几个档。只做猪脸检测且要在普通显卡上跑,我推荐yolov5s.pt起步。它速度快、显存占用低,精度虽然不如m和l,但猪脸检测是单类目标,复杂度远低于COCO的80类,s的容量足够。
如果你的检测场景特别复杂,比如圈舍里有大量猪只互相遮挡、光照极差,可以试yolov5m.pt。我实测下来,m比s的mAP大概高2到3个百分点,但推理速度慢三成。工业场景如果摄像头数量多、需要并发推理,速度和精度之间的平衡要慎重考虑。
如果你完全不要预训练权重,从零开始训练,那你的数据量至少得一万张以上才行。像我这种2000到3000张的量,还是要用预训练权重做迁移学习,收敛快太多。
3.2 训练超参数的设置逻辑
我用的一组参数是这样跑的:
python train.py \ --data pig_face.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --device 0img可以设成640或416。640精度更高,但显存占用大约翻倍;416的速度快、对小目标其实有损。猪脸在画面里通常不算特别小,但如果猪离摄像头远,脸可能只占几十个像素,这种属于小目标场景,推荐保持640。
batch取决于显存大小。8G显存跑yolov5s、640分辨率,batch=16刚好能压住,如果爆显存就降到8。这里有个反直觉的经验:不是batch越大越好,batch太大会让模型对猪脸这种差异很大的个体产生“平均脸”倾向,收敛后的框会偏保守。
epochs我设100。到第70轮左右mAP基本就不涨了,但多训练30轮可以让模型的稳定性更好,验证集上的波动更小。训练过程中记得开--patience,如果连续多少轮没提升,自动早停,能省不少时间。
3.3 训练过程如何观察是否收敛
训练的时候不要只盯着一张loss曲线看。我习惯同时看三个指标:
train/box_loss:边界框回归损失,平稳下降是正常;val/box_loss:验证集上的对应损失,如果它上升而train还在下降,就是过拟合信号;metrics/mAP_0.5:验证集上IOU阈值0.5时的平均精度,这是最直观的模型好坏。
yolo-v5在训练完会自动在runs/train/exp目录里生成results.png,这张图汇总了损失曲线和PR曲线,基本一眼就能判断模型状态。正常收敛的模型,在训练后半段mAP曲线是缓慢上升并趋于平稳的,而不是持续抖动。
我这次训练到60轮时val的box_loss开始震荡,但mAP还在缓慢爬升,说明模型还在学习细节。最后30轮没有再出现过拟合,整体训练过程是健康的。
3.4 我用到的数据增强手段
yolo-v5自带了一套增强参数,在hyp.scratch-low.yaml里,默认就很好用。我对猪脸场景调了两个地方:
hsv_h: 0.015增加时色相轻微偏移,数据里有大量不同色温的灯照,调大一点让模型对颜色变化不那么敏感;degrees: 10.0轻微旋转,猪的头会歪,10度足够覆盖姿态变化。
默认设置里有一个mosaic增强,会把四张图拼成一张喂进网络。这个对检测遮挡和拥挤场景特别有效,等于强迫模型学会在复杂背景下找猪脸。训练前20轮mosaic会降低训练稳定性,但整体收益是正向的。
4. 训练过程中的评价标准:别只盯着mAP一个数
4.1 mAP是什么,怎么读
目标检测训练过程中的评价标准,最核心的就是mAP(mean Average Precision)。简单理解:对每个置信度阈值都计算一组precision和recall,然后画一条PR曲线,曲线下的面积就是AP,所有类别平均一下就是mAP。
在yolo-v5的输出里你会看到两个常用指标:
mAP_0.5:IOU阈值0.5时的AP。这是个比较宽松的评价标准,框只要大致对就算命中;mAP_0.5:0.95:IOU阈值从0.5到0.95,每隔0.05算一次再取平均。这个标准严格得多,要求框的位置非常准确。
做猪脸检测时,我主要看mAP_0.5,因为下游的个体识别任务只需要把整张脸框住,不需要像素级精确的边缘。mAP_0.5:0.95如果低于0.5也不用太慌,这是正常水平;如果你能把它做到0.6以上,说明框的位置已经非常精准。
4.2 Precision和Recall的取舍
Precision(查准率)表示模型预测出来的猪脸有多少是对的;Recall(查全率)表示真正的猪脸有多少被找出来了。
猪脸检测和通用目标检测有个不同点——漏检和误检的代价不一样。比如自动喂食场景,漏检一头猪可能导致它吃不到料,这个代价很高;但误检最多就是在屏幕上多画一个框,影响可接受。所以我调参时会倾向于提高Recall,即便Precision稍微降低一点也行。
具体操作上,推理时把conf_thres从默认的0.25降到0.15,能把更多低置信度的候选框捞回来。作为代价,假阳性的框也会变多,需要结合场景判断。另一个办法是在训练后期单独用--hyp参数调整cls_pw,让分类损失的权重更高,模型对猪脸和非猪脸的区分更严格。
4.3 F1曲线和Confidence阈值
yolo-v5在验证后还会画一张F1曲线和一张confidence曲线。F1是precision和recall的调和平均,综合反映模型质量。而confidence曲线展示的是不同置信度下precision和recall的变化趋势——两条线交汇的地方,通常是F1最高的位置。
我在部署时用这个策略:读F1曲线找到最佳置信度阈值,把它写进推理脚本。比如这次训练后F1峰值对应confidence=0.31,那部署时就用0.31而不是默认的0.25或0.5。这是个很简单但很有效的技巧,网上教程很少提。
4.4 混淆矩阵:看看猪脸被错认成什么
yolo-v5验证结果里还有一份confusion_matrix.png。我原以为只有单类目标,混淆矩阵没什么可看的。实际上,单类目标的混淆矩阵能看到“猪脸被检测成背景”的比例,也就是漏检的分布。
我第一版模型训练完,混淆矩阵里大约有8%的猪脸被分类成背景。结合图片排查后发现问题集中在一类图片上:猪在泥地里打滚后,脸上覆盖大量污泥,纹理和背景几乎一样。后来我在数据里单独补充了50多张脏脸猪的图片,再训练,混淆矩阵中的漏检率降到了2%以下。
5. 训练完成之后:本地模型加载与实时推理
5.1 保存出来的pt权重文件
训练结束后,runs/train/exp/weights/目录下会生成两个文件:best.pt(验证集上mAP最优的权重)和last.pt(最后一轮的权重)。部署时一定用best.pt,不要用last.pt。last看似训练得更多,但可能存在过拟合,实际推理效果反而差。
我对best.pt做过一次剪枝和量化实验——用torch.quantization把FP32转成FP16,模型文件从30MB缩小到16MB,推理速度提升了约30%,精度几乎没损失。如果你部署在Jetson这种边缘设备上,强烈建议做FP16量化。
5.2 Python推理代码:加载本地模型
加载训练好的本地模型并推理,代码并不复杂。我用的是yolo-v5官方的推理接口,它会自动读取训练时保存的类别名称,不需要手动指定:
import torch import cv2 import numpy as np # 加载本地模型 model = torch.hub.load('D:/yolov5', 'custom', path='D:/pig-face-detection/runs/train/exp/weights/best.pt', source='local') model.conf = 0.31 # 由F1曲线确定的最佳置信度 model.iou = 0.45 # NMS的IoU阈值,默认即可 # 读取一张测试图片 img = cv2.imread('test_pig.jpg') img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 推理,返回的是pandas DataFrame results = model(img_rgb, size=640) # 提取检测框和置信度 boxes = results.xyxy[0].cpu().numpy() for box in boxes: x1, y1, x2, y2, conf, cls = box label = f"pig_face {conf:.2f}" cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(img, label, (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite('output.jpg', img) print(f"检测到 {len(boxes)} 个猪脸")注意torch.hub.load的source参数必须设置为'local',否则会去GitHub拉取远程模型,导致加载失败或者加载到不匹配的权重。这里踩坑的人非常多,务必记住。
5.3 实时摄像头/视频流推流检测
如果拿到的是视频流而不是单张图片,推理框架稍微改一下,加一个循环读取帧的过程。要注意的是,摄像头帧率和模型推理速度如果不匹配,会导致画面延迟累积。
import torch import cv2 model = torch.hub.load('D:/yolov5', 'custom', path='D:/pig-face-detection/runs/train/exp/weights/best.pt', source='local') model.conf = 0.31 cap = cv2.VideoCapture("rtsp://192.168.1.100:554/stream") while True: ret, frame = cap.read() if not ret: break frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = model(frame_rgb, size=640) boxes = results.xyxy[0].cpu().numpy() for box in boxes: x1, y1, x2, y2, conf, cls = box cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(frame, f"pig {conf:.2f}", (int(x1), int(y1)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) cv2.imshow("pig detection", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()如果你在Jetson Nano或者树莓派上跑,可以把size从640降到320,推理速度能翻倍,代价是检测小目标的能力会下降。这个取舍根据自己的摄像头安装距离来定。
5.4 ONNX导出与跨平台部署
训练好的pt文件只能在PyTorch环境里运行,实际工业部署时经常要脱离这个环境,比如Android端或者用C++的推理框架。yolo-v5自带导出脚本:
python export.py --weights runs/train/exp/weights/best.pt --include onnx --opset 12导出后会生成best.onnx,用ONNX Runtime就可以加载推理,好处是部署端不需要装PyTorch。在我接手过的项目里,服务端用ONNX Runtime做推理的占大多数,因为内存占用小、启动快、没有GPU也能用CPU跑。
导出的ONNX模型再配合onnxruntime做推理,推荐直接写一个独立的推理类,把加载模型和预处理封装起来,方便后续在Flask服务或者边缘设备上调用。
6. 实际落地中绕不开的坑
6.1 夜间红外光和猪脸反光
养殖场通常晚上开的是红外灯或低照度灯,画面整体偏暗且色调单调。我最初训练模型时全部用白天自然光图,晚上测试时mAP直接掉到0.5以下。
解决办法不是去调模型,而是在数据层面想办法:专门挑傍晚和夜间的视频帧补充进训练集。我先后补了400张夜间图,权重位置没有做任何改动,夜间mAP就回到了0.83。这说明目标检测模型对域差异非常敏感,训练数据的光照分布必须覆盖使用场景的光照分布。
6.2 重叠猪只的漏检
猪挤在一起时,脸部重叠的概率很高。如果两头的脸重叠面积超过50%,我的模型经常会只框出其中一头。这种情况单靠yolo-v5本身比较难根治,我用的折中方案:
- 把
model.iou从0.45调低到0.3,NMS会更宽容,允许更多重叠的框保留下来; - 在数据里刻意标注了大量重叠场景,让模型学到“即使被挡住一部分,也是一头猪”。
这样调整之后,重叠场景的漏检率从18%降到了9%,虽然还是会漏,但至少不会完全忽略。
6.3 错误报告常见的坑
如果你训练时遇到报错,先说三个最容易出现的:
- 加载本地模型时报错“No such file or directory”,检查weights路径是否写绝对路径;
- 训练时提示“Dataset not found”,检查
pig_face.yaml中path字段的路径,这个路径一旦包含中文,yolo-v5有时会识别不了,建议项目目录和数据集路径全用英文; - 显存不足OOM,不要盲目调低batch,先检查是否开着
--workers太多,线程数比CPU核心数高会挤爆内存,触发OOM。
如果遇到别的报错,把报错信息复制到搜索框里,在yolo官方仓库的issue里找,基本都能找到答案。绝大多数报错问题在网络的讨论区里都有现成解决方案。
6.4 模型在远处猪只上的表现
摄像头装在圈舍墙角时,远处猪只的像素面积很小,脸可能只占40×40像素。我第一版模型在近处猪上表现很好,但mAP一到远距离就崩了。检查后发现,训练集中2米以内的近景图占了大半,远处的小目标样本不足。
后面我在数据增强中把原图随机裁剪放大,强迫模型看到更多小尺寸目标,同时增加了远景标注图的数量。重新训练后,远距离场景的召回率提升明显。如果你也在做类似养殖场景,一定要保证训练集里有各种拍摄距离下的猪脸,不能全是近距离大头照。
7. 训练时的资源占用与硬件选择
7.1 GPU配置经验
train.py默认会用device=0也就是第一块GPU。如果你机器上没有独立显卡,纯CPU也能训练,就是速度慢得让人崩溃,100轮下来可能得好几天。建议至少要一块RTX 3060级别以上的显卡,显存8GB以上,训练时间大概在6到8小时。
如果你只有CPU,也不是完全不能跑。把--batch降到4、--img降到416、--epochs减到50,模型依然能收敛到能用的程度,只是精度会差一些。对验证算法可行性来说足够了,真要上生产还是建议配GPU。
7.2 显存不足优化三板斧
8G显存跑yolov5m报OOM的话,我会按顺序优化:
--batch 8或者--batch 4,线性降低显存占用;- 开
--amp混合精度训练,这个选项在v5里默认开启,如果关了就重新打开,能省一半显存; --img 512,分辨率降一档,猪脸检测精度损失可以接受。
这三招用完,6G显存的卡也能勉强跑yolov5m。再不行就老实换回s版本。
7.3 训练时间评估
在我使用的GPU上(RTX 3060,12GB显存),100轮训练大概用时5小时40分钟。每次验证大概占用8分钟。跑到第70轮后损失基本平稳,后续30轮主要是让精度更稳定。如果时间紧张,--epochs 70也足够得到一个能用的模型。
实际项目中我经常用早停机制,如果验证集mAP连续20轮没有提高,直接停止。这样可以避免不必要的计算资源和时间浪费。
8. 后续扩展方向
8.1 从检测到识别:猪只个体ID
检测到猪脸只是第一步。下游要做的就是个识别,判断“这个脸是哪头猪”。我建议用ReID的思路:检测模型输出猪脸区域,然后用一个轻量级分类网络对脸部图像做embedding提取,再用向量检索匹配个体ID。整体架构清晰,并且检测模型可以直接复用。
8.2 与yolo-v8小目标检测头的对比
后来我也在同样的猪脸数据集上试过yolo-v8的p2小目标检测头,最终mAP确实比v5高了一点,大概高了2个百分点,但推理速度慢了近25%。对于当前这个猪脸场景,v5的表现已经满足项目需求,所以我暂时没有迁移到v8。如果你的问题里小目标猪脸占比特别高,可以试试p2检测头的版本。
8.3 部署到边缘盒子
模型最终在Jetson Nano上部署,FP16量化后推理速度大约28ms每帧,大概能跑到35帧每秒,满足实时性需求。如果追求更高的帧率,可以在TensorRT上做int8量化,速度可以再快一倍,但需要小心精度回退,建议量化后用实际场景数据重新验证。
这套基于yolo-v5的猪脸目标检测方案,从数据准备到模型部署,每个环节都有大量细节值得打磨。如果你也是第一次做类似项目,我的建议是先把数据集质量做好,这是性价比最高的一步。数据靠谱了,后面的模型训练和部署流程都是水到渠成。中途如果卡在某个报错上,不妨停下来看看路径、显存、数据集这三个最基础的地方,很多时候问题出在最简单的位置。根据我个人的实操经验,目标检测项目的成败,八成由数据和配置决定,模型结构本身的反而不是最关键的。希望这篇内容能让你少走一些弯路。
本文还有配套的精品资源,点击获取