猪行为识别数据集工程处理:COCO标注解析与YOLOv8训练实战

发布时间:2026/9/14 23:36:23
猪行为识别数据集工程处理:COCO标注解析与YOLOv8训练实战 简介猪圈环境下猪行为识别数据集聚焦智慧养殖与计算机视觉应用场景适合从事深度学习目标检测或动物行为分析方向的开发者、研究人员与相关专业学生。数据集中图像均采集自猪圈实际监控画面共计1272张JPG图片配套3个JSON文件采用COCO JSON格式标注覆盖喝、吃、睡觉、站立等常见行为类别可直接投入目标检测、姿态估计或行为识别模型的训练与结果验证。根据作者提供信息该数据集在相应任务上的平均正确识别率约92.6%说明标注质量与模型适配度较为理想对算法调优和实验对比有实际帮助。资源包整体包含1275个文件压缩后大小约85.57MB文件组织简洁图片与标注一一对应便于筛选使用。目前已有213人学习使用适合智慧养殖、行为分析等课题研究及需要公开实测数据集进行验证的开发者。1. 猪圈行为识别从监控视频帧到COCO标注数据集的工程路径一个标准猪栏装两台摄像头每天产出的视频按小时计量人工盯着屏幕判断猪在喝水、吃料还是睡觉既费眼又费人。行为识别数据集要做的事就是把这四类日常行为变成可训练、可评估、可部署的标注数据。这套包含1272张图片、以COCO JSON格式标注的猪行为数据集平均正确识别率在92.6%覆盖猪场内最高频的喝、吃、睡觉、站立四类行为适合用作检测模型的训练集、迁移学习基底或边缘端行为统计的验证数据。对做智慧养殖或视觉检测的工程师来说关键问题不是拿到图片而是标注结构怎么读、怎么转成训练格式、类别分布存在什么坑、部署时边界条件怎么处理。2. 数据集解剖1272张图像、四类行为与COCO JSON标注结构2.1 数据来源与预处理从mp4连续帧到筛选图片数据集文件名保留了原始来源信息例如9_1_mp4-10_jpg.rf.*.jpg、10_00-1-1-_mp4-48_jpg.rf.*.jpg这种命名结构来自Roboflow导出其中9_1_mp4-10表示第9栋第1栏的视频第10帧.rf.后是一段随机哈希用于版本追踪和去重。mp4段说明原始素材是视频文件导出时按帧抽取保留帧号便于回溯原始监控画面。常见的抽帧做法是用OpenCV按固定间隔取帧import cv2 cap cv2.VideoCapture(9_1_mp4.mp4) fps cap.get(cv2.CAP_PROP_FPS) frame_interval int(fps) # 每1秒取1帧 frame_idx 0 saved_idx 0 while True: ret, frame cap.read() if not ret: break if frame_idx % frame_interval 0: cv2.imwrite(fframe_{saved_idx:04d}.jpg, frame) saved_idx 1 frame_idx 1 cap.release()frame_interval直接决定样本数量和相邻帧的相似度。间隔太小连续几帧画面几乎一致模型会把猪的静止姿态学成唯一答案泛化能力变差间隔太大喝水这类持续时间短的行为可能根本采不到关键帧。先按每秒1帧抽一轮再人工剔除模糊帧和猪完全离栏的空帧是数据质量的第一道关口。抽帧完成后要检查是否有重复画面视频压缩产生的花屏帧也可能混入这类坏帧不处理干净训练时会出现loss异常波动。2.2 COCO JSON的categories与annotations字段拆解COCO格式的核心是images、categories、annotations三个数组。这套数据集的annotations数组里每个元素对应一个目标框实例对应四类行为。字段结构如下顶层字段作用本数据集对应内容images图片ID、文件名、宽高1272张jpg图片categories类别ID和名称drink / eat / sleep / standannotations目标框类别、坐标、面积四类行为目标框licenses许可信息标注工具或来源方的授权说明读取并验证标注文件的最小脚本import json with open(annotations/instances_train.json) as f: data json.load(f) print(图片数量:, len(data[images])) print(标注数量:, len(data[annotations])) print(类别:, [(c[id], c[name]) for c in data[categories]]) for img in data[images][:3]: print(样例图片:, img[file_name], img[width], img[height])bbox字段在COCO格式中是[x, y, width, height]x和y为目标框左上角像素坐标不是归一化坐标。area对矩形框而言等于width * height但若原始标注工具导出的是多边形area需要通过pycocotools.mask计算直接用宽高相乘会偏大。这个细节后续在做小目标过滤或计算类别占比时会造成统计偏差。2.3 调用pycocotools验证标注完整性拿到JSON后第一步不是训练而是用COCO官方工具做完整性体检。常见问题包括标注框超出图片边界、类别ID对不上、图片路径指向不存在的文件。下面是完整的校验脚本import os from pycocotools.coco import COCO coco COCO(annotations/instances_train.json) img_ids coco.getImgIds() err_count 0 for img_id in img_ids: img_info coco.loadImgs(img_id)[0] if not os.path.exists(os.path.join(images, img_info[file_name])): print(缺失图片:, img_info[file_name]) err_count 1 continue ann_ids coco.getAnnIds(imgIdsimg_id) anns coco.loadAnns(ann_ids) for ann in anns: x, y, w, h ann[bbox] if x 0 or y 0 or x w img_info[width] or y h img_info[height]: print(f越界框: {img_info[file_name]}, bbox{ann[bbox]}) err_count 1 print(异常数量:, err_count)越界框不一定是错误。猪的头部探出画面边缘时标注工具会把框截断为画面内坐标此时x w刚好等于图片宽度不会触发越界只有标注工具允许负坐标或超出宽高的框才需要修正。跑完这一轮再进入训练能避免后续出现的IndexError或loss为NaN这类基础问题。pycocotools在Windows上需要预编译wheel包如果安装失败可以使用pycocotools-windows替代功能一致。3. YOLOv8训练行为识别模型从COCO JSON到可推理权重3.1 为什么选用目标检测框架而不是图像分类识别行为听起来像是分类任务但猪圈场景里是多目标共存——一只猪在喝水、另一只在睡觉图像分类只能给整张图打一个标签完全无法覆盖这种情形。检测模型天然输出每个实例的类别和位置因此这里采用目标检测思路解决。数据集宣称的92.6%平均正确识别率在目标检测语境下对应的是逐类准确率的均值或mAP。训练阶段用YOLOv8n或YOLOv8s性价比最高显存占用小、迭代快普通消费级显卡即可启动。3.2 把COCO标注转换为YOLO训练格式YOLO训练要求每张图片对应一个txt文件每行格式为class_id x_center y_center width height所有坐标归一化到0到1。COCO到YOLO的转换是绕不开的一步直接写成脚本import json import os with open(annotations/instances_train.json) as f: data json.load(f) os.makedirs(labels, exist_okTrue) cat_map {cat[id]: idx for idx, cat in enumerate(data[categories])} img_id_to_name {img[id]: img[file_name] for img in data[images]} img_id_to_size {img[id]: (img[width], img[height]) for img in data[images]} for img in data[images]: img_id img[id] w, h img[width], img[height] txt_path os.path.join(labels, img[file_name].replace(.jpg, .txt)) with open(txt_path, w) as f: for ann in data[annotations]: if ann[image_id] ! img_id: continue x, y, bw, bh ann[bbox] x_center (x bw / 2) / w y_center (y bh / 2) / h f.write(f{cat_map[ann[category_id]]} {x_center:.6f} {y_center:.6f} {bw / w:.6f} {bh / h:.6f}\n)转换时有个致命细节COCO的bbox是左上角坐标加宽高YOLO需要中心点坐标加宽高x bw / 2这步漏掉训练会直接发散。cat_map用枚举重新编号是为了防止COCO原始类别ID不连续导致YOLO的类别数对不上。转换完成后要抽查几个txt文件确认没有空文件——如果某张图片没有任何标注YOLO训练时会跳过但验证时可能出现警告需要单独处理。3.3 训练参数配置与超参调整YOLOv8训练入口是命令行但参数需要逐条核对。以下是针对1272张图片的推荐配置yolo detect train \ modelyolov8s.pt \ datadataset.yaml \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ patience20 \ projectrun_pigdataset.yaml需要手动创建指向图片目录、标签目录和类别名train: images/train val: images/val nc: 4 names: [drink, eat, sleep, stand]patience20表示验证集mAP连续20个epoch未提升就提前终止。1272张图的数据量通常在第80到110个epoch之间收敛早停既能节省时间又能防止尾部过拟合。imgsz640是性价比选择猪目标在画面中占比通常较大用512也能跑但低头喝水这类细节会在降采样中丢失。lr0从0.01起步如果训练前10个epoch出现明显loss震荡降到0.005再试。batch16取决于显存8GB显存建议降到8否则会OOM中断。3.4 用验证集复算平均正确识别率训练完成后关注两个输出results.csv和confusion_matrix.png。results.csv包含整体mAP不是逐类准确率。要验证92.6%这个指标的复现情况需要按类别分别计算import pandas as pd df pd.read_csv(run_pig/detect/train/results.csv) final_epoch df.iloc[-1] print(mAP0.5:, final_epoch[metrics/mAP50(B)]) print(mAP0.5:0.95:, final_epoch[metrics/mAP50-95(B)])results.csv中的mAP是全部类别取平均如果某一类表现特别差整体数值会被拉低。使用yolo val导出逐类AP报告重点检查drink类别——喝水动作持续短、头部低垂、经常与食槽重叠是最容易掉点的类。若drink的AP显著低于其他三类先回数据集统计该类样本数量多数情况是样本不足而不是模型问题。4. 类别分布与标注质量行为识别数据集的长尾与边界4.1 四类行为的样本数量与长尾问题1272张图内睡觉行为通常占比最高因为猪的作息里睡眠时间最长视频抽帧抽到睡觉帧的概率天然更大喝水行为持续时间最短只有站在饮水器附近的几帧才被标注单类样本可能只有其他类的三分之一。这种不均衡会直接影响梯度更新方向高频类别学得更准低频类别被牺牲。做一个快速的类别统计import json from collections import Counter with open(annotations/instances_train.json) as f: data json.load(f) cat_counter Counter() for ann in data[annotations]: cat_name [c[name] for c in data[categories] if c[id] ann[category_id]] cat_counter[cat_name[0]] 1 total sum(cat_counter.values()) for name, cnt in cat_counter.most_common(): print(f{name}: {cnt} ({cnt / total * 100:.1f}%))如果drink类占比低于15%给该类增加样本权重是常规手段。dataset.yaml里不能直接配置权重需要再写一个采样器在训练前对drink类做复制增强或者用图像级复制直接扩充该类图片。注意不要重复超过2倍过度重复会让模型把特定猪的毛色或栏位背景当成类别特征换个猪圈部署时性能骤降。4.2 混淆矩阵中的典型错误sleep与stand、eat与drink四类行为在视觉层面存在天然重叠。sleep和stand的边界模糊——猪卧着时头和前肢撑起姿态介于两者之间eat和drink因为食槽与饮水器位置相邻目标框大量交叠。这些边界情况无法靠调置信度阈值解决要从标注规范和推理逻辑两个层面处理。训练后的混淆矩阵会显示误判方向。如果sleep被大量预测成stand检查标注框的尺度是否包含了整头猪还是只框了身体如果eat和drink互相混淆考虑在推理阶段引入空间约束——饮水器和食槽在图像中的坐标是固定的划定两个ROI区域只统计落在对应区域内的检测结果。这种基于位置的后置判断比更换更大参数量的模型更有效且成本更低。4.3 用CVAT补标和修正已有标注拿到此数据集后最常见的操作不是直接训练而是加入自己的猪场视频扩展样本。CVAT是处理此类标注流转最顺手的工具导入COCO JSON后补标再导出为COCO流程闭环。操作时注意以下几点创建task时选择数据目录后导入格式必须选COCO JSON 1.0标注过程中新增标签时标签名要与JSON里categories.name完全一致大小写敏感导出时同样选COCO JSON 1.0CVAT会重新生成annotations文件导出后检查categories的顺序CVAT有时会按ID重排再转YOLO格式时类别编号会错位修正已有标注还有一个更快的可视化途径——把框画在图上直接看import cv2 import os from pycocotools.coco import COCO coco COCO(annotations/instances_train.json) img_ids coco.getImgIds()[:5] colors {1: (0, 255, 0), 2: (255, 0, 0), 3: (100, 100, 255), 4: (0, 165, 255)} for img_id in img_ids: img_info coco.loadImgs(img_id)[0] img cv2.imread(os.path.join(images, img_info[file_name])) ann_ids coco.getAnnIds(imgIdsimg_id) for ann in coco.loadAnns(ann_ids): x, y, w, h map(int, ann[bbox]) cv2.rectangle(img, (x, y), (x w, y h), colors[ann[category_id]], 2) label coco.loadCats(ann[category_id])[0][name] cv2.putText(img, label, (x, y - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.6, colors[ann[category_id]], 2) cv2.imwrite(fcheck_{img_id}.jpg, img)可视化能瞬间暴露标注偏移问题。框偏大、偏小、漏标这些情况在纯JSON数据里很难察觉但叠在图上后一目了然。漏标是训练中最隐蔽的问题——它不报错只是让模型在对应区域学到错误的背景特征推理时表现为在该位置反复漏检或误检排查时很难定位到具体是哪些图导致的。5. 部署与进阶视频流推理中的ROI约束与行为判定5.1 视频流推理与检测结果平滑训练好的权重在离线单帧上表现再好也不等于视频流里可以直接用。实际猪场摄像头输出RTSP流逐帧推理对边缘设备压力过大通常每秒抽2到3帧送入模型。对于同一个目标的检测结果需要在连续多帧上做投票平滑避免单帧误检直接触发行为状态切换def vote_behavior(results_window): from collections import Counter counter Counter(results_window) behavior, count counter.most_common(1)[0] return behavior, count / len(results_window)results_window取当前帧前5到10帧的检测类别列表比例超过0.6才采纳该结果。这里采用比例阈值而不是简单取众数是为了压掉单帧抖动——猪甩头瞬间可能被误判为喝水但连续几帧里该误判比例很低会被正确类别覆盖。阈值设到0.5以下容易受噪声影响设到0.8以上则行为切换响应过慢0.6是兼顾灵敏度和稳定性的常用值。5.2 用ROI约束和时空逻辑过滤误检喝水行为的判定不能只看模型输出。在猪场部署场景中饮水器位置固定可以预先在图像坐标中划定ROI区域只有目标框中心落在ROI内的drink检测才计入统计def is_in_roi(bbox_center, roi): x, y bbox_center return roi[0] x roi[2] and roi[1] y roi[3] # roi定义: [x_min, y_min, x_max, y_max]取饮水器四周扩大20像素 drink_roi [620, 180, 780, 320] box_center (box_x box_w / 2, box_y box_h / 2) if label drink and is_in_roi(box_center, drink_roi): drink_count 1ROI坐标需要通过标定确定具体做法是取一帧含饮水器的画面用图像标注工具量出饮水器边缘的像素坐标。框中心点判定比框的交并比计算更简单且抗干扰猪身体其他部位靠近饮水器时不会触发计数只有头部正对饮水器的框中心落进区域才算有效。5.3 行为持久化统计与异常预警行为识别不只是单帧分类还要做时间维度的统计。记录每个行为状态的进入和离开时间戳计算单次行为持续时长能直接服务于养殖管理。猪连续躺卧超过6小时且期间无饮水记录大概率存在健康问题这套逻辑可以作为异常预警的触发条件behavior_start {} alert_threshold {no_drink_hours: 6, eat_less_than_minutes: 10} def update_behavior(pen_id, behavior, timestamp): if behavior not in behavior_start: behavior_start[behavior] timestamp if behavior drink and timestamp - behavior_start.get(drink, timestamp) 0: pass # 保持状态等待连续时长实际部署建议把模型跑在NVIDIA Jetson Orin或工控机上TensorRT导出后推理延迟可控制在20到50毫秒配合每秒2到3帧的抽帧策略完全满足实时监控需求。日志记录建议直接写SQLite单表按小时轮转避免长时间运行后文件过大影响查询性能。光照变化对行为识别的影响在夜间猪舍尤为明显红外补光场景下若验证集准确率下降明显采集夜间样本重新微调是必要的收尾工作。本文还有配套的精品资源点击获取