基于 YOLO11 的宠物猫日常行为识别系统
一套面向宠物家庭、猫舍寄养与宠物医院观察场景的视觉行为识别方案,使用 YOLO11n + Streamlit 构建,可实时识别"趴卧 / 坐姿 / 睡眠 / 站立"四类猫咪日常行为,辅助饮食、活动量与健康洞察。
一、背景
1.1 行业痛点
养猫家庭和猫舍寄养机构普遍面临三个问题:
- 白天看不到猫——上班期间想知道主子在干嘛,只能事后回看监控录像;
- 健康预警靠经验——猫的厌食、活动量骤降往往晚发现两三天,错过最佳干预窗口;
- 远程关怀缺手段——传统宠物相机只能"看见画面",无法对行为做结构化分析。
本项目把"看视频"升级为"读行为":摄像头采集 → YOLO11 检测 → 行为分类汇总,给铲屎官、猫舍管理员和宠物医生一个可量化、可告警的猫咪行为台账。

数据集来自真实室内场景,约 2000 张高质量标注图,覆盖不同光照、不同背景,按 YOLO 格式组织(train / valid / test),四个类别 nc=4:趴卧 / 坐姿 / 睡眠 / 站立。
视频演示与源码 下载

包含: 📦完整项目源码 📦 预训练 模型权重
🗂️数据集
1.2 项目运行效果
Web 界面总览(紫橙撞色的宠物科技风,侧栏聚合品类、场景、部署信息):

单张图片识别效果(左原图,右标注图;下方为类别统计与置信度分布):

批量图片行为分析:

1.3 项目介绍
创新点 / 亮点
| 维度 | 说明 |
|---|---|
| 行为粒度细 | 四类静态行为(趴/坐/睡/站),可作为长期活动量统计的基础原子 |
| 配置即业务 | project.yaml 描述行业、场景、部署、行为亮点,前端 0 代码定制品牌 |
| 中文类名 | 训练就用中文标签,前端无需翻译,对非技术用户更友好 |
| 多源接入 | 同一 UI 支持单图、批量、视频、摄像头四种模式,零部署门槛 |
系统功能概览
- 单张图片识别:上传图片即得标注图 + 行为分布 + 类别置信度
- 批量图片识别:多图或 ZIP 上传,自动汇总猫咪当天主要行为占比
- 视频行为分析:逐帧识别 + 时间线分布,导出标注视频与行为明细 CSV
- 摄像头实时检测:浏览器拉本机摄像头,单帧推理输出实时行为
技术栈
| 层级 | 技术选型 |
|---|---|
| 检测模型 | YOLO11n(Ultralytics) |
| Web 框架 | Streamlit |
| 图像处理 | OpenCV、Pillow |
| 数据 / 图表 | Pandas、Streamlit 内置图表 |
| 视频编解码 | imageio-ffmpeg |
| 部署 | Python 3.9+,本地 / 容器 / 边缘盒子 均可 |
类别定义:nc=4,names=['趴卧','坐姿','睡眠','站立']。
二、设计框架
系统架构
┌────────────────────────────────────────────────────────────┐
│ 用户浏览器(铲屎官 / 猫舍管理员) │
│ 单张图片 │ 批量图片 │ 视频 │ 摄像头 │
└──────────────────────┬─────────────────────────────────────┘
│ HTTP / WebSocket
┌──────────────────────▼─────────────────────────────────────┐
│ Streamlit App (app/streamlit_app.py) │
│ · 模式路由(st.radio) │
│ · 上传 / 预览 / 行为分布图 │
│ · 行业品牌渲染(project.yaml 驱动) │
└──────────────────────┬─────────────────────────────────────┘
│ model.predict(conf=0.25, iou=0.7)
┌──────────────────────▼─────────────────────────────────────┐
│ YOLO11n 推理引擎 │
│ Backbone (C2f + SPPF) → Neck (FPN + PAN) → Decoupled Head │
│ + DFL(分布式回归) → NMS │
└──────────────────────┬─────────────────────────────────────┘
│ result.boxes (cls, conf, xyxy)
┌──────────────────────▼─────────────────────────────────────┐
│ 后处理:类别映射 → DataFrame 明细 → 行为占比 / 置信度 │
└────────────────────────────────────────────────────────────┘
YOLO11 网络结构(沿用 v8 主干,更轻更深)
- Backbone:
Conv + C2f堆叠下采样 5 次,末端SPPF融合多尺度特征 - Neck:
FPN(自顶向下语义)+PAN(自底向上定位)双向特征金字塔 - Head:解耦头 + DFL(分布回归),小目标 / 模糊轮廓定位更稳
- 损失:BCE(分类)+ CIoU + DFL(回归)
检测流程:图像/帧 → letterbox 至 imgsz=640 → 推理 → 置信度过滤(conf=0.25) → NMS(iou=0.7) → 类别映射 → 前端图表渲染。
三、代码结构(核心 50 行 + 解析)
项目结构:
宠物猫行为识别/
├── app/streamlit_app.py # Streamlit Web 入口
├── configs/project.yaml # 业务配置(行业、场景、部署、UI 主题)
├── model/best.pt # YOLO11n 训练权重
├── scripts/ # 训练 / 评测 / 导出脚本
├── data/dataset/ # train / valid / test
└── 猫的四种行为检测train_CH_yolo11n/train/ # 训练产物
核心 50 行(精简版):
from pathlib import Path
import pandas as pd
import streamlit as st
import yaml
from ultralytics import YOLO
PROJECT_ROOT = Path(__file__).resolve().parent.parent
CONFIG_PATH = PROJECT_ROOT / "configs" / "project.yaml"
MODEL_PATH = PROJECT_ROOT / "model" / "best.pt"
APP_CONFIG = yaml.safe_load(open(CONFIG_PATH, "r", encoding="utf-8"))
APP_META = APP_CONFIG.get("app", {
})
INFER = APP_CONFIG.get("inference", {
})
DEFAULT_CONF = float(INFER.get("conf", 0.25)) # project.yaml 驱动
DEFAULT_IOU = float(INFER.get("iou", 0.7))
@st.cache_resource(show_spinner=False)
def load_model(model_path: str) -> YOLO:
return YOLO(model_path) # 全局缓存,避免反复加载
def infer_image(model: YOLO, image_path: Path, conf: float):
result = model.predict(str(image_path), conf=conf, iou=DEFAULT_IOU, verbose=False)[0]
annotated = result.plot() # 直接拿到带框图
rows = []
if result.boxes is not None:
for box in result.boxes:
cls_id = int(box.cls.item())
rows.append({
"class_id": cls_id,
"class_name": result.names[cls_id], # '趴卧' / '坐姿' / '睡眠' / '站立'
"confidence": round(float(box.conf.item()), 4),
"x1": float(box.xyxy[0][0]), "y1": float(box.xyxy[0][1]),
"x2": float(box.xyxy[0][2]), "y2": float(box.xyxy[0][3]),
})
return annotated[:, :, ::-1], pd.DataFrame(rows) # BGR -> RGB
# ---------------- Streamlit 主流程 ----------------
st.set_page_config(page_title=APP_META.get("title"), layout="wide")
model = load_model(str(MODEL_PATH))
conf = st.sidebar.slider("置信度阈值", 0.05, 0.95, DEFAULT_CONF, 0.05)
mode = st.radio("输入类型", ["单张图片", "批量图片", "视频", "摄像头"], horizontal=True)
if mode == "单张图片":
uploaded = st.file_uploader("上传待检测图片", type=["jpg", "png", "jpeg"])
if uploaded is not None:
# 写到临时文件再走 infer_image,省去手动 numpy decode
tmp = Path("/tmp") / uploaded.name
tmp.write_bytes(uploaded.getvalue())
annotated, df = infer_image(model, tmp, conf)
col1, col2 = st.columns(2)
col1.image(uploaded.getvalue(), caption="原图", width="stretch")
col2.image(annotated, caption="检测结果", width="stretch")
st.bar_chart(df["class_name"].value_counts())
st.dataframe(df, width="stretch")
逐段解析
yaml.safe_load(project.yaml)+INFER.get(...):所有推理参数(conf、iou、批量上限)都从配置读取,调超参不用改代码,对运营友好。@st.cache_resource缓存YOLO(model_path):避免 Streamlit 每次交互重建模型,首屏后单图响应稳定在 100ms 内。model.predict一行完成"预处理 + 推理 + NMS",返回Results,.plot()直接生成带标签框的 ndarray,配合[:, :, ::-1]转回 RGB 喂给 Streamlit。result.boxes迭代得到cls / conf / xyxy,组成 DataFrame:既可前端展示,也可一键导出 CSV 入库,做长期行为趋势分析。st.radio+if/elif路由四种输入模式,模型一次加载、四个入口共享,新增"摄像头流"等模式只需复用infer_image。
四、训练效果
训练采用 YOLO11n 预训练权重 微调 ,epochs=200, imgsz=640, batch=16, patience=50。best.pt 对应的最佳指标:
| 指标 | 数值 |
|---|---|
| Precision (B) | 0.885 |
| Recall (B) | 0.819 |
| mAP@0.5 | 0.879 |
| mAP@0.5:0.95 | 0.680 |

