""" 徘徊检测服务 集成行为检测算法到后端服务 """ import sys import os from typing import Dict, List, Optional import logging # 添加算法模块路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'models', 'loitering_detection')) from processors import BehaviorProcessor logger = logging.getLogger(__name__) class LoiteringService: """ 徘徊检测服务 为视频流检测提供行为分析功能: - 静止检测(基于位置,无需跟踪) - 徘徊检测(基于跟踪ID) """ def __init__(self): self.processor = None self.is_initialized = False def initialize( self, stationary_threshold: float = 10.0, position_tolerance: int = 50, loitering_threshold: float = 300.0, movement_threshold: float = 5.0, enable_stationary_alert: bool = True, enable_loitering_alert: bool = True, stationary_alert_threshold: Optional[float] = None, loitering_alert_threshold: Optional[float] = None ): """ 初始化服务 Args: stationary_threshold: 静止检测阈值(秒)- 用于判断是否静止 position_tolerance: 位置容差(像素) loitering_threshold: 徘徊检测阈值(秒)- 用于判断是否徘徊 movement_threshold: 移动阈值(像素) enable_stationary_alert: 是否启用静止告警 enable_loitering_alert: 是否启用徘徊告警 stationary_alert_threshold: 静止告警阈值(秒)- 超过此时间产生告警,默认等于 stationary_threshold loitering_alert_threshold: 徘徊告警阈值(秒)- 超过此时间产生告警,默认等于 loitering_threshold """ try: self.processor = BehaviorProcessor( stationary_threshold=stationary_threshold, position_tolerance=position_tolerance, loitering_threshold=loitering_threshold, movement_threshold=movement_threshold, enable_stationary_alert=enable_stationary_alert, enable_loitering_alert=enable_loitering_alert, stationary_alert_threshold=stationary_alert_threshold if stationary_alert_threshold is not None else stationary_threshold, loitering_alert_threshold=loitering_alert_threshold if loitering_alert_threshold is not None else loitering_threshold ) self.is_initialized = True logger.info(f"徘徊检测服务初始化成功: 静止阈值={stationary_threshold}s, 告警阈值={stationary_alert_threshold or stationary_threshold}s") except Exception as e: logger.error(f"徘徊检测服务初始化失败: {e}") self.is_initialized = False def process_detections( self, detections: List[Dict], use_tracking: bool = False, track_id_key: str = 'track_id' ) -> Dict: """ 处理检测结果 Args: detections: YOLO检测结果列表 use_tracking: 是否使用跟踪ID track_id_key: 跟踪ID字段名 Returns: { 'detections': 添加行为信息的检测结果, 'alerts': 触发的告警列表, 'stats': 统计信息 } """ if not self.is_initialized or not self.processor: return { 'detections': detections, 'alerts': [], 'stats': {'error': '服务未初始化'} } try: return self.processor.process( detections=detections, use_tracking=use_tracking, track_id_key=track_id_key ) except Exception as e: logger.error(f"处理检测结果失败: {e}") return { 'detections': detections, 'alerts': [], 'stats': {'error': str(e)} } def get_stationary_persons(self) -> List[Dict]: """获取所有静止人员""" if not self.is_initialized or not self.processor: return [] return self.processor.get_stationary_persons() def get_loitering_persons(self) -> List[Dict]: """获取所有徘徊人员""" if not self.is_initialized or not self.processor: return [] return self.processor.get_loitering_persons() def reset(self): """重置检测器""" if self.processor: self.processor.reset() logger.info("徘徊检测器已重置") def get_config(self) -> Dict: """获取当前配置""" if not self.is_initialized or not self.processor: return {'error': '服务未初始化'} return self.processor.get_config() def get_stats(self) -> Dict: """获取统计信息""" if not self.is_initialized or not self.processor: return {'error': '服务未初始化'} stats = { 'stationary_count': len(self.get_stationary_persons()), 'loitering_count': len(self.get_loitering_persons()), 'config': self.get_config() } return stats # 全局服务实例 _loitering_service: Optional[LoiteringService] = None def get_loitering_service() -> LoiteringService: """获取全局徘徊检测服务实例""" global _loitering_service if _loitering_service is None: _loitering_service = LoiteringService() return _loitering_service def initialize_loitering_service(**kwargs): """初始化全局徘徊检测服务""" service = get_loitering_service() service.initialize(**kwargs) return service