nenzilea commited on
Commit
2d4062d
Β·
verified Β·
1 Parent(s): 64d35c5

Upload 2 files

Browse files

Adjustments to UI

Files changed (1) hide show
  1. app.py +88 -72
app.py CHANGED
@@ -8,7 +8,7 @@ import json
8
  # ---------------------------------------------------------------------------
9
  # Car brands β€” must match the classes the ViT model was trained on
10
  # ---------------------------------------------------------------------------
11
- CAR_BRANDS = ['BMW', 'Ferrari', 'Ford', 'Jeep', 'Lamborghini', 'Porsche', 'Rolls-Royce', 'Toyota']
12
 
13
  # ---------------------------------------------------------------------------
14
  # Load models (loaded once at startup)
@@ -38,47 +38,51 @@ def encode_image_to_base64(image_path: str) -> str:
38
 
39
  def classify_with_openai(image_path: str) -> dict:
40
  """Send image to GPT-4o and ask it to return confidence scores per brand."""
41
- api_key = os.environ.get("OPENAI_API_KEY")
42
- client = openai.OpenAI(api_key=api_key)
43
-
44
- ext = os.path.splitext(image_path)[1].lower().lstrip(".")
45
- mime_type = "image/jpeg" if ext in ("jpg", "jpeg") else f"image/{ext}"
46
- base64_image = encode_image_to_base64(image_path)
47
-
48
- prompt = (
49
- f"You are a car classification expert. Classify the car brand shown in this image. "
50
- f"The possible classes are: {', '.join(CAR_BRANDS)}. "
51
- "Respond ONLY with a valid JSON object where each key is a brand name from the list and "
52
- "each value is a confidence score between 0.0 and 1.0. All scores must sum to 1.0. "
53
- 'Example format: {"BMW": 0.05, "Ferrari": 0.85, "Ford": 0.02, ...}'
54
- )
55
-
56
- response = client.chat.completions.create(
57
- model="gpt-4o",
58
- messages=[
59
- {
60
- "role": "user",
61
- "content": [
62
- {"type": "text", "text": prompt},
63
- {
64
- "type": "image_url",
65
- "image_url": {"url": f"data:{mime_type};base64,{base64_image}"},
66
- },
67
- ],
68
- }
69
- ],
70
- max_tokens=300,
71
- )
72
-
73
- text = response.choices[0].message.content
74
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  start = text.find("{")
76
  end = text.rfind("}") + 1
77
  scores = json.loads(text[start:end])
78
  return {brand: float(scores.get(brand, 0.0)) for brand in CAR_BRANDS}
79
- except Exception:
80
- uniform = 1.0 / len(CAR_BRANDS)
81
- return {brand: uniform for brand in CAR_BRANDS}
 
 
82
 
83
 
84
  # ---------------------------------------------------------------------------
@@ -107,46 +111,64 @@ def classify_car(image):
107
  # Example images (add representative car images to example_images/)
108
  # ---------------------------------------------------------------------------
109
 
 
110
  example_images = [
111
- ["example_images/ferrari.jpg"],
112
- ["example_images/lamborghini.jpg"],
113
- ["example_images/bmw.jpg"],
114
- ["example_images/jeep.jpg"],
115
- ["example_images/ford.jpg"],
116
- ["example_images/toyota.jpg"],
117
- ["example_images/porsche.jpg"],
118
- ["example_images/rolls_royce.jpg"],
119
  ]
120
 
121
  # ---------------------------------------------------------------------------
122
  # Gradio UI
123
  # ---------------------------------------------------------------------------
124
 
125
- with gr.Blocks(title="Car Brand Classification Comparison") as demo:
126
- gr.Markdown("# Car Brand Classification β€” Model Comparison")
127
- gr.Markdown(
128
- "Upload a car image to compare predictions from three different models:\n\n"
129
- "- **Custom ViT** β€” fine-tuned on Stanford Cars (8 brand classes)\n"
130
- "- **CLIP** β€” zero-shot classification with `openai/clip-vit-large-patch14`\n"
131
- "- **OpenAI GPT-4o** β€” vision LLM classification\n\n"
132
- f"**Classes:** {', '.join(CAR_BRANDS)}"
133
- )
134
 
135
- with gr.Row():
136
- input_image = gr.Image(type="filepath", label="Upload Car Image")
137
 
138
- classify_btn = gr.Button("Classify", variant="primary")
 
 
 
 
 
139
 
 
140
  with gr.Row():
141
- with gr.Column():
142
- gr.Markdown("### Custom ViT Model")
143
- vit_output = gr.Label(num_top_classes=8, label="ViT Predictions")
144
- with gr.Column():
145
- gr.Markdown("### CLIP Zero-Shot")
146
- clip_output = gr.Label(num_top_classes=8, label="CLIP Predictions")
147
- with gr.Column():
148
- gr.Markdown("### OpenAI GPT-4o Vision")
149
- openai_output = gr.Label(num_top_classes=8, label="OpenAI Predictions")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  classify_btn.click(
152
  fn=classify_car,
@@ -154,10 +176,4 @@ with gr.Blocks(title="Car Brand Classification Comparison") as demo:
154
  outputs=[vit_output, clip_output, openai_output],
155
  )
156
 
157
- gr.Examples(
158
- examples=example_images,
159
- inputs=input_image,
160
- label="Example Images",
161
- )
162
-
163
  demo.launch()
 
8
  # ---------------------------------------------------------------------------
9
  # Car brands β€” must match the classes the ViT model was trained on
10
  # ---------------------------------------------------------------------------
