
简介基于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设为1names只放一个类名。这里的类名不影响训练但会影响推理时显示的文字。另一个容易被忽略的字段是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分辨率batch16刚好能压住如果爆显存就降到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是什么怎么读目标检测训练过程中的评价标准最核心的就是mAPmean Average Precision。简单理解对每个置信度阈值都计算一组precision和recall然后画一条PR曲线曲线下的面积就是AP所有类别平均一下就是mAP。在yolo-v5的输出里你会看到两个常用指标mAP_0.5IOU阈值0.5时的AP。这是个比较宽松的评价标准框只要大致对就算命中mAP_0.5:0.95IOU阈值从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峰值对应confidence0.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, pathD:/pig-face-detection/runs/train/exp/weights/best.pt, sourcelocal) 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, size640) # 提取检测框和置信度 boxes results.xyxy[0].cpu().numpy() for box in boxes: x1, y1, x2, y2, conf, cls box label fpig_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, pathD:/pig-face-detection/runs/train/exp/weights/best.pt, sourcelocal) 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, size640) 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, fpig {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.3NMS会更宽容允许更多重叠的框保留下来在数据里刻意标注了大量重叠场景让模型学到“即使被挡住一部分也是一头猪”。这样调整之后重叠场景的漏检率从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默认会用device0也就是第一块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 306012GB显存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的猪脸目标检测方案从数据准备到模型部署每个环节都有大量细节值得打磨。如果你也是第一次做类似项目我的建议是先把数据集质量做好这是性价比最高的一步。数据靠谱了后面的模型训练和部署流程都是水到渠成。中途如果卡在某个报错上不妨停下来看看路径、显存、数据集这三个最基础的地方很多时候问题出在最简单的位置。根据我个人的实操经验目标检测项目的成败八成由数据和配置决定模型结构本身的反而不是最关键的。希望这篇内容能让你少走一些弯路。本文还有配套的精品资源点击获取