基于 YOLO11 的狗的 6 种行为识别系统:从模型到 Streamlit 全流程实战
关键词:YOLO11、狗行为识别、宠物 AI、Streamlit、目标检测、Ultralytics
一、背景
1.1 行业痛点
随着城市养宠人群的快速增长,宠物视觉智能已经从猫狗品种识别延伸到了更精细的行为分析:
- 家庭场景:主人不在家时,狗是吠叫、奔跑还是趴卧?是不是长时间没进食?要不要远程关注一下?
- 宠物店 / 寄养机构:能不能用一个摄像头自动统计每只狗的活跃 / 静息时长,作为日报推送给主人?
- 训练学校 / 行为科研:行为标注完全依赖人工逐帧打标,几个小时视频要花一整天,能不能让模型先做一遍粗标?
- 流浪动物收容所:同时看护几十只狗,工作人员很难持续观察每只狗的状态变化,需要异常预警。
把 目标检测 + 行为分类合并到 YOLO11 这类 Anchor-Free 检测器里,用一张图就能同时给出"狗在哪里"和"它在做什么",是当前最简洁的工程方案。本项目就是这条路线下的一个完整落点:基于 YOLO11n,识别狗的吠叫、进食、趴卧、奔跑、端坐、站立这 6 种典型行为,并提供一个开箱即用的 Streamlit 可视化界面。
视频演示与源码 下载

包含: 📦完整项目源码 📦 预训练 模型权重
🗂️数据集
1.2 项目运行效果


1.3 项目介绍
核心创新点:
| 维度 | 设计 |
|---|---|
| 类目设计 | 把"目标检测 + 行为分类"合并为一个 6 类检测任务,避免两阶段管线带来的延迟 |
| 模型选型 | YOLO11n,参数量约 2.6 M,CPU 实时、Apple Silicon / NVIDIA GPU 加速可选 |
| 部署形态 | Streamlit 单页应用 + 本地 best.pt,零数据库、零中间件,开箱即用 |
| 输入兼容 | 图片 / 批量图片(含 zip)/ 视频 / 摄像头 4 种输入复用同一推理引擎 |
| 中英映射 | 标签内含中英双映射 + emoji,模型权重切换不影响 UI 显示 |

功能概览:
- 🐕 单图检测:拖拽上传 → 实时返回带框图 + 行为类别 / 置信度 / 坐标明细
- 📚 批量检测:单次最多 200 张,输出汇总表 + 行为分布柱状图 + zip 打包下载
- 🎬 视频检测:mp4 / avi / mov / mkv,逐帧推理后落盘新视频,便于监控录像离线分析
- 📷 摄像头实时检测:可对接家庭摄像头 / 宠物店 IPC,做实时行为感知
6 种行为类别:吠叫 🐕🦺、进食 🍖、趴卧 💤、奔跑 🏃、端坐 🪑、站立 🐾。
技术栈:
| 层 | 选型 |
|---|---|
| 模型框架 | Ultralytics 8.3 + PyTorch |
| 视觉算法 | YOLO11n(Anchor-Free,C2f Backbone,Decoupled Head + DFL) |
| Web 前端 | Streamlit 1.35 + 自定义 HTML 主题(暖橙 + 蓝灰,呼应狗毛色与项圈) |
| 视频 / 图像 | OpenCV、imageio-ffmpeg |
| 数据可视化 | Plotly / Streamlit 原生 chart |
| 配置管理 | 单一 configs/project.yaml,行业话术 / UI / 推理阈值统一收口 |

二、设计框架
2.1 系统架构
┌──────────────────────────────────────────┐
│ Streamlit Web 前端(单页 SPA) │
│ · 6 类行为图鉴 / 单图 / 批量 / 视频 / 摄像头 │
│ · 侧栏 · 阈值 · 类别筛选 · 模型缓存 │
└────────────────────┬─────────────────────┘
│ Python 调用
▼
┌──────────────────────────────────────────┐
│ 推理服务层(infer_image_path 等) │
│ · bytes / Path / frame → tensor │
│ · 推理结果 → 标注图 + DataFrame │
└────────────────────┬─────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ YOLO11n 推理引擎(model/best.pt) │
│ Backbone (C2f+SPPF) → Neck (FPN/PAN) │
│ → Decoupled Head(DFL + cls) │
└──────────────────────────────────────────┘
2.2 YOLO11 网络结构
输入 640×640×3
│
▼
[Backbone]
Conv → C2f → Conv → C2f → Conv → C2f → Conv → C2f → SPPF
│
▼
[Neck] FPN 上采样 + PAN 下采样:P3 / P4 / P5 三级金字塔
│
▼
[Head] Decoupled Head(cls 头 / reg 头解耦)
回归头采用 DFL(Distribution Focal Loss)
Anchor-Free,输出 (cx, cy, w, h, cls × 6)
│
▼
[NMS] iou=0.7, conf=0.25 → 最终检测框
2.3 检测流程
图像 / 监控视频帧
│
▼
Letterbox 640×640 + RGB
│
▼
YOLO11n forward
│
▼
Detect Head 输出 (cls × 6)
│
▼
conf 过滤 + NMS
│
▼
result.plot() 画框 + 行为类别 + 置信度
│
▼
Streamlit 双列展示 + DataFrame + 行为分布图

