CoolFace
Apppublic

midlajvalappil/Real-time_Object_Detection_with_YOLO

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
error_handler.py327 linesDownload Raw Back to utils
1"""2Error Handler Module3Provides comprehensive error handling and recovery mechanisms.4"""5 6import logging7import traceback8import functools9from typing import Any, Callable, Optional10import cv211import numpy as np12 13# Configure logging14logging.basicConfig(level=logging.INFO)15logger = logging.getLogger(__name__)16 17class DetectionError(Exception):18    """Custom exception for detection-related errors."""19    pass20 21class CameraError(Exception):22    """Custom exception for camera-related errors."""23    pass24 25class ModelError(Exception):26    """Custom exception for model-related errors."""27    pass28 29def handle_exceptions(default_return=None, log_error=True):30    """31    Decorator for handling exceptions in functions.32    33    Args:34        default_return: Default value to return on exception35        log_error (bool): Whether to log the error36    """37    def decorator(func: Callable) -> Callable:38        @functools.wraps(func)39        def wrapper(*args, **kwargs):40            try:41                return func(*args, **kwargs)42            except Exception as e:43                if log_error:44                    logger.error(f"Error in {func.__name__}: {str(e)}")45                    logger.debug(traceback.format_exc())46                return default_return47        return wrapper48    return decorator49 50class ErrorHandler:51    """52    Centralized error handling and recovery system.53    """54    55    def __init__(self):56        self.error_counts = {}57        self.max_retries = 358        self.recovery_strategies = {59            'camera_error': self._recover_camera,60            'model_error': self._recover_model,61            'detection_error': self._recover_detection62        }63    64    def handle_error(self, error_type: str, error: Exception, context: dict = None) -> bool:65        """66        Handle an error with appropriate recovery strategy.67        68        Args:69            error_type (str): Type of error70            error (Exception): The exception that occurred71            context (dict): Additional context information72            73        Returns:74            bool: True if recovery was successful, False otherwise75        """76        # Log the error77        logger.error(f"{error_type}: {str(error)}")78        79        # Track error count80        self.error_counts[error_type] = self.error_counts.get(error_type, 0) + 181        82        # Check if we've exceeded max retries83        if self.error_counts[error_type] > self.max_retries:84            logger.error(f"Max retries exceeded for {error_type}")85            return False86        87        # Try recovery strategy88        if error_type in self.recovery_strategies:89            try:90                return self.recovery_strategies[error_type](error, context)91            except Exception as recovery_error:92                logger.error(f"Recovery failed for {error_type}: {str(recovery_error)}")93                return False94        95        return False96    97    def _recover_camera(self, error: Exception, context: dict = None) -> bool:98        """99        Attempt to recover from camera errors.100        101        Args:102            error (Exception): The camera error103            context (dict): Context information104            105        Returns:106            bool: True if recovery successful107        """108        logger.info("Attempting camera recovery...")109        110        if context and 'webcam' in context:111            webcam = context['webcam']112            113            # Try to reinitialize camera114            try:115                webcam.stop_capture()116                return webcam.start_capture()117            except Exception as e:118                logger.error(f"Camera recovery failed: {str(e)}")119                return False120        121        return False122    123    def _recover_model(self, error: Exception, context: dict = None) -> bool:124        """125        Attempt to recover from model errors.126        127        Args:128            error (Exception): The model error129            context (dict): Context information130            131        Returns:132            bool: True if recovery successful133        """134        logger.info("Attempting model recovery...")135        136        if context and 'detector' in context:137            detector = context['detector']138            139            # Try to reload model140            try:141                return detector.load_model()142            except Exception as e:143                logger.error(f"Model recovery failed: {str(e)}")144                return False145        146        return False147    148    def _recover_detection(self, error: Exception, context: dict = None) -> bool:149        """150        Attempt to recover from detection errors.151        152        Args:153            error (Exception): The detection error154            context (dict): Context information155            156        Returns:157            bool: True if recovery successful158        """159        logger.info("Attempting detection recovery...")160        161        # For detection errors, we can try reducing confidence threshold162        if context and 'detector' in context:163            detector = context['detector']164            current_threshold = detector.confidence_threshold165            166            if current_threshold > 0.1:167                new_threshold = max(0.1, current_threshold - 0.1)168                detector.update_confidence_threshold(new_threshold)169                logger.info(f"Reduced confidence threshold to {new_threshold}")170                return True171        172        return False173    174    def reset_error_counts(self):175        """Reset all error counts."""176        self.error_counts.clear()177        logger.info("Error counts reset")178    179    def get_error_summary(self) -> dict:180        """181        Get summary of errors encountered.182        183        Returns:184            dict: Error summary185        """186        return {187            'error_counts': self.error_counts.copy(),188            'total_errors': sum(self.error_counts.values()),189            'error_types': list(self.error_counts.keys())190        }191 192class SafeDetector:193    """194    Wrapper for YOLO detector with error handling and fallbacks.195    """196    197    def __init__(self, detector, error_handler: ErrorHandler):198        self.detector = detector199        self.error_handler = error_handler200        self.fallback_frame = None201    202    @handle_exceptions(default_return=[])203    def detect_objects(self, image: np.ndarray) -> list:204        """205        Safe object detection with error handling.206        207        Args:208            image (np.ndarray): Input image209            210        Returns:211            list: List of detections or empty list on error212        """213        try:214            return self.detector.detect_objects(image)215        except Exception as e:216            # Try to recover217            context = {'detector': self.detector}218            if self.error_handler.handle_error('detection_error', e, context):219                # Retry detection after recovery220                return self.detector.detect_objects(image)221            else:222                raise DetectionError(f"Detection failed: {str(e)}")223    224    @handle_exceptions(default_return=None)225    def draw_detections(self, image: np.ndarray, detections: list) -> Optional[np.ndarray]:226        """227        Safe detection drawing with error handling.228        229        Args:230            image (np.ndarray): Input image231            detections (list): List of detections232            233        Returns:234            Optional[np.ndarray]: Annotated image or None on error235        """236        try:237            return self.detector.draw_detections(image, detections)238        except Exception as e:239            logger.error(f"Error drawing detections: {str(e)}")240            return image  # Return original image as fallback241 242class SafeWebcam:243    """244    Wrapper for webcam capture with error handling and fallbacks.245    """246    247    def __init__(self, webcam, error_handler: ErrorHandler):248        self.webcam = webcam249        self.error_handler = error_handler250        self.last_good_frame = None251    252    @handle_exceptions(default_return=None)253    def get_frame(self) -> Optional[np.ndarray]:254        """255        Safe frame capture with error handling.256        257        Returns:258            Optional[np.ndarray]: Frame or None on error259        """260        try:261            frame = self.webcam.get_frame()262            if frame is not None:263                self.last_good_frame = frame.copy()264                return frame265            else:266                # Try to recover camera267                context = {'webcam': self.webcam}268                if self.error_handler.handle_error('camera_error', CameraError("No frame received"), context):269                    return self.webcam.get_frame()270                else:271                    # Return last good frame as fallback272                    return self.last_good_frame273        except Exception as e:274            context = {'webcam': self.webcam}275            if self.error_handler.handle_error('camera_error', e, context):276                return self.webcam.get_frame()277            else:278                return self.last_good_frame279    280    def get_fps(self) -> float:281        """Get FPS with error handling."""282        try:283            return self.webcam.get_fps()284        except Exception:285            return 0.0286    287    def is_camera_available(self) -> bool:288        """Check camera availability with error handling."""289        try:290            return self.webcam.is_camera_available()291        except Exception:292            return False293 294def create_fallback_frame(width: int = 640, height: int = 480, message: str = "Camera Error") -> np.ndarray:295    """296    Create a fallback frame to display when camera fails.297    298    Args:299        width (int): Frame width300        height (int): Frame height301        message (str): Error message to display302        303    Returns:304        np.ndarray: Fallback frame305    """306    frame = np.zeros((height, width, 3), dtype=np.uint8)307    308    # Add error message309    font = cv2.FONT_HERSHEY_SIMPLEX310    font_scale = 1311    color = (0, 0, 255)  # Red312    thickness = 2313    314    # Get text size315    text_size = cv2.getTextSize(message, font, font_scale, thickness)[0]316    317    # Center the text318    text_x = (width - text_size[0]) // 2319    text_y = (height + text_size[1]) // 2320    321    cv2.putText(frame, message, (text_x, text_y), font, font_scale, color, thickness)322    323    return frame324 325# Global error handler instance326global_error_handler = ErrorHandler()327