完成犯人带出检测
This commit is contained in:
@@ -876,7 +876,10 @@ def sync_videofaceprisonbiz_params():
|
|||||||
"face.min_face_size": "min_face_size",
|
"face.min_face_size": "min_face_size",
|
||||||
"face.pitch_threshold": "pitch_threshold",
|
"face.pitch_threshold": "pitch_threshold",
|
||||||
"face.yaw_threshold": "yaw_threshold",
|
"face.yaw_threshold": "yaw_threshold",
|
||||||
"face.similarity_threshold": "similarity_threshold"
|
"face.similarity_threshold": "similarity_threshold",
|
||||||
|
"face.detection_window_seconds": "detection_window_seconds",
|
||||||
|
"face.min_match_count": "min_match_count",
|
||||||
|
"face.cooldown_seconds": "cooldown_seconds"
|
||||||
}
|
}
|
||||||
|
|
||||||
updated_count = 0
|
updated_count = 0
|
||||||
@@ -925,6 +928,27 @@ def sync_videofaceprisonbiz_params():
|
|||||||
updated_count += 1
|
updated_count += 1
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error(f"无效的相似度阈值: {config_value}")
|
logger.error(f"无效的相似度阈值: {config_value}")
|
||||||
|
elif param_name == "detection_window_seconds":
|
||||||
|
try:
|
||||||
|
window_seconds = float(config_value)
|
||||||
|
video_face_prison_biz.set_detection_window_seconds(window_seconds)
|
||||||
|
updated_count += 1
|
||||||
|
except ValueError:
|
||||||
|
logger.error(f"无效的检测窗口时间: {config_value}")
|
||||||
|
elif param_name == "min_match_count":
|
||||||
|
try:
|
||||||
|
min_matches = int(config_value)
|
||||||
|
video_face_prison_biz.set_min_match_count(min_matches)
|
||||||
|
updated_count += 1
|
||||||
|
except ValueError:
|
||||||
|
logger.error(f"无效的最小匹配次数: {config_value}")
|
||||||
|
elif param_name == "cooldown_seconds":
|
||||||
|
try:
|
||||||
|
cooldown_seconds = int(config_value)
|
||||||
|
video_face_prison_biz.set_cooldown_seconds(cooldown_seconds)
|
||||||
|
updated_count += 1
|
||||||
|
except ValueError:
|
||||||
|
logger.error(f"无效的冷却时间: {config_value}")
|
||||||
|
|
||||||
logger.info(f"✅ 同步VideoFacePrisonBiz参数完成,更新了 {updated_count} 个参数(配置组ID: {prison_config.config_group_id})")
|
logger.info(f"✅ 同步VideoFacePrisonBiz参数完成,更新了 {updated_count} 个参数(配置组ID: {prison_config.config_group_id})")
|
||||||
return updated_count
|
return updated_count
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ class VideoFacePrisonBiz(BaseFaceBiz):
|
|||||||
"""
|
"""
|
||||||
super().__init__(face_analysis)
|
super().__init__(face_analysis)
|
||||||
|
|
||||||
|
# 人脸匹配跟踪配置
|
||||||
|
self.detection_window_seconds = 2.0 # 检测窗口时间(秒)
|
||||||
|
self.min_match_count = 5 # 最小匹配次数
|
||||||
|
self.cooldown_seconds = 30 # 冷却时间(秒)
|
||||||
|
|
||||||
|
# 跟踪数据结构
|
||||||
|
self.person_tracking = {} # {person_id: [timestamp1, timestamp2, ...]}
|
||||||
|
self.person_cooldown = {} # {person_id: cooldown_end_time}
|
||||||
|
|
||||||
def draw_detections(self, frame: np.ndarray, results: List[Dict]) -> np.ndarray:
|
def draw_detections(self, frame: np.ndarray, results: List[Dict]) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
重写绘制检测结果方法
|
重写绘制检测结果方法
|
||||||
@@ -64,6 +73,120 @@ class VideoFacePrisonBiz(BaseFaceBiz):
|
|||||||
|
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
|
def set_detection_window_seconds(self, window_seconds: float):
|
||||||
|
"""
|
||||||
|
设置检测窗口时间
|
||||||
|
|
||||||
|
参数:
|
||||||
|
window_seconds: 检测窗口时间(秒)
|
||||||
|
"""
|
||||||
|
self.detection_window_seconds = window_seconds
|
||||||
|
|
||||||
|
def get_detection_window_seconds(self) -> float:
|
||||||
|
"""
|
||||||
|
获取检测窗口时间
|
||||||
|
|
||||||
|
返回:
|
||||||
|
检测窗口时间(秒)
|
||||||
|
"""
|
||||||
|
return self.detection_window_seconds
|
||||||
|
|
||||||
|
def set_min_match_count(self, min_matches: int):
|
||||||
|
"""
|
||||||
|
设置最小匹配次数
|
||||||
|
|
||||||
|
参数:
|
||||||
|
min_matches: 最小匹配次数
|
||||||
|
"""
|
||||||
|
self.min_match_count = min_matches
|
||||||
|
|
||||||
|
def get_min_match_count(self) -> int:
|
||||||
|
"""
|
||||||
|
获取最小匹配次数
|
||||||
|
|
||||||
|
返回:
|
||||||
|
最小匹配次数
|
||||||
|
"""
|
||||||
|
return self.min_match_count
|
||||||
|
|
||||||
|
def set_cooldown_seconds(self, cooldown_seconds: int):
|
||||||
|
"""
|
||||||
|
设置冷却时间
|
||||||
|
|
||||||
|
参数:
|
||||||
|
cooldown_seconds: 冷却时间(秒)
|
||||||
|
"""
|
||||||
|
self.cooldown_seconds = cooldown_seconds
|
||||||
|
|
||||||
|
def get_cooldown_seconds(self) -> int:
|
||||||
|
"""
|
||||||
|
获取冷却时间
|
||||||
|
|
||||||
|
返回:
|
||||||
|
冷却时间(秒)
|
||||||
|
"""
|
||||||
|
return self.cooldown_seconds
|
||||||
|
|
||||||
|
def _cleanup_old_records(self, current_time: float):
|
||||||
|
"""
|
||||||
|
清理过期的跟踪记录
|
||||||
|
|
||||||
|
参数:
|
||||||
|
current_time: 当前时间戳
|
||||||
|
"""
|
||||||
|
# 清理过期的匹配记录
|
||||||
|
for person_id in list(self.person_tracking.keys()):
|
||||||
|
# 保留在检测窗口内的记录
|
||||||
|
self.person_tracking[person_id] = [
|
||||||
|
ts for ts in self.person_tracking[person_id]
|
||||||
|
if current_time - ts <= self.detection_window_seconds
|
||||||
|
]
|
||||||
|
|
||||||
|
# 如果记录为空,删除该person_id
|
||||||
|
if not self.person_tracking[person_id]:
|
||||||
|
del self.person_tracking[person_id]
|
||||||
|
|
||||||
|
# 清理过期的冷却记录
|
||||||
|
for person_id in list(self.person_cooldown.keys()):
|
||||||
|
if current_time > self.person_cooldown[person_id]:
|
||||||
|
del self.person_cooldown[person_id]
|
||||||
|
|
||||||
|
def _is_person_passed(self, person_id: str, current_time: float) -> bool:
|
||||||
|
"""
|
||||||
|
判断人员是否已经通过
|
||||||
|
|
||||||
|
参数:
|
||||||
|
person_id: 人员标识符
|
||||||
|
current_time: 当前时间戳
|
||||||
|
|
||||||
|
返回:
|
||||||
|
是否通过
|
||||||
|
"""
|
||||||
|
# 检查是否在冷却期内
|
||||||
|
if person_id in self.person_cooldown:
|
||||||
|
if current_time <= self.person_cooldown[person_id]:
|
||||||
|
# 还在冷却期内,忽略此人
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# 冷却期结束,删除记录
|
||||||
|
del self.person_cooldown[person_id]
|
||||||
|
|
||||||
|
# 检查是否达到最小匹配次数
|
||||||
|
if person_id in self.person_tracking:
|
||||||
|
recent_matches = [
|
||||||
|
ts for ts in self.person_tracking[person_id]
|
||||||
|
if current_time - ts <= self.detection_window_seconds
|
||||||
|
]
|
||||||
|
|
||||||
|
if len(recent_matches) >= self.min_match_count:
|
||||||
|
# 达到条件,设置冷却期
|
||||||
|
self.person_cooldown[person_id] = current_time + self.cooldown_seconds
|
||||||
|
# 清空该人员的匹配记录
|
||||||
|
del self.person_tracking[person_id]
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def process_frame(self, frame: np.ndarray) -> Tuple[np.ndarray, List[Dict], float]:
|
def process_frame(self, frame: np.ndarray) -> Tuple[np.ndarray, List[Dict], float]:
|
||||||
"""
|
"""
|
||||||
处理单帧图像
|
处理单帧图像
|
||||||
@@ -72,6 +195,10 @@ class VideoFacePrisonBiz(BaseFaceBiz):
|
|||||||
(原始帧, 识别结果列表, 处理时间ms)
|
(原始帧, 识别结果列表, 处理时间ms)
|
||||||
"""
|
"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
# 清理过期的跟踪记录
|
||||||
|
self._cleanup_old_records(current_time)
|
||||||
|
|
||||||
# 人脸检测和识别
|
# 人脸检测和识别
|
||||||
faces = self.app.get(frame)
|
faces = self.app.get(frame)
|
||||||
@@ -83,14 +210,25 @@ class VideoFacePrisonBiz(BaseFaceBiz):
|
|||||||
|
|
||||||
# 查找最佳匹配
|
# 查找最佳匹配
|
||||||
best_name, similarity = self.find_best_match(face.embedding)
|
best_name, similarity = self.find_best_match(face.embedding)
|
||||||
|
|
||||||
is_match = best_name is not None and similarity >= self.similarity_threshold
|
is_match = best_name is not None and similarity >= self.similarity_threshold
|
||||||
|
|
||||||
|
# 新增:判断是否已经通过
|
||||||
|
has_passed = False
|
||||||
|
if is_match and best_name:
|
||||||
|
has_passed = self._is_person_passed(best_name, current_time)
|
||||||
|
|
||||||
|
# 如果匹配但未通过,记录匹配时间
|
||||||
|
if is_match and not has_passed:
|
||||||
|
if best_name not in self.person_tracking:
|
||||||
|
self.person_tracking[best_name] = []
|
||||||
|
self.person_tracking[best_name].append(current_time)
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'bbox': face.bbox.astype(int).tolist(),
|
'bbox': face.bbox.astype(int).tolist(),
|
||||||
'similarity': similarity,
|
'similarity': similarity,
|
||||||
'best_match': best_name,
|
'best_match': best_name,
|
||||||
'is_match': is_match,
|
'is_match': is_match,
|
||||||
|
'has_passed': has_passed, # 新增:是否已经通过
|
||||||
'det_score': float(face.det_score),
|
'det_score': float(face.det_score),
|
||||||
'quality_metrics': quality_metrics,
|
'quality_metrics': quality_metrics,
|
||||||
'is_acceptable': is_acceptable
|
'is_acceptable': is_acceptable
|
||||||
|
|||||||
Reference in New Issue
Block a user