PR 曲线(mAP@0.5 = 0.879,4 类整体表现均衡):

归一化混淆矩阵(对角线主导,"睡眠 / 趴卧"之间有轻度混淆——两类静态姿态在某些视角下确实视觉接近,符合预期):

类别分布:

从分布图看,四类样本基本均衡,目标尺寸集中在画面中等区域,模型不会因尺度极端而退化。
五、项目总结
做对了什么
- 业务话术、行业、部署形态全在
project.yaml,前端render_industry_panel自动渲染品牌区,同一套代码可换皮卖到不同宠物 SaaS。 - 中文类别 + 紫橙撞色 UI,对非技术用户(猫舍管理员、铲屎官)友好,不需要任何前置培训。
- 推理函数返回
(annotated, DataFrame),单图 / 批量 / 视频 / 摄像头复用同一份逻辑,扩展新模式成本极低。
还能怎么做
- 引入时序模型(LSTM / TimesNet)做行为序列分类,把单帧"坐姿"汇聚成"持续端坐 30 分钟"等可告警事件。
- 加入个体重识别(Re-ID),多猫家庭可分别为每只猫建立行为画像。
- 结合营养数据 + 体重秤,把行为占比与健康指标联动,做"饮食 / 活动 / 体重"三联监测。
- 边缘部署:YOLO11n 单帧 5ms@CPU、< 1ms@GPU,再做 INT8 量化后可塞进宠物摄像头本地芯片。
一句话总结
YOLO11n + Streamlit 把"看监控"升级为"读行为",给宠物科技产品一个可立即落地、可配置化复用的视觉底座,从家庭萌宠到连锁猫舍都能一键铺开。