Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from torchvision import models, transforms | |
| from PIL import Image | |
| # ββ Config βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| IMG_SIZE = 224 | |
| CLASS_ORDER = ['no_damage', 'low', 'medium', 'high', 'severe'] | |
| device = torch.device('cpu') | |
| # ββ Model Definition ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def build_model(num_classes): | |
| m = models.mobilenet_v2(weights=None) | |
| in_features = m.classifier[1].in_features | |
| m.classifier = nn.Sequential( | |
| nn.Dropout(0.4), | |
| nn.Linear(in_features, 256), | |
| nn.ReLU(), | |
| nn.Dropout(0.3), | |
| nn.Linear(256, num_classes), | |
| ) | |
| return m | |
| # Load Model Weights | |
| try: | |
| ckpt = torch.load('damage_classifier.pth', map_location=device) | |
| model = build_model(len(CLASS_ORDER)) | |
| model.load_state_dict(ckpt['model_state_dict']) | |
| model.to(device).eval() | |
| print("Model loaded successfully.") | |
| except Exception as e: | |
| print(f"Error loading model: {e}") | |
| model = None | |
| # ββ Transform βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| INFER_TF = transforms.Compose([ | |
| transforms.Resize((IMG_SIZE, IMG_SIZE)), | |
| transforms.ToTensor(), | |
| transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), | |
| ]) | |
| # ββ Prediction Logic ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def predict(image): | |
| if image is None or model is None: | |
| return {"Model Error or No Image": 1.0} | |
| # Ensure image is RGB | |
| image = image.convert('RGB') | |
| tensor = INFER_TF(image).unsqueeze(0).to(device) | |
| with torch.no_grad(): | |
| logits = model(tensor) | |
| probs = F.softmax(logits, dim=1).squeeze().tolist() | |
| # Gradio Label component expects a dictionary of {class_name: float_probability} | |
| prediction_dict = { | |
| class_name.replace('_', ' ').capitalize(): prob | |
| for class_name, prob in zip(CLASS_ORDER, probs) | |
| } | |
| return prediction_dict | |
| # ββ Gradio Interface ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| demo = gr.Interface( | |
| fn=predict, | |
| inputs=gr.Image(type="pil", label="Upload Drone Image"), | |
| outputs=gr.Label(num_top_classes=5, label="Predicted Damage Severity"), | |
| title="π°οΈ Disaster Damage Classifier", | |
| description="**AI-powered drone image damage assessment.** Upload a post-disaster drone image to instantly classify the structural damage severity using our fine-tuned MobileNetV2 model.", | |
| allow_flagging="never", | |
| theme=gr.themes.Soft(primary_hue="indigo") | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |