feat: 设置面板分组整理 + 人员时间精确到秒
This commit is contained in:
30
config.py
30
config.py
@@ -25,22 +25,26 @@ DEFAULT_CONFIG = {
|
||||
"camera_index": 0,
|
||||
"capture_interval": 60,
|
||||
"auto_analyze": True,
|
||||
"refresh_interval": 5, # 页面刷新间隔(秒)
|
||||
"display_limit": 20, # 显示最近多少条
|
||||
"refresh_interval": 5,
|
||||
"display_limit": 20,
|
||||
|
||||
# 检测算法开关
|
||||
"use_yolo": True, # YOLO 检测(最准确)
|
||||
"use_haar_cascade": False, # Haar Cascade 人体检测(备用)
|
||||
"use_mediapipe_face": True, # MediaPipe 人脸检测
|
||||
"use_face_recognition": True, # face_recognition 人脸识别
|
||||
# 人体检测设置(YOLO)
|
||||
"use_yolo": True,
|
||||
"yolo_min_confidence": 0.3,
|
||||
|
||||
# 连续性判断配置
|
||||
"confirm_frames": 3, # 连续几帧确认
|
||||
"min_detection_confidence": 0.3, # 检测置信度阈值
|
||||
# 人员识别设置
|
||||
"use_face_recognition": True,
|
||||
"use_mediapipe_face": True,
|
||||
"use_color_histogram": True,
|
||||
"face_match_threshold": 0.6,
|
||||
|
||||
# AI大模型分析开关
|
||||
"use_vision_api": False, # 是否使用大模型分析(默认关闭)
|
||||
"vision_api_trigger": "person_change", # 触发条件:person_change/motion/brightness/always
|
||||
# 连续判断设置
|
||||
"confirm_frames": 3,
|
||||
"leave_frames": 2,
|
||||
|
||||
# AI大模型分析
|
||||
"use_vision_api": False,
|
||||
"vision_api_trigger": "person_change",
|
||||
|
||||
# Vision API 配置
|
||||
"vision_api_url": os.environ.get("VISION_API_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"),
|
||||
|
||||
@@ -61,25 +61,30 @@ class PersonManager:
|
||||
|
||||
# 配置
|
||||
self.config = {
|
||||
'face_match_threshold': 0.6, # 人脸匹配阈值
|
||||
'unknown_person_id': 'unknown', # 未知人员ID
|
||||
'max_persons': 100, # 最大人员数量
|
||||
'face_match_threshold': 0.6,
|
||||
'unknown_person_id': 'unknown',
|
||||
'max_persons': 100,
|
||||
|
||||
# 方案1: 参数调整
|
||||
'mediapipe_min_confidence': 0.3, # 降低阈值,更容易检测
|
||||
'mediapipe_model_selection': 1, # 1: 远距离模型
|
||||
'haar_scale_factor': 1.05, # Haar更细粒度
|
||||
'haar_min_neighbors': 2, # 降低邻居要求
|
||||
|
||||
# 方案2: 连续性判断
|
||||
'confirm_frames': 3, # 连续几帧确认
|
||||
'leave_frames': 2, # 连续几帧消失才算离开
|
||||
# YOLO 检测参数
|
||||
'yolo_min_confidence': 0.3,
|
||||
'confirm_frames': 3,
|
||||
'leave_frames': 2,
|
||||
}
|
||||
|
||||
# 方案2: 追踪状态(连续判断)
|
||||
self.tracked_persons = {} # {person_id: {'frames': count, 'confirmed': bool}}
|
||||
self.prev_persons = [] # 前一帧检测到的人
|
||||
self.confirmation_buffer = {} # 确认缓冲区
|
||||
# 从配置文件读取参数
|
||||
try:
|
||||
from config import config_mgr
|
||||
self.config['yolo_min_confidence'] = config_mgr.get('yolo_min_confidence', 0.3)
|
||||
self.config['face_match_threshold'] = config_mgr.get('face_match_threshold', 0.6)
|
||||
self.config['confirm_frames'] = config_mgr.get('confirm_frames', 3)
|
||||
self.config['leave_frames'] = config_mgr.get('leave_frames', 2)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 追踪状态(连续判断)
|
||||
self.tracked_persons = {}
|
||||
self.prev_persons = []
|
||||
self.confirmation_buffer = {}
|
||||
|
||||
# 统计
|
||||
self.total_detections = 0
|
||||
@@ -151,6 +156,8 @@ class PersonManager:
|
||||
if self.yolo_detector is None:
|
||||
return persons
|
||||
|
||||
min_conf = self.config.get('yolo_min_confidence', 0.3)
|
||||
|
||||
try:
|
||||
results = self.yolo_detector(image, classes=[0], verbose=False) # class 0 = person
|
||||
|
||||
@@ -160,7 +167,6 @@ class PersonManager:
|
||||
conf = box.conf[0].item()
|
||||
|
||||
# 置信度过滤
|
||||
min_conf = self.config.get('mediapipe_min_confidence', 0.3)
|
||||
if conf < min_conf:
|
||||
continue
|
||||
|
||||
@@ -370,7 +376,7 @@ class PersonManager:
|
||||
dict: {'person_id': str, 'name': str, 'is_new': bool}
|
||||
"""
|
||||
if threshold is None:
|
||||
threshold = self.config['face_match_threshold']
|
||||
threshold = self.config.get('face_match_threshold', 0.6)
|
||||
|
||||
if face_encoding is None:
|
||||
return {'person_id': 'unknown', 'name': 'Unknown', 'is_new': False}
|
||||
@@ -621,8 +627,8 @@ class PersonManager:
|
||||
'person_id': p['person_id'],
|
||||
'name': p['name'],
|
||||
'visit_count': p['visit_count'],
|
||||
'first_seen': p['first_seen'],
|
||||
'last_seen': p['last_seen']
|
||||
'first_seen': p['first_seen'], # 已经精确到秒
|
||||
'last_seen': p['last_seen'], # 已经精确到秒
|
||||
}
|
||||
for p in self.persons.values()
|
||||
]
|
||||
|
||||
@@ -472,8 +472,8 @@ function loadPersonsList() {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'person-item';
|
||||
|
||||
var firstSeen = new Date(person.first_seen).toLocaleDateString();
|
||||
var lastSeen = new Date(person.last_seen).toLocaleDateString();
|
||||
var firstSeen = new Date(person.first_seen).toLocaleString();
|
||||
var lastSeen = new Date(person.last_seen).toLocaleString();
|
||||
|
||||
item.innerHTML = '<div class="person-info">' +
|
||||
'<span class="person-name">' + person.name + '</span>' +
|
||||
@@ -537,15 +537,19 @@ function loadSettingsForm() {
|
||||
document.getElementById('setting-display-limit').value = config.display_limit || 20;
|
||||
document.getElementById('setting-refresh-interval').value = config.refresh_interval || 5;
|
||||
|
||||
// Detection algorithm settings
|
||||
// Person Detection (YOLO)
|
||||
document.getElementById('setting-use-yolo').checked = config.use_yolo !== false;
|
||||
document.getElementById('setting-use-mediapipe').checked = config.use_mediapipe_face !== false;
|
||||
document.getElementById('setting-use-haar').checked = config.use_haar_cascade === true;
|
||||
document.getElementById('setting-use-face-rec').checked = config.use_face_recognition !== false;
|
||||
document.getElementById('setting-yolo-confidence').value = config.yolo_min_confidence || 0.3;
|
||||
|
||||
// Confirmation settings
|
||||
// Person Identification
|
||||
document.getElementById('setting-use-face-rec').checked = config.use_face_recognition !== false;
|
||||
document.getElementById('setting-use-mediapipe').checked = config.use_mediapipe_face !== false;
|
||||
document.getElementById('setting-use-color-hist').checked = config.use_color_histogram !== false;
|
||||
document.getElementById('setting-match-threshold').value = config.face_match_threshold || 0.6;
|
||||
|
||||
// Confirmation Settings
|
||||
document.getElementById('setting-confirm-frames').value = config.confirm_frames || 3;
|
||||
document.getElementById('setting-min-confidence').value = config.min_detection_confidence || 0.3;
|
||||
document.getElementById('setting-leave-frames').value = config.leave_frames || 2;
|
||||
|
||||
// Vision API settings
|
||||
document.getElementById('setting-use-vision-api').checked = config.use_vision_api === true;
|
||||
@@ -568,15 +572,19 @@ function saveSettings() {
|
||||
display_limit: parseInt(document.getElementById('setting-display-limit').value),
|
||||
refresh_interval: parseInt(document.getElementById('setting-refresh-interval').value),
|
||||
|
||||
// Detection algorithms
|
||||
// Person Detection (YOLO)
|
||||
use_yolo: document.getElementById('setting-use-yolo').checked,
|
||||
use_haar_cascade: document.getElementById('setting-use-haar').checked,
|
||||
use_mediapipe_face: document.getElementById('setting-use-mediapipe').checked,
|
||||
use_face_recognition: document.getElementById('setting-use-face-rec').checked,
|
||||
yolo_min_confidence: parseFloat(document.getElementById('setting-yolo-confidence').value),
|
||||
|
||||
// Confirmation settings
|
||||
// Person Identification
|
||||
use_face_recognition: document.getElementById('setting-use-face-rec').checked,
|
||||
use_mediapipe_face: document.getElementById('setting-use-mediapipe').checked,
|
||||
use_color_histogram: document.getElementById('setting-use-color-hist').checked,
|
||||
face_match_threshold: parseFloat(document.getElementById('setting-match-threshold').value),
|
||||
|
||||
// Confirmation Settings
|
||||
confirm_frames: parseInt(document.getElementById('setting-confirm-frames').value),
|
||||
min_detection_confidence: parseFloat(document.getElementById('setting-min-confidence').value),
|
||||
leave_frames: parseInt(document.getElementById('setting-leave-frames').value),
|
||||
|
||||
// Vision API
|
||||
use_vision_api: document.getElementById('setting-use-vision-api').checked,
|
||||
|
||||
@@ -138,40 +138,59 @@
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Detection Algorithms</h4>
|
||||
<h4>👤 Person Detection (YOLO)</h4>
|
||||
<div class="setting-item">
|
||||
<label>YOLO (Most Accurate):</label>
|
||||
<label>Enable YOLO:</label>
|
||||
<input type="checkbox" id="setting-use-yolo" checked>
|
||||
<span class="setting-desc">YOLOv8 nano - Best accuracy</span>
|
||||
<span class="setting-desc">Human body detection</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>MediaPipe Face:</label>
|
||||
<input type="checkbox" id="setting-use-mediapipe" checked>
|
||||
<span class="setting-desc">High precision face detection</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>Haar Cascade Body:</label>
|
||||
<input type="checkbox" id="setting-use-haar">
|
||||
<span class="setting-desc">Traditional body detection (backup)</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>Face Recognition:</label>
|
||||
<input type="checkbox" id="setting-use-face-rec" checked>
|
||||
<span class="setting-desc">Identify same person</span>
|
||||
<label>Min Confidence:</label>
|
||||
<input type="number" id="setting-yolo-confidence" value="0.3" min="0.1" max="1" step="0.1">
|
||||
<span class="setting-desc">Detection threshold (lower = more sensitive)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>Confirmation Settings</h4>
|
||||
<h4>🔍 Person Identification</h4>
|
||||
<div class="setting-item">
|
||||
<label>Face Recognition:</label>
|
||||
<input type="checkbox" id="setting-use-face-rec" checked>
|
||||
<span class="setting-desc">Best accuracy (requires dlib)</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>MediaPipe Face:</label>
|
||||
<input type="checkbox" id="setting-use-mediapipe" checked>
|
||||
<span class="setting-desc">Face landmarks detection</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>Color Histogram:</label>
|
||||
<input type="checkbox" id="setting-use-color-hist" checked>
|
||||
<span class="setting-desc">Backup method</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>Match Threshold:</label>
|
||||
<input type="number" id="setting-match-threshold" value="0.6" min="0.1" max="1" step="0.1">
|
||||
<span class="setting-desc">Lower = stricter matching</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>✅ Confirmation Settings</h4>
|
||||
<div class="setting-item">
|
||||
<label>Confirm Frames:</label>
|
||||
<input type="number" id="setting-confirm-frames" value="3" min="1" max="10">
|
||||
<span class="setting-desc">Frames to confirm detection</span>
|
||||
<span class="setting-desc">Frames to confirm change</span>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>Min Confidence:</label>
|
||||
<input type="number" id="setting-min-confidence" value="0.3" min="0.1" max="1" step="0.1">
|
||||
<span class="setting-desc">Detection confidence threshold</span>
|
||||
<label>Leave Frames:</label>
|
||||
<input type="number" id="setting-leave-frames" value="2" min="1" max="10">
|
||||
<span class="setting-desc">Frames to confirm leaving</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h4>🤖 AI Analysis</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user