feat: 人员识别与管理模块 - MediaPipe人脸检测、人脸识别、人员库管理

This commit is contained in:
2026-04-16 18:47:15 +08:00
parent 32f98ce4f3
commit 55c6ad88c8
7 changed files with 769 additions and 45 deletions

View File

@@ -5,7 +5,7 @@ Local Analyzer - 本地视觉分析(无需大模型)
功能:
- 帧间差分:检测运动
- 背景建模:检测前景物体
- 人体检测:检测人员进出
- 人员识别:检测并识别人物(新人员自动入库)
- 亮度检测:检测光线变化
- 自动判断是否需要调用大模型
"""
@@ -13,6 +13,18 @@ import cv2
import numpy as np
from pathlib import Path
import datetime
import sys
import os
# 添加项目路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
from person_manager import person_manager
HAS_PERSON_MANAGER = True
except ImportError:
HAS_PERSON_MANAGER = False
print("[LocalAnalyzer] PersonManager not available")
class LocalAnalyzer:
@@ -104,40 +116,90 @@ class LocalAnalyzer:
})
self.motion_count += 1
# 2. 人检测
human_result = self._detect_human(current_frame)
metrics['human_count'] = human_result['count']
# 2. 人检测与识别
person_result = {'persons': [], 'total_count': 0, 'new_count': 0, 'known_count': 0}
# 记录人数变化
human_count_change = human_result['count'] - self.prev_human_count
metrics['human_count_change'] = human_count_change
if human_count_change > 0:
events.append({
'event_type': '人物活动',
'description': f'检测到 {human_count_change} 人进入,当前共 {human_result["count"]}',
'confidence': '',
'source': 'local'
})
self.human_count += human_count_change
elif human_count_change < 0:
events.append({
'event_type': '人物活动',
'description': f'检测到 {abs(human_count_change)} 人离开,当前剩 {human_result["count"]}',
'confidence': '',
'source': 'local'
})
elif human_result['count'] > 0:
# 人数没变但有人
events.append({
'event_type': '人物活动',
'description': f'检测到 {human_result["count"]} 个人(无变化)',
'confidence': '',
'source': 'local'
})
# 更新前一帧人数(在 should_call_model 中更新)
# self.prev_human_count = human_result['count']
if HAS_PERSON_MANAGER:
print(f"[LocalAnalyzer] Using PersonManager for face detection...")
person_result = person_manager.analyze_image(image_path, save_new_person=True)
metrics['person_count'] = person_result['total_count']
metrics['new_persons'] = person_result['new_count']
metrics['known_persons'] = person_result['known_count']
# 记录人员变化
prev_person_count = self.prev_human_count # 用之前的变量名
person_count_change = person_result['total_count'] - prev_person_count
metrics['person_count_change'] = person_count_change
for person in person_result['persons']:
if person['is_new']:
events.append({
'event_type': '人物活动',
'description': f'新人出现: {person["name"]},当前共 {person_result["total_count"]}',
'confidence': '',
'source': 'local'
})
self.human_count += 1
else:
events.append({
'event_type': '人物活动',
'description': f'已知人员: {person["name"]},已访问 {person_manager.persons.get(person["person_id"], {}).get("visit_count", 1)}',
'confidence': '',
'source': 'local'
})
# 检测人员进出
if person_count_change > 0:
events.append({
'event_type': '人员进出',
'description': f'检测到 {person_count_change} 人进入,当前共 {person_result["total_count"]}',
'confidence': '',
'source': 'local'
})
elif person_count_change < 0:
events.append({
'event_type': '人员进出',
'description': f'检测到 {abs(person_count_change)} 人离开,当前剩 {person_result["total_count"]}',
'confidence': '',
'source': 'local'
})
# 更新前一帧人数
self.prev_human_count = person_result['total_count']
else:
# 使用传统人体检测(备用)
human_result = self._detect_human(current_frame)
metrics['human_count'] = human_result['count']
human_count_change = human_result['count'] - self.prev_human_count
metrics['human_count_change'] = human_count_change
if human_count_change > 0:
events.append({
'event_type': '人物活动',
'description': f'检测到 {human_count_change} 人进入,当前共 {human_result["count"]}',
'confidence': '',
'source': 'local'
})
self.human_count += human_count_change
elif human_count_change < 0:
events.append({
'event_type': '人物活动',
'description': f'检测到 {abs(human_count_change)} 人离开,当前剩 {human_result["count"]}',
'confidence': '',
'source': 'local'
})
elif human_result['count'] > 0:
events.append({
'event_type': '人物活动',
'description': f'检测到 {human_result["count"]} 个人(无变化)',
'confidence': '',
'source': 'local'
})
self.prev_human_count = human_result['count']
# 3. 亮度检测
brightness_result = self._detect_brightness_change(current_gray, prev_image_path)
@@ -306,23 +368,25 @@ class LocalAnalyzer:
"""判断是否需要调用大模型"""
# 条件1人数变化最重要
current_human_count = metrics.get('human_count', 0)
human_count_change = abs(current_human_count - self.prev_human_count)
current_person_count = metrics.get('person_count', metrics.get('human_count', 0))
person_count_change = metrics.get('person_count_change', metrics.get('human_count_change', 0))
# 更新前一帧人数
self.prev_human_count = current_human_count
if human_count_change >= self.config['human_count_change_threshold']:
print(f"[LocalAnalyzer] Human count changed: {self.prev_human_count} -> {current_human_count}, triggering model")
# 更新前一帧人数(如果还没更新)
if abs(person_count_change) >= self.config['human_count_change_threshold']:
print(f"[LocalAnalyzer] Person count changed: {current_person_count - person_count_change} -> {current_person_count}, triggering model")
return True
# 条件2运动面积超过阈值(排除有人但不动的情况)
# 只有在没有人变化时才用这个条件
# 条件2检测到新人
if metrics.get('new_persons', 0) > 0:
print(f"[LocalAnalyzer] New person detected: {metrics.get('new_persons', 0)}, triggering model")
return True
# 条件3运动面积超过阈值排除有人但不动的情况
if metrics.get('motion_ratio', 0) > self.config['trigger_model_threshold'] * 2:
print(f"[LocalAnalyzer] Large motion detected: {metrics.get('motion_ratio', 0):.2%}")
return True
# 条件3:亮度大幅变化(灯开关等)
# 条件4:亮度大幅变化(灯开关等)
if abs(metrics.get('brightness_change', 0)) > self.config['brightness_change_threshold'] * 2:
print(f"[LocalAnalyzer] Brightness changed: {metrics.get('brightness_change', 0)}")
return True