三、代码结构(核心 50 行 + 解析)
项目目录:
狗行为识别/
├── app/streamlit_app.py # Web 入口
├── configs/project.yaml # 行业话术 / UI / 训练 / 推理参数
├── model/best.pt # 训练好的 YOLO11n 权重
├── scripts/ # train / validate / export 等
├── data/dataset/ # 训练 / 验证 / 测试集
└── 狗狗的6种行为识别数据集/ # 原始数据集(含训练 / 验证 / 测试切分)
最核心的 50 行——模型加载 + 单图推理 + Streamlit 单图 Tab:
# === 1. 模型加载(带 streamlit 资源缓存,避免每次刷新重载)=============
@st.cache_resource(show_spinner=False)
def load_model(model_path: str) -> YOLO:
return YOLO(model_path)
# === 2. 单图推理:路径 → 标注图 + 检测明细 DataFrame ===================
def infer_image_path(model: YOLO, image_path: Path, conf: float):
result = model.predict(str(image_path), conf=conf, verbose=False)[0]
annotated = result.plot() # BGR ndarray,已画框
rows = []
if result.boxes is not None:
for box in result.boxes:
cls_id = int(box.cls.item())
x1, y1, x2, y2 = [float(v) for v in box.xyxy[0].tolist()]
rows.append({
"class_id": cls_id,
"class_name": result.names[cls_id], # eg. "端坐" / "sitting"
"confidence": round(float(box.conf.item()), 4),
"x1": round(x1, 1), "y1": round(y1, 1),
"x2": round(x2, 1), "y2": round(y2, 1),
})
# BGR → RGB 给 Streamlit;rows 转 DataFrame 给表格组件
return annotated[:, :, ::-1], pd.DataFrame(rows)
# === 3. bytes → 临时文件 → 复用同一函数 ================================
def run_image_inference(model: YOLO, image_bytes: bytes, conf: float, suffix=".jpg"):
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as f:
f.write(image_bytes); tmp = Path(f.name)
try:
return infer_image_path(model, tmp, conf)
finally:
tmp.unlink(missing_ok=True)
# === 4. Streamlit 单图 Tab:上传 → 推理 → 双列展示 =====================
model = load_model(str(MODEL_PATH))
uploaded = st.file_uploader("上传一张包含狗的图片", type=IMAGE_UPLOAD_TYPES)
conf = st.sidebar.slider("置信度阈值", 0.05, 0.95, DEFAULT_CONF, 0.01)
if uploaded is not None:
annotated, df = run_image_inference(model, uploaded.getvalue(), conf,
suffix=Path(uploaded.name).suffix)
col1, col2 = st.columns(2)
col1.image(uploaded, caption="原图")
col2.image(annotated, caption="检测结果(带行为标签)")
st.dataframe(detections_to_display(df))
render_detection_analysis(df)
5 段解析:
@st.cache_resource把YOLO(model_path)的耗时锁在第一次访问,之后所有 session 共享同一份模型实例,避免每次切换 Tab 都重载(这对宠物店多用户场景尤其友好)。result.plot()直接返回带颜色框 + 行为类别 + 置信度的BGR ndarray,自动按class_id上色,6 种行为对应 6 种颜色,肉眼一目了然。- 把每个
box的cls / conf / xyxy拍成dict,再拼成DataFrame——后续表格、CSV 下载、行为分布柱状图、视频时间线全部复用同一份结构。 - 中英映射 + emoji 通过
apply_class_display二次处理:模型权重输出英文sitting,UI 自动映射成"🪑 端坐",方便切换到双语版本权重时无需改 UI 代码。 - Streamlit 的
cache_resource + file_uploader + dataframe组合,让一个产品级行为识别页面只需 11 行代码——这是 Streamlit 在 AI 应用快速出活的关键。

四、训练效果
模型在自建的"狗狗 6 种行为识别"数据集上完成 YOLO11n 训练并保存 best.pt。在测试集上检测效果良好,可稳定识别狗的吠叫、进食、趴卧、奔跑、端坐、站立 6 类 典型行为,已能满足家庭宠物远程关注、宠物店行为日报、收容所异常预警等场景的初筛感知使用需要。
从单图检测样例(上文「项目运行效果」截图)可以看到:在室内地板、户外草地、笼内环境等不同背景下,模型都能准确给出框 + 行为类别 + 置信度。
五、项目总结
做对了什么:
- 把"狗的检测 + 行为分类"合并成一个 6 类检测任务,避免了"先检测目标再分类行为"的两阶段管线,整体延迟降低、部署更简单;
- 用一份
project.yaml把"行业话术 / UI 主题色 / 中英类别映射 / 训练超参 / 推理阈值"全部收口,迁移到猫的行为识别、马的行为识别等场景只需替换数据集与重新训练; - 单图、批量、视频、摄像头四种输入复用同一个
infer_image_path,后期接 RTSP 摄像头流时只需把"摄像头帧"喂进来即可。
还能怎么做:
- 在数据集层面持续补充夜间 / 多狗同框 / 视角畸变(鱼眼摄像头)等场景,把"奔跑/站立"这类高动态相似行为的判别力进一步拉开;
- 接入时序信息(如 ByteTrack 跟踪 + LSTM 平滑),把单帧的瞬时行为升级成"持续 N 秒的稳定行为",更贴合主人/兽医关心的"行为时长";
- 把检测结果 + 时间戳推送到家用 IoT 看护盒子,对"长时间未进食""异常吠叫超过 X 分钟"等场景生成主动提醒。
一句话总结:YOLO11 + Streamlit 让"宠物行为视觉感知"从一个研究课题变成了"一份 yaml + 一份 best.pt + 一份 streamlit_app.py"的工程化标准动作,本文给出了一份可以直接 fork 落地的样板。