Ricesuu commited on
Commit
7bb277b
Β·
verified Β·
1 Parent(s): e02aeb2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +28 -26
app.py CHANGED
@@ -4,12 +4,13 @@ import timm
4
  import torchvision.transforms as T
5
  from PIL import Image
6
  import numpy as np
 
7
  import json, os
8
 
9
  # ------------------------------
10
  # CONFIGURATION
11
  # ------------------------------
12
- DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
13
  NUM_CLASSES = 200
14
 
15
  MODEL_PATHS = {
@@ -23,13 +24,19 @@ MODEL_NAMES = {
23
  }
24
 
25
  # ------------------------------
26
- # LOAD CLASS NAMES (JSON or TXT)
27
  # ------------------------------
28
  CLASS_NAMES = []
 
29
  if os.path.exists("class_names.json"):
30
  try:
31
  with open("class_names.json", "r") as f:
32
- CLASS_NAMES = json.load(f)
 
 
 
 
 
33
  print(f"βœ… Loaded {len(CLASS_NAMES)} class names from class_names.json")
34
  except Exception as e:
35
  print(f"⚠️ Error reading class_names.json: {e}")
@@ -66,17 +73,17 @@ def get_model(model_name):
66
  # ------------------------------
67
  def predict(image, model_choice):
68
  if image is None:
69
- return None, "Please upload an image."
70
 
71
  model = get_model(model_choice)
72
 
73
- # Ensure image is valid RGB
74
  try:
75
  image = image.convert("RGB")
76
  except Exception as e:
77
- return None, f"❌ Error reading image: {e}"
78
 
79
- # Pick reasonable size per model
80
  size = 300 if "b3" in model_choice.lower() else 384
81
  preprocess = T.Compose([
82
  T.Resize((size, size)),
@@ -86,7 +93,6 @@ def predict(image, model_choice):
86
  ])
87
  img_tensor = preprocess(image).unsqueeze(0).to(DEVICE)
88
 
89
- # Inference
90
  with torch.no_grad():
91
  logits = model(img_tensor)
92
  probs = torch.nn.functional.softmax(logits, dim=1)[0]
@@ -95,19 +101,19 @@ def predict(image, model_choice):
95
  indices = top5.indices.cpu().numpy().tolist()
96
  scores = top5.values.cpu().numpy().tolist()
97
 
98
- # Map indices to class names
99
- if CLASS_NAMES and len(CLASS_NAMES) >= max(indices) + 1:
100
  names = [CLASS_NAMES[i] for i in indices]
101
  else:
102
  names = [f"Class {i}" for i in indices]
103
 
104
- # Result table
105
- result_table = {
106
  "Class": names,
107
  "Confidence (%)": [round(s * 100, 2) for s in scores]
108
- }
109
 
110
- return result_table, f"βœ… Prediction complete using {model_choice}"
111
 
112
  # ------------------------------
113
  # GRADIO INTERFACE
@@ -117,7 +123,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
117
  """
118
  # 🐦 Bird Species Classifier
119
  Upload a bird image or use your camera to identify its species.
120
- Select a model and view the top-5 predictions with confidence scores.
121
  """
122
  )
123
 
@@ -133,26 +139,22 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
133
  btn = gr.Button("πŸ” Classify")
134
 
135
  with gr.Column(scale=1):
136
- df_out = gr.Dataframe(headers=["Class", "Confidence (%)"],
137
- label="Top-5 Predictions")
138
  status = gr.Textbox(label="Status", interactive=False)
139
 
140
- btn.click(fn=predict,
141
- inputs=[img_in, model_sel],
142
  outputs=[df_out, status])
143
 
144
  gr.Markdown(
145
  """
146
  ---
147
- ### πŸ’‘ Tips
148
- - Use **EfficientNet-B3** for faster inference.
149
- - Use **EfficientNetV2-S (in21k)** for higher accuracy.
150
- - Images of any size or orientation are automatically resized.
151
  """
152
  )
153
 
