import torch import gradio as gr import timm from torchvision import transforms as T from PIL import Image import numpy as np import cv2 from pytorch_grad_cam import GradCAMPlusPlus from pytorch_grad_cam.utils.image import show_cam_on_image # ========================================== # 1. Configuration & Setup # ========================================== class_names = ['Anger', 'Fear', 'Joy', 'Neutral'] model_name = "resnext101_32x8d" weights_path = "autism_best_model.pth" im_size = 224 mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] # Hugging Face Free Tier uses CPU device = torch.device("cpu") # ========================================== # 2. Model Loading # ========================================== def load_model(): print("Loading Model...") model = timm.create_model( model_name, pretrained=False, num_classes=len(class_names)) state_dict = torch.load(weights_path, map_location=device) model.load_state_dict(state_dict) model.to(device) model.eval() return model model = load_model() # ========================================== # 3. Preprocessing # ========================================== transform = T.Compose([ T.Resize((im_size, im_size)), T.ToTensor(), T.Normalize(mean=mean, std=std) ]) # ========================================== # 4. Inference & Grad-CAM Function # ========================================== # đŸŸĸ Fixed: Added !important to force pure black text so Dark Mode doesn't hide it waiting_text = """

âŗ Waiting for upload...

""" def predict(image): if image is None: return None, waiting_text, None # Prepare Image image = image.convert("RGB") input_tensor = transform(image).unsqueeze(0).to(device) # 1. Classification (Inside no_grad) with torch.no_grad(): outputs = model(input_tensor) probabilities = torch.nn.functional.softmax(outputs[0], dim=0) confidences = {class_names[i]: float(probabilities[i]) for i in range(len(class_names))} top_class = max(confidences, key=confidences.get) top_score = confidences[top_class] # đŸŸĸ Fixed: Forced pure black text on light blue background message = f"""

🧠 The model is {top_score*100:.1f}% confident that the primary expression is {top_class}.

""" # 2. Grad-CAM Generation (Outside no_grad because Grad-CAM requires gradients) target_layers = [model.layer4[-1].conv3] cam = GradCAMPlusPlus(model=model, target_layers=target_layers, use_cuda=False) # CPU mode # Generate heatmap grayscale_cam = cam(input_tensor=input_tensor)[0, :] # Overlay heatmap on original image rgb_img = np.array(image.resize((im_size, im_size))) / 255.0 cam_image = show_cam_on_image(rgb_img, grayscale_cam, use_rgb=True, image_weight=0.4) return confidences, message, cam_image # ========================================== # 5. Modern Gradio UI (Blocks) # ========================================== theme = gr.themes.Soft( primary_hue="indigo", secondary_hue="blue", neutral_hue="slate", font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"] ) custom_css = """ .gradio-container { background-color: #f8fafc; } .header-box { text-align: center; padding: 2rem; background: linear-gradient(135deg, #4f46e5 0%, #3b82f6 100%); border-radius: 15px; color: white; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); margin-bottom: 20px; } .header-title { font-size: 2.5rem; font-weight: 800; margin-bottom: 0.5rem; } .header-subtitle { font-size: 1.1rem; opacity: 0.9; } """ with gr.Blocks(theme=theme, css=custom_css) as demo: gr.HTML("""
✨ Facial Emotion Recognition in Autistic Children
Explainable deep learning model trained on the Dataset to analyze facial emotions of autistic children.
""") with gr.Row(): # Left Column: Inputs with gr.Column(scale=1): # đŸŸĸ Fixed: Forced Pure Black Text on White Background gr.HTML("""

📸 Upload Image

Upload a clear photo of a child's face.

""") input_image = gr.Image(type="pil", label="Input Image", elem_classes="image-box") with gr.Row(): clear_btn = gr.Button("đŸ—‘ī¸ Clear", variant="secondary") submit_btn = gr.Button("🚀 Analyze Expression", variant="primary") # Right Column: Outputs (Parallel to Input) with gr.Column(scale=1): # đŸŸĸ Fixed: Forced Pure Black Text on White Background gr.HTML("""

📊 Result Analysis & Grad-CAM Visualization

""") # Message Block output_message = gr.HTML(waiting_text) # Parallel Display for Labels and Grad-CAM image with gr.Row(): output_label = gr.Label(num_top_classes=4, label="Confidence Scores") output_cam = gr.Image(type="numpy", label="Grad-CAM Focus Map") with gr.Accordion("â„šī¸ About this Model", open=False): gr.Markdown(""" * **Architecture:** ResNeXt-101 (32x8d) * **Input Resolution:** 224x224 pixels * **Visualizer:** Grad-CAM (Highlights the impactful region) * **Note:** This tool is for research demonstration purposes and is not a clinical diagnostic tool. """) # Button Functionality submit_btn.click( fn=predict, inputs=[input_image], outputs=[output_label, output_message, output_cam] ) clear_btn.click( fn=lambda: (None, waiting_text, None), inputs=[], outputs=[input_image, output_label, output_message, output_cam] ) if __name__ == "__main__": demo.launch()