ARTICLE DETAIL

资讯详情

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

猪行为识别数据集实战:从COCO标注到YOLOv8训练与落地避坑

猪行为识别数据集实战:从COCO标注到YOLOv8训练与落地避坑 简介这份猪圈猪行为识别数据集面向智慧养殖、动物行为分析与计算机视觉方向的研究者和开发者可用于构建猪只日常行为自动监测模型识别喝、吃、睡觉、站立等典型动作平均正确识别率达92.6%适合目标检测与行为分类任务的训练与验证。资源包共1275个文件其中1272张jpg图像构成主要样本另有3个json标注文件采用coco json格式可直接对接主流检测框架压缩包整体约85.57MB体积轻便便于快速部署实验。目前已有214人学习下载具备一定参考热度。图像覆盖多段视频抽帧场景标注信息完整读者可据此完成数据加载、模型训练、精度复现与行为统计等流程也可作为养殖场智能化改造的算法验证素材帮助缩短从数据准备到模型落地的周期。1. 猪圈里的猪行为识别数据集1272 张图、92.6% 准确率背后能落地什么猪舍里最耗人力的活是盯着猪看。一头母猪一天采食、饮水、躺卧、站立、拱地、打架这些行为直接关联到饲喂策略、发情鉴定、疾病预警和栏舍密度评估。过去靠饲养员拿本子记一个人管几百头猪记到第三栏就开始凭印象。现在换成摄像头加模型问题就变成拿什么数据训、训出来能不能用、92.6% 这个数字在真实猪圈里还剩多少。这个数据集就是冲这个场景来的1272 张猪圈实拍图标注了喝、吃、睡觉、站立等行为类别标注格式是 coco json官方给出的平均正确识别率在 92.6%。它解决的不是“有没有数据”的问题而是“小样本、强遮挡、光照乱”的猪圈场景下怎么快速把行为识别跑起来。适合两类人一类是想做智慧养殖、动物福利监测的算法工程师另一类是手里有猪场资源、想验证行为识别到底值不值得投入的从业者。1272 张不算大但 coco json 这个格式意味着它能直接进主流检测/分类框架不用先花两天写转换脚本。2. 从 coco json 到可训练张量数据到底长什么样2.1 先看清 1272 张图的标注结构再动手coco json 不是“一个标签文件”那么简单它是一套带 images、annotations、categories 三个核心数组的字典结构。猪行为识别数据集里images 记录每张图的文件名、宽高、idannotations 记录每个标注框的 bbox、类别 id、所属图片 idcategories 记录行为类别名和 id。喝、吃、睡觉、站立这些行为在 categories 里就是几个整数 id 对应几个字符串。拿到数据第一件事不是写训练脚本是先把 json 读出来数一遍。我一般会先确认三件事图片数量和 json 里 images 数量是否一致、每个类别的框数分布、有没有宽高为 0 的脏框。1272 张图如果某个行为只有几十个框那这个类别训出来大概率是玄学得靠数据增强或者类别重加权补。import json from collections import Counter with open(pig_behavior/annotations/instances.json, r, encodingutf-8) as f: coco json.load(f) print(图片数:, len(coco[images])) print(标注框数:, len(coco[annotations])) print(类别:, [(c[id], c[name]) for c in coco[categories]]) # 统计每个类别的框数判断类别是否失衡 cat_counter Counter(a[category_id] for a in coco[annotations]) id2name {c[id]: c[name] for c in coco[categories]} for cid, cnt in cat_counter.most_common(): print(f{id2name[cid]}: {cnt} 框) # 检查脏框宽或高为 0 的标注 bad [a[id] for a in coco[annotations] if a[bbox][2] 0 or a[bbox][3] 0] print(脏框数量:, len(bad))这段代码的逻辑很直白先加载 json再分别统计图片、标注、类别最后用 Counter 看类别分布。参数上唯一要注意的是encodingutf-8coco json 里类别名如果是中文不指定编码在 Windows 上会直接报错。脏框检查不能省bbox 宽高为 0 的框送进训练会在计算 loss 时产生 NaN这种翻车现场我见过不止一次。2.2 把 coco 标注转成 YOLO 格式的脚本与四个边界坑虽然数据集原生是 coco json但实际训练时很多人会用 YOLOv8 这类框架它吃的是每张图一个 txt 的 YOLO 格式。转换本身不难难在边界处理。coco 的 bbox 是[x_min, y_min, width, height]绝对像素YOLO 要的是[class_id, x_center, y_center, width, height]归一化到 0~1。四个坑分别是坐标越界、图片名带路径、类别 id 不连续、空标注图。import json, os from PIL import Image with open(pig_behavior/annotations/instances.json, r, encodingutf-8) as f: coco json.load(f) img_info {img[id]: img for img in coco[images]} # 建立 category_id 到 0 起始连续 id 的映射YOLO 要求类别从 0 开始 cat_ids sorted(c[id] for c in coco[categories]) cat2idx {cid: i for i, cid in enumerate(cat_ids)} out_dir pig_behavior/labels os.makedirs(out_dir, exist_okTrue) # 按图片聚合标注 from collections import defaultdict per_img defaultdict(list) for a in coco[annotations]: per_img[a[image_id]].append(a) for img_id, anns in per_img.items(): info img_info[img_id] w, h info[width], info[height] name os.path.splitext(os.path.basename(info[file_name]))[0] lines [] for a in anns: x, y, bw, bh a[bbox] # 裁剪越界坐标防止归一化后超出 0~1 x max(0, min(x, w)) y max(0, min(y, h)) bw min(bw, w - x) bh min(bh, h - y) if bw 1 or bh 1: continue # 过滤掉裁剪后过小的框 xc (x bw / 2) / w yc (y bh / 2) / h lines.append(f{cat2idx[a[category_id]]} {xc:.6f} {yc:.6f} {bw/w:.6f} {bh/h:.6f}) with open(os.path.join(out_dir, name .txt), w) as f: f.write(\n.join(lines))逻辑说明先建cat2idx把原始类别 id 映射成从 0 开始的连续整数这是 YOLO 的硬要求不映射训练时类别索引会错位。然后按 image_id 聚合标注逐框做坐标裁剪和归一化。参数上bw 1 or bh 1这个阈值是经验值小于 1 像素的框在 640 输入下基本是噪声留着只会拉低精度。:.6f保留六位小数够用且不会让文件膨胀。注意转换完一定要抽查几张图的可视化结果把 YOLO txt 画回原图看框有没有偏移。我踩过的坑是 coco 的 bbox 有人写成[x_min, y_min, x_max, y_max]直接套公式会得到一堆错位框肉眼看 json 根本发现不了。2.3 训练前的数据划分与增强策略1272 张图按 8:1:1 划分训练集约 1017 张验证集和测试集各 127 张左右。这个量级下验证集只有一百多张单次评估的波动会很大所以别只看一轮的 92.6%要跑多次取平均。划分时按图片随机分不要按视频帧分否则同一头猪的相邻帧会同时进训练和验证准确率虚高。增强策略上猪圈场景的核心干扰是光照变化和遮挡。我一般会开 HSV 色调饱和度扰动、随机亮度对比度、马赛克增强和随机遮挡。但要注意猪的行为和姿态强相关上下翻转要慎用翻转后“站立”可能变得不像站立水平翻转相对安全。旋转角度控制在 ±10 度以内大角度旋转会让躺卧和站立的边界模糊。3. 用 YOLOv8 把猪行为识别跑起来配置、训练与评估3.1 环境准备与 data.yaml 的关键字段YOLOv8 的环境用 pip 装就行pip install ultralytics。装完先确认版本不同版本对 data.yaml 字段的容忍度不一样。数据集目录建议按images/train、images/val、labels/train、labels/val组织YOLO 会自动根据 images 路径推导 labels 路径。# pig_behavior/data.yaml path: /data/pig_behavior train: images/train val: images/val test: images/test names: 0: drink 1: eat 2: sleep 3: stand 4: walkpath是数据集根目录train/val/test是相对路径。names的键必须从 0 开始连续和前面转换脚本里的cat2idx完全对应这里错一个训练出来的类别名就全乱。如果数据集里还有“拱地”“打架”等行为按同样规则往后加。字段名不要自己发明YOLOv8 只认这几个。3.2 训练命令与必调参数yolo detect train \ data/data/pig_behavior/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience30 \ augmentTrue \ hsv_h0.015 hsv_s0.7 hsv_v0.4 \ degrees10.0 translate0.1 scale0.5 \ fliplr0.5 flipud0.0 \ mosaic1.0 \ projectruns/pig \ nameexp1参数逐个说modelyolov8s.pt选 s 而不是 n是因为 1272 张图量小n 容易欠拟合s 在精度和速度间更稳。epochs150配合patience3030 轮没提升就早停省时间。imgsz640是默认值猪圈图如果分辨率高、猪只小可以提到 960但显存要够。lr00.01是初始学习率小数据集别调太大否则 loss 震荡。lrf0.01是最终学习率因子配合余弦退火。增强参数里flipud0.0就是前面说的上下翻转禁用degrees10.0控制旋转幅度mosaic1.0开满小数据集靠它扩样本。训练过程中重点看三个指标box_loss 是否稳定下降、mAP50 是否在验证集上持续爬升、cls_loss 有没有突然跳变。cls_loss 跳变通常意味着某个类别样本太少模型在类别间反复横跳。3.3 评估 92.6% 这个数字在你自己数据上的含义官方给的 92.6% 是平均正确识别率但你要清楚它是在什么口径下算的。是分类准确率还是检测 mAP是单帧还是视频级投票拿到自己的数据后用yolo detect val跑一遍看每个类别的 mAP50 和混淆矩阵。yolo detect val \ modelruns/pig/exp1/weights/best.pt \ data/data/pig_behavior/data.yaml \ imgsz640 \ conf0.25 \ iou0.5 \ plotsTrueconf0.25是置信度阈值低于它的框不算。iou0.5是 NMS 的 IoU 阈值。plotsTrue会生成混淆矩阵和 PR 曲线。重点看混淆矩阵里“站立”和“行走”有没有大量互混这两个行为在静态图上本来就难分。如果“睡觉”被大量误判成“站立”那说明躺卧姿态的样本多样性不够得补数据或加姿态相关的增强。注意验证集上的 92.6% 和真实猪圈里的表现是两回事。真实场景有夜间红外、猪只重叠、镜头脏污这些在 1272 张图里未必覆盖全。上线前一定要留一段自己猪场的视频做端到端测试别拿验证集数字直接汇报。4. 猪行为识别落地避坑5 个血泪教训4.1 类别失衡导致“睡觉”一家独大现象训练完发现模型几乎把所有框都预测成“睡觉”其他行为召回率极低。原因猪一天里躺卧时间最长数据集里“睡觉”框数远多于“喝”“吃”模型学到的最省力策略就是全猜多数类。解决先统计类别分布对少数类做过采样或复制粘贴增强训练时用类别权重或者在 loss 里对少数类加权。YOLOv8 本身不直接暴露类别权重可以通过调整数据集采样比例间接实现。4.2 标注框把整头猪和头部混为一谈现象同一个行为类别里有的框标整头猪有的只标头部模型学出来的框大小忽大忽小mAP 上不去。原因多人标注时标准不统一。解决拿到数据先可视化抽查统一标注规范——行为识别建议标整头猪的躯干范围因为行为是全身姿态的体现。发现不一致的框要么重标要么剔除。4.3 验证集和训练集来自同一段视频现象验证集准确率 95%换一段新视频掉到 70%。原因按帧随机划分相邻帧高度相似等于变相泄漏。解决按视频或按时间段划分确保验证集的猪只、栏舍、光照条件和训练集有差异。1272 张图如果来自少数几段视频划分时要以视频为单位整体分。4.4 输入分辨率与猪只尺度不匹配现象小猪只漏检严重大猪只框不准。原因猪圈摄像头装得高猪在画面里占比小640 输入下小目标特征丢失。解决提高输入到 960 或 1280或者用切片推理把大图切块分别检测再合并。代价是推理变慢要权衡。4.5 忽略红外和夜间场景现象白天准确率正常夜间全瞎。原因数据集全是白天可见光图模型没见过红外成像的纹理。解决如果猪场有夜间监控需求必须补红外数据或者用图像增强模拟红外风格做域适应。没有夜间数据就敢上夜间场景这是最典型的翻车。5. 把 92.6% 再往上推小样本下的进阶技巧与验证习惯1272 张图想再往上走靠堆 epoch 没用得从数据和推理两头抠。数据这头我一般会做两件事一是用训练好的模型在无标注的猪场视频上跑推理把高置信度的预测框人工复核后加进训练集这是最省力的半自动扩样本二是针对易混类别做定向增强比如“站立”和“行走”互混就专门裁出这两类的图做对比训练。推理这头单帧检测抖动大行为识别本质是时序问题。一个实用技巧是对同一头猪连续多帧的检测结果做投票比如 15 帧窗口内多数票决定行为类别抖动会明显下降。如果要做实时用跟踪算法给每头猪分配 id再按 id 聚合行为序列这样“吃”这个行为不会因为中间一帧误判就断掉。验证习惯上我坚持留一个“脏测试集”从真实猪场随机截一段没参与任何训练的录像人工标 100 帧专门用来打脸。每次模型更新都在这上面跑一遍看真实场景的 mAP 有没有提升。这个习惯帮我避免过好几次“验证集涨了、上线崩了”的尴尬。# 多帧投票的简化逻辑 from collections import Counter, deque class BehaviorVoter: def __init__(self, window15): self.window window self.buffers {} # track_id - deque of behavior labels def update(self, track_id, behavior): if track_id not in self.buffers: self.buffers[track_id] deque(maxlenself.window) self.buffers[track_id].append(behavior) # 多数票 return Counter(self.buffers[track_id]).most_common(1)[0][0]这段逻辑的核心是给每个跟踪 id 维护一个固定长度的行为队列每次新检测进来就投票。window15是经验值太小压不住抖动太大行为切换会延迟。实际部署时跟踪 id 的稳定性直接决定投票效果id 频繁跳变的话投票反而会引入错误。最后说个我自己的教训别迷信单一数字。92.6% 是个起点不是终点。真正决定这套东西值不值得做的是它在你自己猪场里连续跑一周饲养员愿不愿意看、看了能不能减少巡栏时间。我现在的习惯是每上一个行为识别模型先让一线饲养员用三天收集他们“觉得不准”的片段那些片段比任何指标都值钱。希望帮到你。本文还有配套的精品资源点击获取
返回列表