11
+ CAR_BRANDS = ['BMW', 'Dodge', 'Ferrari', 'Ford', 'Jeep', 'Lamborghini', 'Porsche', 'Rolls-Royce', 'Toyota']
12
 
13
  # ---------------------------------------------------------------------------
14
  # Load models (loaded once at startup)
 
38
 
39
  def classify_with_openai(image_path: str) -> dict:
40
  """Send image to GPT-4o and ask it to return confidence scores per brand."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  try:
42
+ api_key = os.environ.get("OPENAI_API_KEY")
43
+ if not api_key:
44
+ return {"Error: OPENAI_API_KEY not set": 1.0}
45
+ client = openai.OpenAI(api_key=api_key)
46
+
47
+ ext = os.path.splitext(image_path)[1].lower().lstrip(".")
48
+ mime_type = "image/jpeg" if ext in ("jpg", "jpeg") else f"image/{ext}"
49
+ base64_image = encode_image_to_base64(image_path)
50
+
51
+ prompt = (
52
+ f"You are a car classification expert. Classify the car brand shown in this image. "
53
+ f"The possible classes are: {', '.join(CAR_BRANDS)}. "
54
+ "Respond ONLY with a valid JSON object where each key is a brand name from the list and "
55
+ "each value is a confidence score between 0.0 and 1.0. All scores must sum to 1.0. "
56
+ 'Example format: {"BMW": 0.05, "Ferrari": 0.85, "Ford": 0.02, ...}'
57
+ )
58
+
59
+ response = client.chat.completions.create(
60
+ model="gpt-4o",
61
+ messages=[
62
+ {
63
+ "role": "user",
64
+ "content": [
65
+ {"type": "text", "text": prompt},
66
+ {
67
+ "type": "image_url",
68
+ "image_url": {"url": f"data:{mime_type};base64,{base64_image}"},
69
+ },
70
+ ],
71
+ }
72
+ ],
73
+ max_tokens=300,
74
+ )
75
+
76
+ text = response.choices[0].message.content
77
  start = text.find("{")
78
  end = text.rfind("}") + 1
79
  scores = json.loads(text[start:end])
80
  return {brand: float(scores.get(brand, 0.0)) for brand in CAR_BRANDS}
81
+
82
+ except openai.AuthenticationError:
83
+ return {"Error: Invalid OpenAI API key": 1.0}
84
+ except Exception as e:
85
+ return {f"Error: {str(e)[:60]}": 1.0}
86
 
87
 
88
  # ---------------------------------------------------------------------------
 
111
  # Example images (add representative car images to example_images/)
112
  # ---------------------------------------------------------------------------
113
 
114
+ _img_dir = os.path.join(os.path.dirname(__file__), "example_images")
115
  example_images = [
116
+ [os.path.join(_img_dir, f)]
117
+ for f in sorted(os.listdir(_img_dir))
118
+ if f.lower().endswith((".jpg", ".jpeg", ".png", ".webp"))
 
 
 
 
 
119
  ]
120
 
121
  # ---------------------------------------------------------------------------
122
  # Gradio UI
123
  # ---------------------------------------------------------------------------
124
 
125
+ css = """
126
+ .title { text-align: center; margin-bottom: 0.25rem; }
127
+ .subtitle { text-align: center; color: #6b7280; margin-bottom: 1.5rem; font-size: 0.95rem; }
128
+ .model-header { font-weight: 600; font-size: 1rem; margin-bottom: 0.25rem; padding: 0.4rem 0.75rem;
129
+ border-radius: 6px; background: #f3f4f6; }
130
+ .classify-btn { max-width: 200px; margin: 0 auto; }
131
+ footer { display: none !important; }
132
+ """
 
133
 
134
+ with gr.Blocks(title="Car Brand Classification", css=css, theme=gr.themes.Soft()) as demo:
 
135
 
136
+ # Header
137
+ gr.Markdown("# πŸš— Car Brand Classification", elem_classes="title")
138
+ gr.Markdown(
139
+ "Upload a car image and compare predictions from three models side by side.",
140
+ elem_classes="subtitle"
141
+ )
142
 
143
+ # Input + button
144
  with gr.Row():
145
+ with gr.Column(scale=1):
146
+ input_image = gr.Image(
147
+ type="filepath",
148
+ label="Car Image",
149
+ height=280,
150
+ )
151
+ classify_btn = gr.Button("Classify", variant="primary", elem_classes="classify-btn")
152
+
153
+ # Results
154
+ with gr.Column(scale=2):
155
+ with gr.Row():
156
+ with gr.Column():
157
+ gr.Markdown("**Custom ViT** β€” fine-tuned", elem_classes="model-header")
158
+ vit_output = gr.Label(num_top_classes=5, label="")
159
+ with gr.Column():
160
+ gr.Markdown("**CLIP** β€” zero-shot", elem_classes="model-header")
161
+ clip_output = gr.Label(num_top_classes=5, label="")
162
+ with gr.Column():
163
+ gr.Markdown("**GPT-4o** β€” vision LLM", elem_classes="model-header")
164
+ openai_output = gr.Label(num_top_classes=5, label="")
165
+
166
+ # Examples
167
+ gr.Examples(
168
+ examples=example_images,
169
+ inputs=input_image,
170
+ label="Example Images",
171
+ )
172
 
173
  classify_btn.click(
174
  fn=classify_car,
 
176
  outputs=[vit_output, clip_output, openai_output],
177
  )
178
 
 
 
 
 
 
 
179
  demo.launch()