news 2026/9/28 17:25:33

狗狗行为检测数据集:1551张图8类动作,YOLO与VOC双格式实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
狗狗行为检测数据集:1551张图8类动作,YOLO与VOC双格式实战指南

简介:这是一份面向计算机视觉学习者与目标检测开发者的狗狗行为识别数据集,覆盖吠叫、进食、躺卧、俯卧、坐、睡眠、站立等8类常见犬类动作,适合用于YOLO系列模型的训练、微调与课堂实验。压缩包共2000个文件,以1551个xml标注文件和449个txt标签文件为主,分别对应VOC与YOLO两种格式,另含1551张清晰jpg图片,整体约57.77MB,目录按图片、标注、标签分文件夹存放,便于直接接入主流检测框架。全部图片均为矩形框标注,共1613个目标框,其中睡眠、躺卧、站立等类别样本相对充足,各类别分布较为均衡,未做数据增强,标注准确合理。目前已有179人学习下载,可作为犬类行为识别、宠物智能监控或课堂实践的基础数据,帮助读者省去自行采集与标注的成本,快速搭建训练与验证流程。

1. 狗狗行为检测数据集:1551 张图、8 类动作,YOLO 和 VOC 双格式到底怎么落地

如果你正在做宠物行为识别、智能看护或者动物行为分析,大概率绕不开一个现实问题:公开的狗狗行为数据集太少了,要么类别粗、要么标注乱、要么只有单一格式。这份 1551 张的狗狗行为检测数据集,直接把 VOC 和 YOLO 两套标注都打包好了,8 个行为类别覆盖了吠叫、进食、趴卧、坐、睡、站立等高频动作,总框数 1613 个。它不是那种动辄几万张的工业级数据集,但胜在标注干净、格式齐全、拿来就能训。适合谁?做 YOLOv5/v8 训练想快速验证行为检测链路的、需要 VOC 格式喂给 SSD 或 Faster R-CNN 的、以及想拿小数据集跑通全流程再迁移到自采数据的从业者。下面我从格式结构、转换脚本、训练配置到踩坑排查,把这份资源拆开讲透。

2. 数据集结构与格式解析:1551 张图怎么对应 1551 个 xml 和 1551 个 txt

拿到压缩包先别急着解压到桌面,目录结构决定了你后面写 data.yaml 和转换脚本时会不会翻车。这份数据集的组织方式很标准,三个文件夹各司其职,但有几个细节如果不提前确认,训练时会出现「图片找不到」「标签对不上」的玄学问题。

2.1 三个文件夹的职责与文件对应关系

解压后你会看到这样的结构:

dataset/ ├── JPEGImages/ # 1551 张 jpg 原图 │ ├── xyxr_image1366.jpg │ ├── xyxr_image567.jpg │ └── ... ├── Annotations/ # 1551 个 VOC 格式 xml │ ├── xyxr_image1366.xml │ ├── xyxr_image567.xml │ └── ... └── labels/ # 1551 个 YOLO 格式 txt ├── xyxr_image1366.txt ├── xyxr_image567.txt └── ...

三个文件夹的文件名主干完全一致,这是好事——意味着你不需要做文件名映射。但要注意:labels文件夹里的 txt 已经是 YOLO 格式(class_id x_center y_center width height,归一化到 0~1),而Annotations里是标准 VOC xml。两套标注同时存在,省去了你自己转换的麻烦,但也带来一个隐患:如果你同时把两个路径都写进训练配置,YOLO 会优先读 labels,xml 就成了摆设。常见做法是只保留一套,另一套留作备份或用于其他框架。

2.2 8 个行为类别的标签映射与框数分布

标签名称和对应的框数如下表,这个映射关系必须和你的data.yaml里的names列表顺序完全一致,否则训练出来的模型会把「bark」识别成「stand」:

class_id标签名含义框数
0bark吠叫168
1default默认/其他211
2eat进食208
3lyingDown趴下240
4lyingProne俯卧148
5sit坐下154
6sleep睡觉253
7stand站立231

