1272张图实现92.6%识别率:YOLOv9猪行为识别数据集全解析 简介面向猪只行为识别与智慧养殖场景这份数据集以猪圈实拍图像为基础标注了喝、吃、睡觉、站立四类常见行为平均正确识别率可达92.6%既可直接用于YOLOv9目标检测模型的训练与验证也适合初学者接触行为识别任务时进行数据准备和模型调优练习。资源整体为zip压缩包共2000个文件包含1272个txt标注文件、727张jpg原始图像和1个yaml配置文件压缩包大小约85.86MB其中txt与jpg按图像一一对应yaml内定义了类别名称与路径加载到YOLOv9工程后即可使用。目前已有251人学习浏览对需要真实猪圈场景数据、希望节省采集与标注时间的用户来说可直接用于实验对比或模型迭代。基于视频帧提取的图像保留了不同时刻、不同圈舍环境下的猪只姿态涵盖多种光照与遮挡情况有助于提升行为检测模型的泛化能力也可作为其他畜禽行为识别项目的参考数据。1. 猪圈行为识别数据集的真相1272 张图如何支撑 92.6% 的平均识别率养猪查栏是笔辛苦账三百头猪挨个看哪头没吃、哪头一直趴着、哪头在饮水器前站太久全靠肉眼硬盯发现异常时往往已经掉膘两三天。这份猪行为识别数据集解决的就是这个痛点——1272 张从多个栏位监控视频抽帧的图片逐张标注出喝、吃、睡觉、站立四类行为直接采用 YOLOv9 标注格式平均识别率 92.6%。它不是演示效果的展示包而是能直接喂给训练脚本的现成数据。适合做智慧养殖算法验证的工程师、行为识别方向的毕设学生以及想用现成数据把 YOLOv9 全流程跑通再迁移到自己场景的人。2. 解构猪行为数据集YOLOv9 格式的目录、标注与行为边界2.1 从文件名读出数据来源与采集策略拿到资源第一步别急着解压训练先把文件名读一遍。这份数据集的图片命名是一个信息量很大的编码比如9_1_mp4-6_jpg.rf.020dcb2ff96b0599565b00043dfe8dc5.jpg拆开能读出三条关键信息。9_1是栏位编号对应一个具体的猪栏摄像头视角mp4-6表示这一帧取自第 6 段视频素材_jpg后缀说明原始采集是视频流后转成了静态帧rf.后面跟的 32 位十六进制哈希是 Roboflow 导出时生成的去重指纹。哈希的目的是给每一帧唯一的身份标识防止同一个画面在数据增强或反复导出中被重复计入。浏览完整目录会发现视频编号从0延伸到49栏位来源涵盖9_1、9_7、10_00三个视角说明数据不是单一猪栏的连续录像而是多栏位、多时间片的采样。这个多样性对训练极其有利——背景、光照、猪只密度都不同模型的泛化能力才有保证不会只认得某一个猪栏的瓷砖墙和食槽位置。从文件名还能推测采集节奏大量相邻编号的帧对出现在最终数据集里比如mp4-6和mp4-7同时存在但数量没有膨胀到几千张说明采集时做了均匀抽帧抽完又做了相似度去重。这种「先抽帧、再去重」的策略是行为识别数据集最常见也最稳妥的做法。2.2 YOLOv9 标注格式一行一个目标的归一化坐标YOLOv9 与 YOLOv5、YOLOv8 共用同一套 txt 标注规范这也是这份数据集能无缝喂进训练脚本的关键。每张 jpg 图片对应一个同名前缀的 txt 文件里面每一行代表一个目标框五个字段依次是类别 ID、目标中心点 x 坐标、中心点 y 坐标、目标框宽度、目标框高度后四个值全部除以图片宽高做了归一化取值在 0 到 1 之间。一份典型的标注文件长这样0 0.483211 0.310546 0.240625 0.333984 2 0.712500 0.583594 0.251563 0.443750第一行的类别 ID 是 0按数据集约定通常代表「喝」第二行类别 ID 是 2对应「睡觉」。后面的四个小数就是归一化后的定位参数。务必先找到数据集里的classes.txt或data.yaml确认 ID 映射关系我见过有人上来就训结果模型把睡觉全预测成了喝因为类别顺序搞反了。这种情况在推理阶段特别难排查因为损失函数照样收敛mAP 曲线照样下降。归一化坐标有个好处无论你最终训练输入尺寸用 640 还是 1280标注文件都不需要重新换算YOLO 系列训练脚本会自动把框映射到输入分辨率上。但这也带来一个检查盲区——你光看数字看不出框画得对不对强烈建议写个小脚本把框可视化回图片上眼见为实import cv2 img cv2.imread(9_1_mp4-6_jpg.rf.020dcb2ff96b0599565b00043dfe8dc5.jpg) h, w img.shape[:2] with open(9_1_mp4-6_jpg.rf.020dcb2ff96b0599565b00043dfe8dc5.txt, r) as f: for line in f: cid, cx, cy, bw, bh map(float, line.split()) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cid)), (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.imwrite(check_vis.jpg, img)这段代码把归一化坐标还原成像素坐标再画框。cx - bw / 2计算的是框左上角 xcy - bh / 2是左上角 y乘上实际宽高w、h完成反归一化最后用 OpenCV 的矩形和文字把目标框画出来。跑完随机抽二十张图人工过一遍重点看两件事框有没有完整包住整头猪而不是只包住头或半截身体框的边沿有没有压到旁边另一头猪。如果普遍存在框偏大的情况说明数据集的标注风格偏宽松训练时数据增强里的scale参数要收小一点否则预测框会在目标边缘来回抖。2.3 四类行为的精确边界定义行为识别最核心的工程问题不是模型结构而是行为边界怎么划。这份数据集把行为分成喝、吃、睡觉、站立四类类与类之间的界线有明确约定。喝的定义是猪嘴接触饮水器或头部明显下探朝向饮水器方向颈部前伸、嘴部动作连续吃的定义是嘴部进入料槽区域并伴随咀嚼动作头埋进槽里持续一段时间睡觉的定义是身体侧躺或卧姿、腹部贴地、没有明显肢体活动站立的定义是四肢支撑身体保持静止或缓步移动。实际标注时最纠结的边界情况是「猪站在料槽前低头闻」。按照数据集的标注逻辑这种情况归入站立而不是吃因为嘴部没有进入料槽、没有咀嚼动作行为识别的业务目标是找到真正在进食的个体闻一下不算进食信号。另一个模糊地带是「半卧半站」前腿跪地、后腿站立的过渡姿态数据集倾向归入睡觉的过渡态因为此时猪的活跃度已经明显下降。理解这套边界逻辑很重要你换到自己的猪场场景时栏位结构不同、料槽和饮水器位置不同边界定义大概率要跟着微调——比如自动料槽的猪嘴只要靠近就会被识别为吃那就得把「嘴部进入槽内」改成「在槽内停留超过 N 秒」。3. 从视频到训练集抽帧、清洗与数据划分的完整落地流程3.1 抽帧策略不要盲目均匀采样如果你手里只有监控视频想自己做一份同类数据集千万别直接拿 OpenCV 每隔 N 帧暴力抽一遍那样抽出来的帧高度相似几乎等效于只有十几张有效图像。常见做法是按行为片段抽帧先人工浏览录像标记出喝、吃、睡、站四类行为出现的连续时间段然后对每个片段分别采样。采样的帧率我一般从 6 帧每秒起步。监控原始素材普遍是 25 帧每秒采样到 6 帧每秒能保留猪头部动作的关键细节——猪喝水时嘴部是有明显节奏的扬动采稀了这种节奏就丢了再密上去又会造成大量相似帧。这份数据集的命名里mp4-6、mp4-7相邻编号成对出现说明作者用的就是类似手法同一段视频均匀降采样随后做相似度去重最终压缩到 1272 张有效帧。抽完帧第一件事是人工快翻一遍删掉三类废帧画面模糊的、猪群完全遮挡目标的、以及有人员或工具入镜的。人员入镜的帧危害最大模型会把「蓝色工作服」学成背景特征一旦换到无人的自动饲喂场景就掉精度。3.2 标注工具选型本地 LabelImg 还是在线 Roboflow做四分类目标检测标注工具选型直接影响效率和格式一致性。如果你对数据隐私没有强制要求直接在 Roboflow 上上传视频、在线抽帧、在线画框是效率最高的路径导出时勾选 YOLOv9 format拿到的就是这份数据集的同款结构图片 同名 txt 一个自动生成的data.yaml连目录划分都给你做好了。Roboflow 的去重指纹就是文件名里的哈希段也正是这么来的。如果你有私有化要求或网络受限本地用 LabelImg 完全够用。LabelImg 保存时选择 YOLO 格式生成的 txt 与 YOLOv9 完全兼容因为这个格式体系向后兼容。用 LabelImg 时有一个必须守住的规矩classes.txt里的类名顺序决定 ID 编号新增类别只能追加在文件末尾绝对不能插到中间否则已有标注的 ID 全部错位训练脚本读出来的全是错配标签而且不会报任何错。每标完一批我习惯写一行命令检查全部标注文件的完整性for f in labels/*.txt; do awk -F {if(NF!5 || $10 || $20 || $30 || $40 || $50) print BAD:, FILENAME, $0} $f; done这一行命令遍历所有标注文件检查每一行是否正好五列、是否有负数。五列是 YOLO 格式的硬性要求类别 ID 和四个坐标都不能是负值。如果有BAD:输出说明那个文件被误编辑过直接定位修复。批量检查在两百张图以上的项目里是刚需人工一个个开文件翻太容易看漏。3.3 划分 train/val/test按视频来源分组而非按帧随机1272 张图按 8:1:1 划成训练集、验证集、测试集是常规比例但划分方式有一个容易被忽略的坑必须先按视频来源分组再在组级别上做随机分配。如果直接对全部帧做随机划分同一段 mp4 的相邻帧会同时出现在训练集和验证集里模型等于提前背过了验证题的答案val 的 mAP 虚高 5% 以上换到真实视频流上立刻现原形。正确的做法是解析文件名里的mp4-*编号以「视频片段」为最小单位做分组。比如 50 段视频随机抽 40 段的全部帧进训练集5 段进验证集5 段进测试集保证同源的帧只出现在一个集合。这一步也是为什么 2.1 里强调保留文件名编号信息——它是你做分组划分的核心依据。Roboflow 导出的数据通常自带划分但建议拿到手后自己核对一遍尤其是那些跨视频来源的数据集。4. 用 YOLOv9 复现 92.6% 识别率训练配置、参数调优与评估4.1 环境准备与预训练权重选择训练 YOLOv9 用官方仓库最省心。YOLOv9 相比 v5、v8 的核心改进是引入了可编程梯度信息PGI和广义高效层聚合网络GELAN在相近参数量下能保留更多梯度信息对小目标行为检测的精度提升明显。这也是这份数据集选择 YOLOv9 格式作为基准的原因——它需要能扛住「猪头」这种小尺寸目标的检测压力。git clone https://github.com/WongKinYiu/yolov9.git cd yolov9 conda create -n pig python3.9 -y conda activate pig pip install -r requirements.txt pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121PyTorch 的安装参数要跟你的显卡驱动匹配cu121对应 CUDA 12.1驱动版本不够就换成cu118或者用 CPU 版跑训练——慢是慢但至少能跑通流程。显存决定你选哪份预训练权重8 GB 及以下用yolov9-c.pt这是中等规模的版本单卡勉强能塞进 batch size 816 GB 以上用yolov9-e.pt精度更高训练时间约多 40%。4.2 数据配置一行类名顺序都不能错在yolov9/data/目录下新建pig.yaml指向数据集的三个子集train: /home/user/pig_dataset/train/images val: /home/user/pig_dataset/val/images test: /home/user/pig_dataset/test/images nc: 4 names: [drink, eat, sleep, stand]路径要写到images目录YOLOv9 会自动去同级目录下找labels/下的同名 txt 标注。nc是类别数四类就写 4。names的列表顺序与标注文件的 ID 严格一一对应这里写错不会报错但训练完的混淆矩阵、PR 曲线全部错位等于白跑一轮。如果数据集的classes.txt顺序是drink, eat, sleep, stand这里就必须照抄。4.3 训练命令与关键参数逐个拆解python train.py \ --data data/pig.yaml \ --weights yolov9-c.pt \ --batch-size 16 \ --imgsz 640 \ --epochs 100 \ --device 0 \ --cache \ --patience 20参数逐一说明--batch-size 16是 16 GB 显存的中等配置8 GB 显存就降到 8batch size 太小会导致 BN 层的统计量不稳定模型收敛变慢--imgsz 640是输入边长猪在画面里占的面积普遍较大640 分辨率足够捕捉到嘴部动作不要盲目上 1280训练时长直接翻倍且容易过拟合--epochs 100对 1272 张图的数据量来说是合理的通常 60 轮以后 mAP 曲线就走平了--cache把全部图片预加载进内存能省三分之一到一半的训练时间前提是内存大于 16 GB--patience 20是早停参数连续 20 轮验证集 mAP 不提升就自动停止并保留历史上最好的权重。训练过程中要盯两个指标终端输出的train/box_loss和val/mAP0.5。box_loss 持续下降且中途没有突然反弹说明学习率和 batch size 配比正常mAP0.5 到了后期每轮涨幅低于 0.5% 就可以手动停了。我习惯在训练时顺手记录每轮 mAP 的变化曲线这样早停条件触发时能立刻判断是收敛了还是震荡了。4.4 评估指标92.6% 平均识别率的含义训练结束后用官方验证脚本评估python val.py \ --data data/pig.yaml \ --weights runs/train/exp/weights/best.pt \ --imgsz 640 \ --conf-thres 0.25 \ --iou-thres 0.5--conf-thres 0.25是置信度阈值低于 0.25 的预测框直接当背景丢掉--iou-thres 0.5是判断预测框是否命中真值框的 IoU 下限也就是 mAP0.5 的判定口径。数据集宣传的 92.6% 平均识别率指的就是四类行为各自的 mAP0.5 的算术平均。跑完验证脚本打开results.csv逐类看 AP通常「睡觉」和「站立」两类 AP 较高能达到 94% 以上「喝」和「吃」偏低因为嘴部是小目标姿态变化剧烈单帧里嘴是否接触饮水器往往只有几个像素的差异。如果某些类的 AP 低于 85%问题大概率出在标注边界不统一回到 2.3 的边界定义去复审标注而不是急着调模型。5. 避坑指南五个让猪行为模型翻车的典型问题5.1 睡觉与站立互相串类混淆矩阵一片红现象训练出来的睡觉和站立两个类PR 曲线都在 0.85 上下摇摆混淆矩阵里互相错分严重验证集 mAP 上不去。 原因趴卧时前腿跪地、躯干悬空的过渡姿态在 2D 图片上跟站立下蹲瞬间非常像标注员没有统一判定标准。 解决回到标注文件把两类边界重新对齐——腹部贴地、四肢弯曲算睡觉躯干离地、四肢支撑算站立。重标后用修正的标注重新训练一般能各涨 2% 到 3% 的 AP。这种问题最好在标注阶段就定成团队规范写进标注说明文档不然多人协作时各标各的。5.2 喝与吃边界模糊验证集虚高但实时推理崩现象验证集 mAP0.5 显示 93%接上实时视频流后猪只是站在料槽前低头没吃也被框成「吃」。 原因标注阶段大量「低头闻料槽」的画面被划进「吃」模型学到的是「头在料槽上方就等于吃」的假规律。 解决按数据集的边界定义嘴部不入槽、无咀嚼动作都只能算站立。先把标签里所有「头在槽上方但嘴未入槽」的样本重新归类再用训练好的模型在测试视频上预测一轮找出置信度在 0.4 到 0.7 之间的模糊样本人工复核——这个置信度档位最容易暴露标注噪声。5.3 夜间红外光照下漏检率陡增现象白天场景 mAP 92% 以上切到夜间红外监控睡觉类漏检率 30%直立行走的猪在灰度图里几乎框不出来。 原因1272 张图大量来自白天或灯光充足的栏位训练分布里压根没有红外灰度帧模型没见过这种成像特征。 解决如果部署环境有夜班需求必须在训练集里补入红外样本。做法是拍 200 张左右的夜间红外帧按 2.3 的边界定义补标然后用现有权重做冻结微调——冻结前 10 层骨干网络只更新检测头训练 30 个 epoch 就停。全量重训会把白天的性能稀释掉冻结微调是性价比最高的路径。5.4 训练集和验证集泄漏val 指标虚高到可疑现象验证集 loss 比训练集 loss 还低PR 曲线平滑得不自然mAP 冲到 96% 以上。 原因数据划分时直接对全部图片做随机切分同一个视频的相邻帧同时进了训练集和验证集模型等于默写考题。 解决回到 3.3 的分组划分方案按视频编号为最小单位重分三集。划分完做一个简单的相似性检查把验证集每张图在训练集中找最相似的帧计算结构相似度如果出现相似度高于 0.9 的配对说明两个集合间仍然存在泄漏需要调整分组策略。5.5 早停触发但保存的 best 权重不是最优 mAP现象训练跑到第 78 轮触发早停脚本说保存了best.pt但拿这个权重验证 mAP 只有 80%比中间某轮明显低。 原因YOLOv9 的早停逻辑默认监控验证集 loss 而不是 mAPloss 最低的轮次并不一定对应 mAP 最高。 解决训练结束后不要急着用best.pt打开runs/train/exp/results.csv找到metrics/mAP_0.5这一列的最大值对应的 epoch去weights/里找那一轮的last.pt转成部署权重。从那以后我每次训完都会扫一遍 results.csv 再谈精度不能只看脚本说 best 就信。6. 部署进阶时序平滑、ROI 联动与行为验证技巧单帧推理在连续视频流上会暴露一个大问题行为预测在帧与帧之间来回闪烁上一帧是「喝」下一帧成了「站立」再下一帧又变回「喝」。原因是单帧模型没有时间记忆猪喝水时的抬头换气动作在 2D 画面上确实和站立瞬间极像。我的做法是在推理输出端加两道后处理不折腾模型本身。第一道是滑动窗口去抖维护一个长度 5 的窗口把最近 5 帧的行为预测放进去最终输出取众数。连续 5 帧里 4 帧预测是睡觉这一秒就输出睡觉偶尔一帧预测成站立不会影响最终结论。窗口长度太短去抖效果差太长会掩盖真实的行为切换——试验下来 5 帧在 25 帧每秒的视频里对应 0.2 秒的延迟体感可以接受。第二道是区域 ROI 联动把料槽和饮水器的位置预先画成矩形区域推理时校验行为输出和位置的关系。头部中心点在料槽 ROI 之外却输出「吃」的预测直接丢弃重判嘴部在饮水器 ROI 外却输出「喝」同理。这道校验能把不少单帧误判挡在业务逻辑之外成本几乎为零。验证这套链路是否有效我习惯统计行为切换次数把一段 10 分钟测试视频逐帧送进模型记录行为输出的切换点数量。不接平滑逻辑时切换次数通常在每分钟 30 次左右接上窗口和 ROI 之后应降到每分钟 5 次以内。同时抽查平滑后的输出有没有把短促的「喝水后抬头换气」误判成站立——如果这类误判变多说明窗口长度太激进调到 3 帧重新测一轮。这套流程走顺再交给业务端模型才算真正落地。从那以后我每次做行为识别数据集都强制走一遍分组划分、标注边界复核和后处理验证缺一项都不敢上线。希望帮到你。本文还有配套的精品资源点击获取