aayanb09 commited on
Commit
219263b
·
verified ·
1 Parent(s): d19b9f4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -34
app.py CHANGED
@@ -1,67 +1,114 @@
1
- import json
2
- import torch
3
  import gradio as gr
4
- import numpy as np
 
 
5
  from PIL import Image
6
- from torchvision import transforms
7
 
8
- from model import FoodIngredientClassifier
 
 
 
 
9
 
10
- DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- # Load classes
13
- with open("mlb_classes.json", "r") as f:
14
- classes = json.load(f)
15
 
16
- NUM_CLASSES = len(classes)
 
 
 
17
 
18
- # Load model
19
- model = FoodIngredientClassifier(NUM_CLASSES)
20
- checkpoint = torch.load(
21
- "best_model.pth",
22
- map_location=DEVICE,
23
- weights_only=False
24
- )
25
  model.load_state_dict(checkpoint["model_state_dict"])
26
- model.to(DEVICE)
27
  model.eval()
28
 
29
- # Image preprocessing
 
 
 
 
30
  transform = transforms.Compose([
31
  transforms.Resize((224, 224)),
32
  transforms.ToTensor(),
33
  transforms.Normalize(
34
- mean=[0.485, 0.456, 0.406],
35
- std=[0.229, 0.224, 0.225]
36
  )
37
  ])
38
 
 
 
 
 
 
 
 
 
 
39
  def predict(image, threshold=0.5):
 
 
 
 
 
 
40
  image = image.convert("RGB")
41
- x = transform(image).unsqueeze(0).to(DEVICE)
42
 
43
  with torch.no_grad():
44
- logits = model(x)
45
  probs = torch.sigmoid(logits).cpu().numpy()[0]
46
 
47
- results = [
48
- (classes[i], float(probs[i]))
49
- for i in np.where(probs > threshold)[0]
50
- ]
 
 
 
51
 
52
- results.sort(key=lambda x: x[1], reverse=True)
53
- return results[:10]
54
 
55
- demo = gr.Interface(
 
 
 
56
  fn=predict,
57
  inputs=[
58
  gr.Image(type="pil", label="Upload Food Image"),
59
- gr.Slider(0.1, 0.9, value=0.5, label="Confidence Threshold")
60
  ],
61
  outputs=gr.Label(label="Detected Ingredients"),
62
- title="🍽️ Food Ingredient Detector",
63
- description="Upload a food image and detect likely ingredients using a ResNet50 multi-label model."
 
 
 
 
 
64
  )
65
 
66
  if __name__ == "__main__":
67
- demo.launch()
 
 
 
1
  import gradio as gr
2
+ import torch
3
+ import torch.nn as nn
4
+ from torchvision import models, transforms
5
  from PIL import Image
6
+ import numpy as np
7
 
8
+ # -----------------------------
9
+ # Device
10
+ # -----------------------------
11
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
12
+ print(f"Using device: {device}")
13
 
14
+ # -----------------------------
15
+ # Model definition (same as training)
16
+ # -----------------------------
17
+ class FoodIngredientClassifier(nn.Module):
18
+ def __init__(self, num_classes):
19
+ super().__init__()
20
+ self.backbone = models.resnet50(pretrained=False)
21
+ num_features = self.backbone.fc.in_features
22
+ self.backbone.fc = nn.Sequential(
23
+ nn.Dropout(0.5),
24
+ nn.Linear(num_features, 512),
25
+ nn.ReLU(),
26
+ nn.Dropout(0.3),
27
+ nn.Linear(512, num_classes)
28
+ )
29
 
30
+ def forward(self, x):
31
+ return self.backbone(x)
 
32
 
33
+ # -----------------------------
34
+ # Load checkpoint
35
+ # -----------------------------
36
+ checkpoint = torch.load("best_model.pth", map_location=device)
37
 
38
+ mlb = checkpoint["mlb"]
39
+ class_names = mlb.classes_
40
+ num_classes = len(class_names)
41
+
42
+ model = FoodIngredientClassifier(num_classes)
 
 
43
  model.load_state_dict(checkpoint["model_state_dict"])
44
+ model.to(device)
45
  model.eval()
46
 
47
+ print(f"Loaded model with {num_classes} ingredient classes")
48
+
49
+ # -----------------------------
50
+ # Image transforms
51
+ # -----------------------------
52
  transform = transforms.Compose([
53
  transforms.Resize((224, 224)),
54
  transforms.ToTensor(),
55
  transforms.Normalize(
56
+ [0.485, 0.456, 0.406],
57
+ [0.229, 0.224, 0.225]
58
  )
59
  ])
60
 
61
+ # -----------------------------
62
+ # Utility
63
+ # -----------------------------
64
+ def clean_name(name):
65
+ return name.replace("_", " ").title()
66
+
67
+ # -----------------------------
68
+ # Prediction function
69
+ # -----------------------------
70
  def predict(image, threshold=0.5):
71
+ if image is None:
72
+ return {}
73
+
74
+ if not isinstance(image, Image.Image):
75
+ image = Image.fromarray(image)
76
+
77
  image = image.convert("RGB")
78
+ input_tensor = transform(image).unsqueeze(0).to(device)
79
 
80
  with torch.no_grad():
81
+ logits = model(input_tensor)
82
  probs = torch.sigmoid(logits).cpu().numpy()[0]
83
 
84
+ results = {}
85
+ for idx, prob in enumerate(probs):
86
+ if prob >= threshold:
87
+ results[clean_name(class_names[idx])] = float(prob)
88
+
89
+ # Sort by confidence
90
+ results = dict(sorted(results.items(), key=lambda x: x[1], reverse=True))
91
 
92
+ return results
 
93
 
94
+ # -----------------------------
95
+ # Gradio UI
96
+ # -----------------------------
97
+ iface = gr.Interface(
98
  fn=predict,
99
  inputs=[
100
  gr.Image(type="pil", label="Upload Food Image"),
101
+ gr.Slider(0.1, 0.9, value=0.5, step=0.05, label="Confidence Threshold")
102
  ],
103
  outputs=gr.Label(label="Detected Ingredients"),
104
+ title="Food Ingredient Detection (Multi-Label)",
105
+ description=(
106
+ "Upload a food image to detect **multiple ingredients at once**. "
107
+ "This model is trained with multi-label classification using ResNet-50."
108
+ ),
109
+ theme=gr.themes.Soft(),
110
+ allow_flagging="never"
111
  )
112
 
113
  if __name__ == "__main__":
114
+ iface.launch()