总框数 1613,平均每张图约 1.04 个框,说明大部分图片只有一只狗、一个行为标注。类别分布相对均衡,最多的 sleep 253 框,最少的 lyingProne 148 框,比例约 1.7:1,不算严重长尾。但default这个类别需要留意——它不是一个具体行为,更像「其他/未分类」的兜底类。如果你的应用场景不需要这个类,可以在训练前把它过滤掉,否则模型会学到一个语义模糊的类别,拉低整体精度。

2.3 VOC 与 YOLO 格式的字段差异与读取验证

VOC xml 的核心字段是<size>里的宽高和<object>里的name、bndbox(xmin/ymin/xmax/ymax,绝对像素坐标)。YOLO txt 则是每行一个目标:class_id x_center y_center width height,全部归一化。两者可以互相转换,但转换时最容易出错的是坐标归一化的分母——必须用对应图片的实际宽高,不能用固定值。

验证标注是否正确的快速方法:

import os from PIL import Image img_dir = "dataset/JPEGImages" lbl_dir = "dataset/labels" for name in os.listdir(lbl_dir)[:5]: txt_path = os.path.join(lbl_dir, name) img_path = os.path.join(img_dir, name.replace(".txt", ".jpg")) img = Image.open(img_path) w, h = img.size with open(txt_path) as f: for line in f: cls, xc, yc, bw, bh = map(float, line.split()) # 反归一化检查是否越界 x1 = (xc - bw / 2) * w y1 = (yc - bh / 2) * h x2 = (xc + bw / 2) * w y2 = (yc + bh / 2) * h assert 0 <= x1 < x2 <= w, f"{name} x 越界" assert 0 <= y1 < y2 <= h, f"{name} y 越界" print(f"{name} 标注正常,图片尺寸 {w}x{h}")

这段代码做了两件事:把 YOLO 归一化坐标还原成像素坐标,然后断言框没有超出图片边界。如果某个框的 x1 小于 0 或 x2 大于图片宽度,说明标注时坐标算错了,这种样本在训练时会导致损失异常。参数说明:xc/yc是框中心点归一化坐标,bw/bh是框宽高归一化值,乘以图片宽高后得到绝对坐标。跑一遍全量数据,把越界的文件名记下来,要么修正要么剔除。

3. 从 VOC 到 YOLO 的转换与训练配置:data.yaml 和 anchor 怎么设

虽然压缩包里已经给了 YOLO 格式的 txt,但实际项目中你很可能需要反向操作——比如拿到一份只有 VOC 的数据,或者想把这份数据转成 YOLOv8 的 txt 格式重新划分训练集。这一章把转换脚本、数据集划分、data.yaml 配置和 anchor 设置一次讲清。

3.1 VOC 转 YOLO 的完整脚本与坐标归一化

下面这个脚本把 Annotations 里的 xml 转成 YOLO txt,同时生成训练集和验证集的索引文件:

import os import xml.etree.ElementTree as ET import random from PIL import Image classes = ["bark", "default", "eat", "lyingDown", "lyingProne", "sit", "sleep", "stand"] def voc_to_yolo(xml_path, img_path, out_path): tree = ET.parse(xml_path) root = tree.getroot() img = Image.open(img_path) w, h = img.size lines = [] for obj in root.findall("object"): cls_name = obj.find("name").text if cls_name not in classes: continue cls_id = classes.index(cls_name) bnd = obj.find("bndbox") xmin = float(bnd.find("xmin").text) ymin = float(bnd.find("ymin").text) xmax = float(bnd.find("xmax").text) ymax = float(bnd.find("ymax").text) # 归一化并转为中心点+宽高 xc = (xmin + xmax) / 2.0 / w yc = (ymin + ymax) / 2.0 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h lines.append(f"{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}") with open(out_path, "w") as f: f.write("\n".join(lines)) # 批量转换 xml_dir = "dataset/Annotations" img_dir = "dataset/JPEGImages" out_dir = "dataset/labels_yolo" os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(".xml"): continue img_file = xml_file.replace(".xml", ".jpg") voc_to_yolo( os.path.join(xml_dir, xml_file), os.path.join(img_dir, img_file), os.path.join(out_dir, xml_file.replace(".xml", ".txt")) ) print("转换完成")

