Files
yingshiyun/analysis/config.py
T
yuming b3608f534e feat: 新增视频分析流水线、Web界面、孤儿清理工具;修复健壮性问题
- 新增 analysis/ 模块:MOG2活动检测、YOLO人物跟踪、MediaPipe摔倒检测、Ollama活动打标、缩略图抽取
- 新增 webapp/:Flask事件浏览界面,按需HEVC→H264转码缓存
- 新增 analyze.py:7阶段状态机流水线(scan→backfill→motion→person→fall→activity→thumbnail)
- 新增 cleanup_orphans.py:清理文件已删除的数据库孤儿记录
- 修复:motion/person/activity三阶段加单视频异常兜底,避免批次中断
- 修复:ollama_client加健康检查和3次重试,num_ctx从8192降到2048
- 修复:transcode_cache加fcntl文件锁,防止并发转码同一视频
- 修复:SQLite开WAL模式+busy_timeout,支持读写并发
- 修复:sync.py ffmpeg路径改为shutil.which查找,删除automate.py死代码PYTHON
- 修复:thumbnail失败加3次重试上限,避免无限重试损坏文件
- 新增:requirements.lock锁定版本、README文档
- 更新:.gitignore排除.playwright-mcp、截图、备份文件
2026-09-18 15:52:49 +08:00

66 lines
4.8 KiB
Python

"""本地视频分析模块的集中配置:路径、阈值、模型名、词表等所有可调参数。"""
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
# 录像来源目录:recordings/{设备号}/{YYYYMMDD}/*.mp4
RECORDINGS_DIR = PROJECT_ROOT / "recordings"
# 分析结果落地位置
DB_PATH = PROJECT_ROOT / "analysis.db"
THUMBNAILS_DIR = PROJECT_ROOT / "thumbnails"
# 网页播放按需转码缓存(源文件mp4容器HEVC轨道sample entry编码标签缺失,
# 浏览器无法直接播放,第一次点击时转码为标准H264并缓存在此,避免重复转码)
TRANSCODED_DIR = PROJECT_ROOT / "transcoded"
# 活动语义打标的限定词表(供 VLM 分类 prompt 和 events.label 取值域共用)
ACTIVITY_LABELS = ["走动", "进食", "坐下", "站立", "离开", "其他"]
# Ollama 本地模型
OLLAMA_MODEL = "qwen2.5vl:7b"
# 活动窗口检测(MOG2 背景建模)参数
# 帧差法对"人物占画面小、动作幅度小"的场景(如老人在客厅整理东西)容易漏检,
# 改用 MOG2 自适应背景建模:背景随时间缓慢更新,前景掩码对小幅度/慢速运动更敏感。
MOTION_RESIZE_WIDTH = 320 # 缩放到此宽度再做背景建模,加速计算
MOTION_HISTORY = 120 # MOG2 背景模型参考的历史帧数
MOTION_VAR_THRESHOLD = 16 # 像素值与背景模型的马氏距离阈值,越小越敏感(越容易判定为前景)
MOTION_WARMUP_FRAMES = 15 # 背景模型尚未收敛的前N个采样帧不计入判断,避免开场误判为"全员活动"
MOTION_SHORT_CLIP_SEC = 2.0 # 短于此时长的视频(约占全量一半,中位时长仅0.56秒)帧数不够MOG2预热,
# 触发即录的告警片段本身就是一次完整活动,直接整段视为活动窗口,不跑MOG2
MOTION_PIXEL_RATIO = 0.015 # 一帧里前景像素(不含阴影)占比超过此值才算"有活动"
MOTION_MERGE_GAP_SEC = 1.5 # 两段活动间隔小于此秒数则合并为一段
MOTION_MIN_DURATION_SEC = 0.5 # 短于此秒数的活动段视为噪声,丢弃
MOTION_SAMPLE_STRIDE = 1 # 每隔几帧采样一次(1=逐帧,长视频可调大提速)
# 人物出现次数统计(YOLO11n 检测 + ByteTrack 跟踪)参数
# 只在 motion_filter 找出的活动窗口内跑,空场景直接跳过,省算力。
PERSON_MODEL_NAME = "yolo11n.pt" # ultralytics 官方COCO预训练权重,首次运行自动下载
PERSON_DEVICE = "mps" # M系列芯片走Metal加速
PERSON_CONF_THRESHOLD = 0.4 # 检测置信度阈值,低于此值的框直接丢弃
PERSON_SAMPLE_STRIDE = 2 # 每隔几帧检测一次(视频多为15fps,隔帧检测足够跟踪连续性)
PERSON_MIN_TRACK_DURATION_SEC = 0.3 # 持续时间短于此值的track视为误检噪声,丢弃
# 摔倒检测(MediaPipe Pose 关键点 + 规则引擎)参数
# 只在 person_tracker 已确认"有人"的时间段内跑姿态估计,空场景不跑。
# 安全信号宁可多报不漏报:判定摔倒 = 短时间内从"直立"骤变为"横躺",且横躺状态持续一段时间
# (躯干角度变水平这个单一条件区分不了"摔倒"和"弯腰/坐下",必须叠加"骤变"+"持续"两个条件)
FALL_MODEL_PATH = PROJECT_ROOT / "analysis" / "models" / "pose_landmarker_lite.task"
FALL_SAMPLE_STRIDE = 2 # 每隔几帧跑一次姿态估计
FALL_MIN_VISIBILITY = 0.5 # 关键点可见度低于此值不参与姿态计算,视为遮挡/未检出
FALL_ASPECT_RATIO_THRESH = 1.3 # 人体关键点bbox 宽/高 超过此值才可能是"横躺"
FALL_TORSO_ANGLE_UPRIGHT = 35 # 躯干(肩中点→髋中点连线)与垂直方向夹角(度),低于此值判定"直立"
FALL_TORSO_ANGLE_PRONE = 55 # 高于此值判定"趋于水平/横躺"
FALL_TRANSITION_MAX_SEC = 1.5 # "直立"变"横躺"必须在此时间内完成,排除缓慢弯腰/坐下/趟下
FALL_SUSTAIN_MIN_SEC = 1.0 # "横躺"状态至少持续这么久才确认为摔倒,排除弯腰瞬间的误判
FALL_GAP_TOLERANCE_SEC = 5.0 # 一次疑似摔倒事件期间,允许多久检测不到"横躺"样本仍视为
# 事件在继续(真实摔倒后姿态/角度常导致关键点长时间漏检,
# 不代表已经爬起来);超过此时长且中途也没等到"直立"信号,
# 才判定事件跟丢并结算
# 活动语义打标(本地 Ollama + Qwen2.5-VL 限定词表分类)参数
# 只在 motion_filter 找出的活动窗口内抽帧,VLM推理比传统CV慢得多,不能逐帧跑。
ACTIVITY_SAMPLE_INTERVAL_SEC = 2.0 # 每隔多少秒抽一帧送VLM分类
ACTIVITY_MERGE_GAP_SEC = 3.0 # 连续同标签采样点之间允许的最大间隔,超过则视为新的一段活动