feat(intrusion): 拆分参数,消失确认3分钟,持续有人5秒才重置
- 拆分confirm_seconds为confirm_intrusion_seconds(5秒)和confirm_clear_seconds(180秒) - 入侵确认:持续检测到人5秒 → 触发告警 - 消失确认:持续无人180秒 → 自动resolve - 消失确认期间逻辑: - 短暂有人(<5秒):继续倒计时 - 持续有人(≥5秒):回到ALARMED状态 - 向后兼容:保留confirm_seconds参数
This commit is contained in:
@@ -371,16 +371,19 @@ class LeavePostAlgorithm:
|
||||
|
||||
class IntrusionAlgorithm:
|
||||
"""
|
||||
周界入侵检测算法(状态机版本 v2.0)
|
||||
周界入侵检测算法(状态机版本 v3.0)
|
||||
|
||||
状态机:
|
||||
IDLE → CONFIRMING_INTRUSION → ALARMED → CONFIRMING_CLEAR → IDLE
|
||||
|
||||
业务流程:
|
||||
1. 检测到人 → 入侵确认期(confirm_seconds,默认5秒)
|
||||
1. 检测到人 → 入侵确认期(confirm_intrusion_seconds,默认5秒)
|
||||
2. 确认入侵 → 触发告警(ALARMED状态)
|
||||
3. 人离开ROI → 入侵消失确认期(confirm_seconds,默认5秒)
|
||||
4. 确认消失 → 发送resolve事件 → 回到空闲状态
|
||||
3. 人离开ROI → 入侵消失确认期(confirm_clear_seconds,默认180秒)
|
||||
4. 消失确认期间:
|
||||
- 短暂有人(<5秒):继续倒计时
|
||||
- 持续有人(≥5秒):回到ALARMED状态
|
||||
5. 确认消失(持续无人180秒)→ 发送resolve事件 → 回到空闲状态
|
||||
"""
|
||||
|
||||
# 状态定义
|
||||
@@ -395,11 +398,20 @@ class IntrusionAlgorithm:
|
||||
def __init__(
|
||||
self,
|
||||
cooldown_seconds: int = 300,
|
||||
confirm_seconds: int = 5,
|
||||
confirm_seconds: int = 5, # 向后兼容:同时设置入侵和消失确认时间
|
||||
confirm_intrusion_seconds: Optional[int] = None, # 入侵确认时间(默认5秒)
|
||||
confirm_clear_seconds: Optional[int] = None, # 消失确认时间(默认180秒)
|
||||
target_class: Optional[str] = None,
|
||||
):
|
||||
self.cooldown_seconds = cooldown_seconds
|
||||
|
||||
# 参数兼容处理
|
||||
self.confirm_intrusion_seconds = confirm_intrusion_seconds if confirm_intrusion_seconds is not None else confirm_seconds
|
||||
self.confirm_clear_seconds = confirm_clear_seconds if confirm_clear_seconds is not None else 180
|
||||
|
||||
# 向后兼容
|
||||
self.confirm_seconds = confirm_seconds
|
||||
|
||||
self.target_class = target_class
|
||||
|
||||
# 状态变量
|
||||
@@ -410,6 +422,9 @@ class IntrusionAlgorithm:
|
||||
self._last_alarm_id: Optional[str] = None
|
||||
self._intrusion_start_time: Optional[datetime] = None
|
||||
|
||||
# CONFIRMING_CLEAR状态下检测到人的时间(用于判断是否持续5秒)
|
||||
self._person_detected_in_clear_time: Optional[datetime] = None
|
||||
|
||||
# 冷却期管理
|
||||
self.alert_cooldowns: Dict[str, datetime] = {}
|
||||
|
||||
@@ -487,7 +502,7 @@ class IntrusionAlgorithm:
|
||||
self.state = self.STATE_IDLE
|
||||
self.state_start_time = None
|
||||
logger.debug(f"ROI {roi_id}: CONFIRMING_INTRUSION → IDLE (人消失)")
|
||||
elif elapsed >= self.confirm_seconds:
|
||||
elif elapsed >= self.confirm_intrusion_seconds:
|
||||
# 入侵确认成功,检查冷却期
|
||||
cooldown_key = f"{camera_id}_{roi_id}"
|
||||
if cooldown_key not in self.alert_cooldowns or \
|
||||
@@ -534,30 +549,46 @@ class IntrusionAlgorithm:
|
||||
elapsed = (current_time - self.state_start_time).total_seconds()
|
||||
|
||||
if roi_has_person:
|
||||
# 人又出现了,回到ALARMED
|
||||
self.state = self.STATE_ALARMED
|
||||
self.state_start_time = current_time
|
||||
logger.debug(f"ROI {roi_id}: CONFIRMING_CLEAR → ALARMED (人又出现)")
|
||||
elif elapsed >= self.confirm_seconds:
|
||||
# 消失确认成功,发送resolve事件
|
||||
if self._last_alarm_id and self._intrusion_start_time:
|
||||
duration_ms = int((current_time - self._intrusion_start_time).total_seconds() * 1000)
|
||||
alerts.append({
|
||||
"alert_type": "alarm_resolve",
|
||||
"resolve_alarm_id": self._last_alarm_id,
|
||||
"duration_ms": duration_ms,
|
||||
"last_frame_time": current_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
"resolve_type": "intrusion_cleared",
|
||||
})
|
||||
# 检测到有人
|
||||
if self._person_detected_in_clear_time is None:
|
||||
# 第一次检测到人,记录时间
|
||||
self._person_detected_in_clear_time = current_time
|
||||
logger.debug(f"ROI {roi_id}: CONFIRMING_CLEAR 检测到人,开始确认(需持续{self.confirm_intrusion_seconds}秒)")
|
||||
else:
|
||||
# 持续有人,检查是否达到确认时间
|
||||
person_elapsed = (current_time - self._person_detected_in_clear_time).total_seconds()
|
||||
if person_elapsed >= self.confirm_intrusion_seconds:
|
||||
# 确认有人重新入侵,回到ALARMED
|
||||
self.state = self.STATE_ALARMED
|
||||
self.state_start_time = None
|
||||
self._person_detected_in_clear_time = None
|
||||
logger.info(f"ROI {roi_id}: CONFIRMING_CLEAR → ALARMED (确认有人重新入侵,持续{person_elapsed:.1f}秒)")
|
||||
else:
|
||||
# 没有人
|
||||
self._person_detected_in_clear_time = None # 清除临时计时
|
||||
|
||||
logger.info(f"ROI {roi_id}: 告警已解决(入侵消失)")
|
||||
# 检查是否达到消失确认时间
|
||||
if elapsed >= self.confirm_clear_seconds:
|
||||
# 消失确认成功,发送resolve事件
|
||||
if self._last_alarm_id and self._intrusion_start_time:
|
||||
duration_ms = int((current_time - self._intrusion_start_time).total_seconds() * 1000)
|
||||
alerts.append({
|
||||
"alert_type": "alarm_resolve",
|
||||
"resolve_alarm_id": self._last_alarm_id,
|
||||
"duration_ms": duration_ms,
|
||||
"last_frame_time": current_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
"resolve_type": "intrusion_cleared",
|
||||
})
|
||||
|
||||
# 重置状态
|
||||
self.state = self.STATE_IDLE
|
||||
self.state_start_time = None
|
||||
self._last_alarm_id = None
|
||||
self._intrusion_start_time = None
|
||||
logger.debug(f"ROI {roi_id}: CONFIRMING_CLEAR → IDLE (消失确认成功)")
|
||||
logger.info(f"ROI {roi_id}: 告警已解决(入侵消失,持续无人{elapsed:.1f}秒)")
|
||||
|
||||
# 重置状态
|
||||
self.state = self.STATE_IDLE
|
||||
self.state_start_time = None
|
||||
self._last_alarm_id = None
|
||||
self._intrusion_start_time = None
|
||||
self._person_detected_in_clear_time = None
|
||||
logger.debug(f"ROI {roi_id}: CONFIRMING_CLEAR → IDLE (消失确认成功)")
|
||||
|
||||
return alerts
|
||||
|
||||
@@ -571,6 +602,7 @@ class IntrusionAlgorithm:
|
||||
self.state_start_time = None
|
||||
self._last_alarm_id = None
|
||||
self._intrusion_start_time = None
|
||||
self._person_detected_in_clear_time = None
|
||||
self.alert_cooldowns.clear()
|
||||
# 向后兼容
|
||||
self.last_alert_time.clear()
|
||||
|
||||
Reference in New Issue
Block a user