AapdaSetu Damage Assessment β€” ResNet50

Post-disaster building damage classifier for the AapdaSetu platform. Given a photo of a disaster-affected building, the model classifies damage severity into one of three grades and drives automated compensation assessment in the AapdaSetu relief pipeline.

Part of the AapdaSetu project (Smart India Hackathon).

Live Deployment

The full assessment service (this model + EXIF authenticity checks + pHash duplicate detection + compensation estimation) is deployed and publicly accessible:

🌐 https://aapdasetu-damage-api.onrender.com

  • Interactive demo UI: / Β· Swagger API docs: /docs Β· Health check: /health
  • Main endpoint: POST /api/assess-damage (multipart: photo, claimed_lat, claimed_lng, property_type, disaster_cutoff)
  • Production inference runs on ONNX Runtime using best.onnx from this repo (torch-free, fits Render's 512 MB free tier). Free-tier instances sleep after ~15 min idle, so the first request after a pause cold-starts in a few seconds.

Model Details

Architecture ResNet50 (ImageNet-1K V2 pretrained backbone) + custom FC head (Dropout β†’ Linear(2048, 3))
Input 224Γ—224 RGB image
Preprocessing Resize(256) β†’ CenterCrop(224) β†’ ToTensor β†’ Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
Classes MINOR, MAJOR, DESTROYED (alphabetical ImageFolder order: DESTROYED=0, MAJOR=1, MINOR=2 β€” see class_mapping.json)
Checkpoint best.pt (~271 MB, PyTorch dict β€” keys: model_state, class_to_idx, classes, epoch, val_acc, val_loss, optim_state)
ONNX export best.onnx (~94 MB, opset 17, softmax baked in, input image, output scores, dynamic batch) β€” parity with PyTorch verified (max abs diff β‰ˆ 6e-8)

Training Recipe

  • Dataset: 2,400 post-disaster building images β€” MINOR (846), MAJOR (525), DESTROYED (1,029), split 75 / 15 / 10 per class with a leak check (image hashes verified disjoint across splits β€” see leak_check.json). Dataset hosted at Divyanshu-Kumar19/aapdasetu-damage-dataset.
  • Two-phase training:
    1. Backbone frozen β€” only the new FC head trains
    2. Full fine-tuning of the entire network
  • Evaluation: 5-crop Test-Time Augmentation (TTA) on the held-out test set.

Evaluation Results

Held-out test set (244 images), with TTA:

Class Precision Recall F1 Support
DESTROYED 0.990 0.981 0.986 104
MAJOR 0.982 1.000 0.991 54
MINOR 0.977 0.977 0.977 86
Overall accuracy 98.36%

Full metrics: eval_report.json Β· Confusion matrix: confusion_matrix.png Β· ROC curves: roc_curves.png Β· Training curves: training_curves.png Β· Misclassified samples: misclassified.png Β· Training history: history.json Β· Split leak audit: leak_check.json

Quick Start β€” ONNX (recommended, CPU-friendly)

import json
import onnxruntime as ort
import numpy as np
from PIL import Image
from torchvision import transforms

mapping = json.load(open("class_mapping.json"))          # {"DESTROYED": 0, "MAJOR": 1, "MINOR": 2}
idx_to_class = {int(v): k for k, v in mapping.items()}

transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

img = Image.open("building.jpg").convert("RGB")
x = transform(img).unsqueeze(0).numpy()

sess = ort.InferenceSession("best.onnx", providers=["CPUExecutionProvider"])
probs = sess.run(["scores"], {"image": x})[0][0]          # softmax already baked in

print("Damage grade:", idx_to_class[int(probs.argmax())])
print("All scores:", {idx_to_class[i]: round(float(p), 4) for i, p in enumerate(probs)})

Quick Start β€” PyTorch (best.pt)

import torch
import torch.nn as nn
from torchvision import models, transforms
from PIL import Image

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 1. Build the exact architecture used during training
model = models.resnet50(weights=None)
model.fc = nn.Sequential(
    nn.Dropout(p=0.0),                    # training-only; inert at inference
    nn.Linear(model.fc.in_features, 3),
)

# 2. Load the checkpoint
ckpt = torch.load("best.pt", map_location=device, weights_only=True)
model.load_state_dict(ckpt["model_state"])
model.to(device).eval()

# 3. IMPORTANT β€” use the checkpoint's index->class mapping.
#    ImageFolder trained classes in ALPHABETICAL order
#    (DESTROYED=0, MAJOR=1, MINOR=2), NOT ["MINOR", "MAJOR", "DESTROYED"].
idx_to_class = {int(v): k for k, v in ckpt["class_to_idx"].items()}

# 4. Preprocess exactly like training validation
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

# 5. Predict
img = Image.open("building.jpg").convert("RGB")
x = transform(img).unsqueeze(0).to(device)
with torch.no_grad():
    probs = torch.softmax(model(x), dim=1)[0]

scores = {idx_to_class[i]: round(float(p), 4) for i, p in enumerate(probs)}
print("Damage grade:", idx_to_class[int(probs.argmax())])
print("All scores:", scores)

Download the checkpoints with:

hf download Divyanshu-Kumar19/aapdasetu-damage-assessment --local-dir ./model

Intended Use

  • Triage of post-disaster building damage photos in the AapdaSetu claim pipeline (maps grade β†’ compensation under NDRF/SDRF norms).
  • Not a substitute for a certified structural engineer's assessment.
  • Out of scope: images that are not disaster-affected buildings, and safety-critical decisions without human review.

Files in This Repository

File Description
best.pt Trained PyTorch checkpoint (state dict + metadata)
best.onnx ONNX export for CPU inference (softmax baked in) β€” used by the live deployment
class_mapping.json Class β†’ index mapping (DESTROYED=0, MAJOR=1, MINOR=2)
eval_report.json Per-class precision / recall / F1 on the test set
confusion_matrix.png Confusion matrix visualization
roc_curves.png One-vs-rest ROC curves
training_curves.png Train/val loss & accuracy curves
confidence_distribution.png Prediction confidence distribution
misclassified.png Test samples the model got wrong
history.json Per-epoch training history
leak_check.json Train/val/test split leak audit

License

MIT

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Evaluation results

  • accuracy on AapdaSetu Building Damage Dataset
    self-reported
    98.36%