154
- # ------------------------------
155
- # LAUNCH APP
156
- # ------------------------------
157
  if __name__ == "__main__":
158
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
4
  import torchvision.transforms as T
5
  from PIL import Image
6
  import numpy as np
7
+ import pandas as pd
8
  import json, os
9
 
10
  # ------------------------------
11
  # CONFIGURATION
12
  # ------------------------------
13
+ DEVICE = "cpu"
14
  NUM_CLASSES = 200
15
 
16
  MODEL_PATHS = {
 
24
  }
25
 
26
  # ------------------------------
27
+ # LOAD CLASS NAMES (supports JSON or TXT)
28
  # ------------------------------
29
  CLASS_NAMES = []
30
+
31
  if os.path.exists("class_names.json"):
32
  try:
33
  with open("class_names.json", "r") as f:
34
+ data = json.load(f)
35
+ if isinstance(data, dict):
36
+ # some JSONs store indices as keys
37
+ CLASS_NAMES = [v for _, v in sorted(data.items(), key=lambda x: int(x[0]))]
38
+ elif isinstance(data, list):
39
+ CLASS_NAMES = data
40
  print(f"βœ… Loaded {len(CLASS_NAMES)} class names from class_names.json")
41
  except Exception as e:
42
  print(f"⚠️ Error reading class_names.json: {e}")
 
73
  # ------------------------------
74
  def predict(image, model_choice):
75
  if image is None:
76
+ return pd.DataFrame(), "Please upload an image."
77
 
78
  model = get_model(model_choice)
79
 
80
+ # Ensure RGB
81
  try:
82
  image = image.convert("RGB")
83
  except Exception as e:
84
+ return pd.DataFrame(), f"❌ Error reading image: {e}"
85
 
86
+ # Resize dynamically
87
  size = 300 if "b3" in model_choice.lower() else 384
88
  preprocess = T.Compose([
89
  T.Resize((size, size)),
 
93
  ])
94
  img_tensor = preprocess(image).unsqueeze(0).to(DEVICE)
95
 
 
96
  with torch.no_grad():
97
  logits = model(img_tensor)
98
  probs = torch.nn.functional.softmax(logits, dim=1)[0]
 
101
  indices = top5.indices.cpu().numpy().tolist()
102
  scores = top5.values.cpu().numpy().tolist()
103
 
104
+ # Map to readable names
105
+ if CLASS_NAMES and len(CLASS_NAMES) > max(indices):
106
  names = [CLASS_NAMES[i] for i in indices]
107
  else:
108
  names = [f"Class {i}" for i in indices]
109
 
110
+ # Make a DataFrame (this avoids 'undefined' issue)
111
+ df = pd.DataFrame({
112
  "Class": names,
113
  "Confidence (%)": [round(s * 100, 2) for s in scores]
114
+ })
115
 
116
+ return df, f"βœ… Prediction complete using {model_choice}"
117
 
118
  # ------------------------------
119
  # GRADIO INTERFACE
 
123
  """
124
  # 🐦 Bird Species Classifier
125
  Upload a bird image or use your camera to identify its species.
126
+ Supports multiple EfficientNet models and displays top-5 predictions.
127
  """
128
  )
129
 
 
139
  btn = gr.Button("πŸ” Classify")
140
 
141
  with gr.Column(scale=1):
142
+ df_out = gr.Dataframe(label="Top-5 Predictions",
143
+ interactive=False)
144
  status = gr.Textbox(label="Status", interactive=False)
145
 
146
+ btn.click(fn=predict, inputs=[img_in, model_sel],
 
147
  outputs=[df_out, status])
148
 
149
  gr.Markdown(
150
  """
151
  ---
152
+ ### πŸ’‘ Notes
153
+ - Works with **any image size or format** (auto-resized).
154
+ - **EfficientNet-B3:** fast inference
155
+ - **EfficientNetV2-S:** higher accuracy
156
  """
157
  )
158
 
 
 
 
159
  if __name__ == "__main__":
160
  demo.launch(server_name="0.0.0.0", server_port=7860)