Spaces:
Build error
Build error
| """ | |
| Animal Type Classification App | |
| A robust Gradio application for classifying animals using YOLOv8 | |
| """ | |
| import gradio as gr | |
| from ultralytics import YOLO | |
| from PIL import Image | |
| import numpy as np | |
| import logging | |
| import sys | |
| import os | |
| from typing import Optional, Tuple | |
| # ============================================================================ | |
| # LOGGING CONFIGURATION | |
| # ============================================================================ | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', | |
| handlers=[ | |
| logging.FileHandler('animal_classifier.log'), | |
| logging.StreamHandler(sys.stdout) | |
| ] | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # ============================================================================ | |
| # CONFIGURATION | |
| # ============================================================================ | |
| MODEL_PATH = "best_animal_classifier.pt" | |
| CLASS_NAMES = ["butterfly", "chicken", "elephant", "horse", "spider", "squirrel"] | |
| CONFIDENCE_THRESHOLD = 0.5 | |
| MIN_DETECTIONS = 1 | |
| # ============================================================================ | |
| # GLOBAL MODEL VARIABLE | |
| # ============================================================================ | |
| model = None | |
| # ============================================================================ | |
| # MODEL INITIALIZATION WITH EXCEPTION HANDLING | |
| # ============================================================================ | |
| def load_model() -> Optional[YOLO]: | |
| """ | |
| Load the YOLO model with comprehensive error handling. | |
| Returns: | |
| YOLO: Loaded model object or None if loading fails | |
| """ | |
| global model | |
| try: | |
| logger.info(f"Attempting to load model from: {MODEL_PATH}") | |
| # Check if model file exists | |
| if not os.path.exists(MODEL_PATH): | |
| logger.error(f"Model file not found at: {MODEL_PATH}") | |
| raise FileNotFoundError( | |
| f"Model file '{MODEL_PATH}' does not exist. " | |
| f"Please ensure the file is in the correct location." | |
| ) | |
| # Check if file has read permissions | |
| if not os.access(MODEL_PATH, os.R_OK): | |
| logger.error(f"No read permission for model file: {MODEL_PATH}") | |
| raise PermissionError( | |
| f"No read permission for model file: {MODEL_PATH}" | |
| ) | |
| # Load the model | |
| model = YOLO(MODEL_PATH) | |
| logger.info("β Model loaded successfully!") | |
| return model | |
| except FileNotFoundError as e: | |
| logger.error(f"FileNotFoundError: {e}") | |
| return None | |
| except PermissionError as e: | |
| logger.error(f"PermissionError: {e}") | |
| return None | |
| except Exception as e: | |
| logger.error(f"Unexpected error loading model: {type(e).__name__}: {e}") | |
| return None | |
| # ============================================================================ | |
| # CLASSIFICATION FUNCTION WITH ROBUST ERROR HANDLING | |
| # ============================================================================ | |
| def classify_animal(image: Optional[np.ndarray]) -> str: | |
| """ | |
| Classify an animal in the provided image using YOLOv8. | |
| Args: | |
| image (Optional[np.ndarray]): Input image as numpy array or PIL Image | |
| Returns: | |
| str: Classification result with confidence score or error message | |
| """ | |
| try: | |
| # ========== INPUT VALIDATION ========== | |
| if image is None: | |
| logger.warning("No image provided") | |
| return "β Error: No image provided. Please upload an image." | |
| logger.info("Image received for classification") | |
| # ========== MODEL AVAILABILITY CHECK ========== | |
| if model is None: | |
| logger.error("Model is not loaded") | |
| return "β Critical Error: Model not loaded. Please restart the application." | |
| # ========== IMAGE TYPE CONVERSION ========== | |
| try: | |
| if isinstance(image, np.ndarray): | |
| # Validate numpy array dimensions | |
| if image.ndim not in [2, 3, 4]: | |
| logger.error(f"Invalid image dimensions: {image.ndim}") | |
| return "β Error: Invalid image dimensions. Expected 2D, 3D, or 4D array." | |
| # Validate data type | |
| if not np.issubdtype(image.dtype, np.integer): | |
| logger.warning(f"Unexpected image dtype: {image.dtype}, attempting conversion") | |
| image = image.astype('uint8') | |
| # Convert to PIL Image | |
| image_pil = Image.fromarray(image.astype('uint8')) | |
| logger.debug("Converted numpy array to PIL Image") | |
| elif isinstance(image, Image.Image): | |
| image_pil = image | |
| lo | |