逻辑说明:先解析 xml 拿到图片宽高和每个 object 的边界框,然后把绝对坐标转成归一化的中心点+宽高格式。参数上,xc = (xmin+xmax)/2/w是中心点 x 归一化,bw = (xmax-xmin)/w是框宽归一化。注意浮点数保留 6 位小数,YOLO 训练时对精度不敏感,但太长的字符串会拖慢数据加载。如果 xml 里有difficult标记为 1 的目标,建议跳过,否则模型会被难样本带偏。

3.2 训练集/验证集划分与 data.yaml 写法

1551 张图按 8:2 划分,训练集 1240 张,验证集 311 张。划分脚本:

import os import random random.seed(42) all_imgs = [f for f in os.listdir("dataset/JPEGImages") if f.endswith(".jpg")] random.shuffle(all_imgs) split = int(len(all_imgs) * 0.8) train_imgs = all_imgs[:split] val_imgs = all_imgs[split:] with open("train.txt", "w") as f: for img in train_imgs: f.write(f"dataset/JPEGImages/{img}\n") with open("val.txt", "w") as f: for img in val_imgs: f.write(f"dataset/JPEGImages/{img}\n") print(f"训练集 {len(train_imgs)} 张,验证集 {len(val_imgs)} 张")

random.seed(42)保证每次划分结果一致,方便复现。划分完写data.yaml:

path: ./dataset train: train.txt val: val.txt nc: 8 names: ["bark", "default", "eat", "lyingDown", "lyingProne", "sit", "sleep", "stand"]

nc必须等于 8,names的顺序必须和转换时的classes列表一致。常见错误是把names写成中文或者顺序打乱,YOLO 不会报错,但训练出来的类别全是错的。

3.3 anchor 聚类与输入尺寸选择

这份数据集的框以中小尺寸为主——狗在画面中的占比不会太大,尤其是趴卧和睡觉的样本,框可能只占图片的 10%~20%。YOLOv5/v8 默认 anchor 是基于 COCO 的,直接拿来用召回率会偏低。建议用自己的数据跑一遍 k-means 聚类:

python utils/autoanchor.py --data data.yaml --img-size 640

如果不想跑聚类,手动设 anchor 的经验值是:小框 10x13、16x30,中框 33x23、30x61,大框 62x45、59x119。输入尺寸选 640x640 是平衡精度和显存的选择,V100 上 batch_size 可以开到 32,单卡 8G 显存建议降到 8 或 16。图片分辨率本身是清晰的,不需要额外放大,但训练时 letterbox 填充会引入灰边,如果狗经常出现在画面边缘,可以改用矩形推理减少填充。

4. 训练避坑与排查:从 loss 不降到框偏移的 5 个血泪经验

小数据集训练最容易出的问题不是模型结构,而是数据本身和配置细节。下面 5 条是我在类似规模数据集上反复踩过的坑,每条按「现象 → 原因 → 解决」写,你对照排查能省不少时间。

4.1 现象:loss 从第一轮就不降,mAP 始终为 0

原因:最常见的是data.yaml里的names顺序和 txt 里的class_id对不上。比如 txt 里0是bark,但 yaml 里0写成了default,模型学的是错位映射,loss 自然不降。另一个原因是图片路径写错,YOLO 找不到图,直接跳过所有样本。

解决:先跑一遍 3.1 的验证脚本确认标注没越界,再检查data.yaml的names和转换脚本里的classes是否逐字一致。路径用绝对路径试一次,排除相对路径的歧义。

4.2 现象:训练到一半 loss 突然变成 NaN

原因:学习率太大或者 batch_size 太小导致梯度爆炸。小数据集上如果用了默认的lr0=0.01,前几轮很容易飞。另外,如果某个样本的框宽高归一化后接近 0(比如标注时框画得太小),计算 loss 时会出现除零。

