junaid17 commited on
Commit
113afd7
·
verified ·
1 Parent(s): 3f07590

Upload 7 files

Browse files
Car_damage_classifier.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
Damage_Classifier_Resnet_18.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f98bfd021148450da8745effb0c77ceb998dbdff133e3d72c62c1b1c63a0cb6f
3
+ size 44801419
Dockerfile ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ # Prevent Python from writing pyc files
4
+ ENV PYTHONDONTWRITEBYTECODE=1
5
+ ENV PYTHONUNBUFFERED=1
6
+
7
+ WORKDIR /app
8
+
9
+ # Install system dependencies (required for sklearn / xgboost)
10
+ RUN apt-get update && apt-get install -y \
11
+ build-essential \
12
+ gcc \
13
+ && rm -rf /var/lib/apt/lists/*
14
+
15
+ # Copy and install dependencies first (better caching)
16
+ COPY requirements.txt .
17
+ RUN pip install --no-cache-dir --upgrade pip \
18
+ && pip install --no-cache-dir -r requirements.txt
19
+
20
+ # Copy application code
21
+ COPY . .
22
+
23
+ # Hugging Face expects port 7860
24
+ EXPOSE 7860
25
+
26
+ # Start FastAPI
27
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File, HTTPException
2
+ from predict_helper import predict_image
3
+ from PIL import Image
4
+
5
+ app = FastAPI(title="Car Damage Detection API", version="1.0")
6
+
7
+ @app.get("/")
8
+ def read_root():
9
+ return {"status": "API is running"}
10
+
11
+ @app.post("/predict")
12
+ async def predict(image: UploadFile = File(...)):
13
+ try:
14
+ img = Image.open(image.file)
15
+ except Exception:
16
+ raise HTTPException(status_code=400, detail="Invalid image file")
17
+
18
+ prediction = predict_image(img)
19
+ return prediction
main.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from app import app as fastapi_app
3
+
4
+ # ---------------------------
5
+ # Root Gradio App
6
+ # ---------------------------
7
+ with gr.Blocks() as demo:
8
+ gr.Markdown(
9
+ """
10
+ # Car Damage Detector
11
+
12
+ Use the API endpoints directly.
13
+ """
14
+ )
15
+
16
+ # ---------------------------
17
+ # Mount FastAPI INSIDE Gradio
18
+ # ---------------------------
19
+ app = gr.mount_gradio_app(
20
+ demo, # Gradio must be the ROOT app
21
+ fastapi_app, # FastAPI is mounted inside it
22
+ path="/" # API available at /
23
+ )
predict_helper.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from torchvision import transforms
2
+ from PIL import Image
3
+ import torch
4
+ import torch.nn as nn
5
+ import torchvision.models as models
6
+
7
+ # Image transformation for inference
8
+ transform = transforms.Compose([
9
+ transforms.Resize((224, 224)), # Resize to model input size
10
+ transforms.ToTensor(), # Convert PIL image to tensor
11
+ transforms.Normalize(
12
+ mean=[0.485, 0.456, 0.406], # ImageNet mean
13
+ std=[0.229, 0.224, 0.225] # ImageNet std
14
+ )
15
+ ])
16
+
17
+ def preprocess_image(image_path):
18
+ image = Image.open(image_path).convert("RGB")
19
+ image = transform(image)
20
+ image = image.unsqueeze(0) # Add batch dimension
21
+ return image
22
+
23
+ # Initializing the model
24
+
25
+ class Car_Classifier_Resnet(nn.Module):
26
+ def __init__(self, num_classes):
27
+ super().__init__()
28
+
29
+ self.model = models.resnet18(weights="DEFAULT")
30
+
31
+ for param in self.model.parameters():
32
+ param.requires_grad = False
33
+
34
+ for param in self.model.layer4.parameters():
35
+ param.requires_grad = True
36
+
37
+ for module in self.model.modules():
38
+ if isinstance(module, nn.BatchNorm2d):
39
+ for param in module.parameters():
40
+ param.requires_grad = True
41
+
42
+ self.model.fc = nn.Sequential(
43
+ nn.Dropout(0.4),
44
+ nn.Linear(self.model.fc.in_features, num_classes)
45
+ )
46
+
47
+
48
+ def forward(self, x):
49
+ return self.model(x)
50
+
51
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
52
+
53
+ num_classes = 6
54
+ model = Car_Classifier_Resnet(num_classes).to(device)
55
+
56
+ model.load_state_dict(torch.load("Damage_Classifier_Resnet_18.pth", map_location=device))
57
+
58
+ # Prediction Function
59
+
60
+ class_names = [
61
+ "F_Breakage",
62
+ "F_Crushed",
63
+ "F_Normal",
64
+ "R_Breakage",
65
+ "R_Crushed",
66
+ "R_Normal"
67
+ ]
68
+
69
+ # Prediction Function
70
+ def predict_image(image: Image.Image):
71
+ model.eval()
72
+
73
+ image = image.convert("RGB")
74
+ image = transform(image).unsqueeze(0).to(device)
75
+
76
+ with torch.no_grad():
77
+ outputs = model(image)
78
+ probs = torch.softmax(outputs, dim=1)
79
+ conf, pred = torch.max(probs, dim=1)
80
+
81
+ pred_idx = pred.item()
82
+ confidence = conf.item()
83
+
84
+ if class_names:
85
+ return {
86
+ "class_index": pred_idx,
87
+ "class_name": class_names[pred_idx],
88
+ "confidence": round(confidence, 4)
89
+ }
90
+ else:
91
+ return {
92
+ "class_index": pred_idx,
93
+ "confidence": round(confidence, 4)
94
+ }
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi~=0.122.0
2
+ pillow~=12.0.0
3
+ torch~=2.9.1
4
+ torchvision~=0.24.1
5
+ protobuf~=6.33.1
6
+ scikit-learn~=1.4.2