解决:把lr0降到0.001,加warmup_epochs=3让模型先稳定几轮。同时过滤掉宽高小于 0.01 的框,这种框在 640 输入下只有 6 个像素,没有训练价值。

4.3 现象:验证集 mAP 正常,但推理时框全部偏移

原因:训练时的 letterbox 填充和推理时的预处理不一致。YOLO 默认在训练时把图片缩放到 640x640 并填充灰边,推理时如果直接 resize 不填充,坐标映射就会错位。

解决:推理时用和训练相同的 letterbox 逻辑,或者直接用model.predict(source, imgsz=640)让 ultralytics 自己处理。如果自己写预处理,记住要把预测框的坐标减去填充偏移再除以缩放比例。

4.4 现象:default类别置信度普遍偏低

原因:default本身语义模糊,标注时可能把「不确定」的样本都归到了这一类,导致类内差异大,模型学不到稳定特征。

解决:如果应用场景不需要这个类,训练前把它从 txt 里删掉,同时把nc改成 7,names里去掉default。如果必须保留,考虑把它合并到最接近的行为类里,或者单独收集更多样本再训。

4.5 现象:训练速度慢,GPU 利用率只有 30%

原因:数据加载成了瓶颈。1551 张图虽然不大,但如果workers设得太小,或者图片没有预缓存,GPU 会频繁等数据。

解决:把workers设成 CPU 核心数的一半,开启cache=True把图片缓存到内存(1551 张 jpg 大约占 1~2G 内存,完全放得下)。另外确认rect=True开启矩形训练,减少填充计算量。

提示:训练前用yolo checks确认环境和依赖版本,尤其是 torch 和 cuda 的匹配,版本不对会报一些看不懂的错。

5. 进阶技巧:用这份数据做迁移学习和行为时序扩展

1551 张图、8 个类别的规模,单独训一个行为检测模型够用,但如果你想做更细粒度的行为识别或者时序动作检测,这份数据可以当起点。我一般会走两条路:一是拿它做预训练,然后在自采数据上微调;二是把检测框输出喂给时序模型,做「站立→行走→趴下」这样的行为链识别。

5.1 冻结 backbone 做小样本微调

如果你自己的数据只有几百张,直接训容易过拟合。做法是加载这份数据训好的权重,冻结 backbone 和前几层 neck,只训 head:

from ultralytics import YOLO model = YOLO("runs/detect/train/weights/best.pt") # 冻结前 10 层 for i, (name, param) in enumerate(model.model.named_parameters()): if i < 10: param.requires_grad = False model.train(data="my_data.yaml", epochs=50, lr0=0.0005, freeze=10)

freeze=10表示冻结前 10 层,lr0降到0.0005避免破坏预训练特征。这样在 300~500 张自采数据上也能拿到可用的 mAP。

5.2 检测结果转行为序列的思路

目标检测只告诉你「这一帧狗在趴着」,但行为分析往往需要「狗从站着变成趴下」这样的时序信息。做法是把视频按帧过检测模型,得到每帧的类别和框,然后按时间轴拼成序列:

import cv2 from ultralytics import YOLO model = YOLO("best.pt") cap = cv2.VideoCapture("dog_video.mp4") fps = cap.get(cv2.CAP_PROP_FPS) frame_id = 0 sequence = [] while cap.isOpened(): ret, frame = cap.read() if not ret: break if frame_id % int(fps) == 0: # 每秒取一帧 results = model(frame, imgsz=640, verbose=False) for r in results: for box in r.boxes: cls_id = int(box.cls) conf = float(box.conf) if conf > 0.5: sequence.append((frame_id / fps, model.names[cls_id])) frame_id += 1 cap.release() # sequence 形如 [(0.0, 'stand'), (1.0, 'stand'), (2.0, 'lyingDown'), ...]

这段代码每秒抽一帧做检测,把时间戳和类别存成序列。拿到序列后可以用简单的状态机或者 LSTM 做行为链识别。参数上,conf > 0.5是置信度阈值,行为分析场景可以适当降低到 0.3 提高召回,但会引入更多误检,需要根据实际视频调。

5.3 数据增强的边界

这份数据集明确说了「图片是否增强:否」,意味着原图没有做过翻转、裁剪、色彩抖动。训练时开 YOLO 默认的增强(hsv_h=0.015、flipud=0.5、fliplr=0.5)没问题,但要注意:狗的行为有方向性,比如「站立」翻转后还是站立,但「趴下」如果翻转后变成侧躺,标注语义可能变了。我的习惯是只开fliplr=0.5和轻微的hsv_h,不开flipud,避免上下翻转把趴卧变成仰卧。另外mosaic=1.0在小数据集上能提升泛化,但会引入大量小框,如果发现验证集 mAP 波动大,可以降到0.5。

从那以后我每次拿到新数据集,都强制先跑一遍标注越界检查、类别分布统计和 10 张图的抽样可视化,确认没问题再开训。这份狗狗行为数据集的结构清晰、标注完整,省去了很多清洗工作,但default类的处理和 anchor 的重新聚类还是得自己动手。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 17:25:13

PanWatch 部署实战:TradingAgents 多智能体协作与 Docker 工程化落地

1. 从 PanWatch 这个名字说起&#xff1a;它到底想解决什么问题第一次看到 PanWatch 这个项目标题&#xff0c;我脑子里冒出来的第一个念头是“盘口监控”或者“面板看板”这类东西。结合 TradingAgents、Docker、AI、Agent 这几个关键词&#xff0c;基本可以判断这是一个把 AI…

作者头像 李华
网站建设 2026/9/28 17:24:46

OpenPose+随机森林疲劳驾驶检测源码:从姿态估计到告警全链路解析

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与开发者的司机驾驶状态检测项目源码&#xff0c;基于深度学习骨骼点OpenPose算法&#xff0c;实现疲劳与姿态识别并触发告警&#xff0c;适合用作毕业设计、课程大作业或项目立项演示。压缩包共28个文件&#…

作者头像 李华
网站建设 2026/9/28 17:24:31

海康威视摄像机二次开发实战:SDK取流、回放与云台控制完整指南

1. 为什么我要啃海康威视的二次开发这块硬骨头第一次接触海康威视摄像机二次开发&#xff0c;是几年前一个园区安防升级的项目。甲方原有十几台海康的枪机和球机&#xff0c;想做一个统一的管理看板&#xff0c;要求实时预览、历史回放、抓图、云台控制全都要集成到自己的业务系…

作者头像 李华
网站建设 2026/9/28 17:24:15

MATLAB LSTM多输入单输出分类源码解析与实战

简介&#xff1a;该资源面向需要掌握时序数据分类的MATLAB用户与机器学习初学者&#xff0c;提供基于长短期记忆神经网络的多输入单输出分类预测方案&#xff0c;可解决多特征输入下的二分类及多分类建模问题&#xff0c;适用于信号识别、故障诊断、行为判别等场景。压缩包共9个…

作者头像 李华
网站建设 2026/9/28 17:22:56

哈尔滨靠谱的国际高中培训机构筛选名录 英领国际学校省心不踩坑

很多哈尔滨家长在规划孩子高中升学路径时&#xff0c;都会陷入筛选国际高中培训机构的纠结&#xff1a;既要担心机构资质不合规&#xff0c;又怕课程体系不对口&#xff0c;还会操心后续升学衔接没保障&#xff0c;想要找到一所靠谱的机构着实不容易。对于想要转轨国际升学的家…

作者头像 李华
网站建设 2026/9/28 17:22:40

ax技术定位解析:从Kubernetes调度到Agent Substrate实践

我无法根据当前输入生成符合要求的博文。原因如下&#xff1a;项目标题仅为 "ax"&#xff0c;无明确语义指向&#xff0c;既非完整技术名词、工具名、框架名&#xff0c;也非可识别的缩写&#xff08;如未说明全称&#xff09;&#xff0c;在工程与运维领域中&#x…

作者头像 李华