DawnC commited on
Commit
a312d58
1 Parent(s): 4368b39

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -59
app.py CHANGED
@@ -251,17 +251,17 @@ def get_akc_breeds_link():
251
  # iface.launch()
252
 
253
  def format_description(description, breed):
254
- # 分別將不同的屬性分開來顯示,保持結果的可讀性
255
  if isinstance(description, dict):
256
- formatted_description = "\n".join([f"**{key}**: {value}" for key, value in description.items()])
257
  else:
258
  formatted_description = description
259
 
260
  formatted_description = f"""
261
  **Breed**: {breed}
 
262
  {formatted_description}
263
 
264
- **Want to learn more about dog breeds?**
265
  [Visit the AKC dog breeds page]({get_akc_breeds_link()}) and search for {breed} to find detailed information.
266
 
267
  *Disclaimer: The external link provided leads to the American Kennel Club (AKC) dog breeds page.
@@ -271,9 +271,7 @@ Please refer to the AKC's terms of use and privacy policy.*
271
  """
272
  return formatted_description
273
 
274
-
275
  def predict_single_dog(image):
276
- # 直接使用模型進行預測,無需通過 YOLO
277
  image_tensor = preprocess_image(image)
278
  with torch.no_grad():
279
  output = model(image_tensor)
@@ -285,21 +283,18 @@ def predict_single_dog(image):
285
  topk_probs_percent = [f"{prob.item() * 100:.2f}%" for prob in topk_probs[0]]
286
  return top1_prob, topk_breeds, topk_probs_percent
287
 
288
-
289
  def detect_multiple_dogs(image):
290
- # 使用 YOLO 檢測多隻狗
291
  results = model_yolo(image)
292
  dogs = []
293
  for result in results:
294
  for box in result.boxes:
295
- if box.cls == 16: # COCO 資料集中狗的類別是 16
296
  xyxy = box.xyxy[0].tolist()
297
  confidence = box.conf.item()
298
  cropped_image = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
299
  dogs.append((cropped_image, confidence, xyxy))
300
  return dogs
301
 
302
-
303
  def predict(image):
304
  if image is None:
305
  return "Please upload an image to start.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
@@ -308,28 +303,34 @@ def predict(image):
308
  if isinstance(image, np.ndarray):
309
  image = Image.fromarray(image)
310
 
311
- # 首先檢查圖片中是否有多隻狗
 
 
 
312
  dogs = detect_multiple_dogs(image)
313
-
314
- if len(dogs) == 0:
315
- # 沒有狗或 YOLO 未檢測到狗,使用單狗直接分類
316
- top1_prob, topk_breeds, topk_probs_percent = predict_single_dog(image)
317
- if top1_prob < 0.2:
318
- return "The image is unclear or the breed is not in the dataset. Please upload a clearer image of a dog.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
319
  breed = topk_breeds[0]
320
  description = get_dog_description(breed)
321
  formatted_description = format_description(description, breed)
322
- return formatted_description, image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
 
 
 
 
 
323
 
324
- if len(dogs) == 1:
325
- # 檢測到一隻狗時,直接分類不使用 YOLO 來節省時間
326
- top1_prob, topk_breeds, topk_probs_percent = predict_single_dog(image)
327
- breed = topk_breeds[0]
328
- description = get_dog_description(breed)
329
- formatted_description = format_description(description, breed)
330
- return formatted_description, image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
331
 
332
- # 若有多隻狗,則使用 YOLO 的檢測結果來處理
 
 
 
 
 
 
333
  explanations = []
334
  visible_buttons = []
335
  annotated_image = image.copy()
@@ -348,6 +349,7 @@ def predict(image):
348
  elif 0.2 <= top1_prob < 0.5:
349
  explanation = f"""
350
  Dog {i+1}: Detected with moderate confidence. Here are the top 3 possible breeds:
 
351
  1. **{topk_breeds[0]}** ({topk_probs_percent[0]})
352
  2. **{topk_breeds[1]}** ({topk_probs_percent[1]})
353
  3. **{topk_breeds[2]}** ({topk_probs_percent[2]})
@@ -358,51 +360,27 @@ Dog {i+1}: Detected with moderate confidence. Here are the top 3 possible breeds
358
  explanations.append(f"Dog {i+1}: The image is unclear or the breed is not in the dataset.")
359
 
360
  final_explanation = "\n\n".join(explanations)
361
- return final_explanation, annotated_image, gr.update(visible=len(visible_buttons) >= 1, value=visible_buttons[0] if visible_buttons else ""), gr.update(visible=len(visible_buttons) >= 2, value=visible_buttons[1] if len(visible_buttons) >= 2 else ""), gr.update(visible=len(visible_buttons) >= 3, value=visible_buttons[2] if len(visible_buttons) >= 3 else "")
362
 
363
  except Exception as e:
364
  return f"An error occurred: {e}", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
365
 
366
-
367
  def show_details(breed):
368
  breed_name = breed.split("More about ")[-1]
369
  description = get_dog_description(breed_name)
370
  return format_description(description, breed_name)
371
 
372
-
373
  with gr.Blocks(css="""
374
- .container {
375
- max-width: 900px;
376
- margin: 0 auto;
377
- padding: 20px;
378
- background-color: rgba(255, 255, 255, 0.9);
379
- border-radius: 15px;
380
- box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
381
- }
382
- .gr-form { display: flex; flex-direction: column; align-items: center; }
383
- .gr-box { width: 100%; max-width: 500px; }
384
- .output-markdown, .output-image {
385
- margin-top: 20px;
386
- padding: 15px;
387
- background-color: #f5f5f5;
388
- border-radius: 10px;
389
- }
390
- .examples {
391
- display: flex;
392
- justify-content: center;
393
- flex-wrap: wrap;
394
- gap: 10px;
395
- margin-top: 20px;
396
- }
397
- .examples img {
398
- width: 100px;
399
- height: 100px;
400
- object-fit: cover;
401
- }
402
  """) as iface:
403
 
404
- gr.HTML("<h1 style='font-family:Roboto; font-weight:bold; color:#2C3E50; text-align:center;'>🐶 Dog Breed Classifier 🔍</h1>")
405
- gr.HTML("<p style='font-family:Open Sans; color:#34495E; text-align:center;'>Upload a picture of a dog, and the model will predict its breed, provide detailed information, and include an extra information link!</p>")
406
 
407
  with gr.Row():
408
  input_image = gr.Image(label="Upload a dog image", type="pil")
@@ -426,7 +404,7 @@ with gr.Blocks(css="""
426
  inputs=input_image
427
  )
428
 
429
- gr.HTML('For more details on this project and other work, feel free to visit my GitHub <a href="https://github.com/Eric-Chung-0511/Learning-Record/tree/main/Data%20Science%20Projects/Dog%20Breed%20Classifier">Dog Breed Classifier</a>')
430
 
431
  if __name__ == "__main__":
432
  iface.launch()
 
251
  # iface.launch()
252
 
253
  def format_description(description, breed):
 
254
  if isinstance(description, dict):
255
+ formatted_description = "\n\n".join([f"**{key}**: {value}" for key, value in description.items()])
256
  else:
257
  formatted_description = description
258
 
259
  formatted_description = f"""
260
  **Breed**: {breed}
261
+
262
  {formatted_description}
263
 
264
+ **Want to learn more about dog breeds?**
265
  [Visit the AKC dog breeds page]({get_akc_breeds_link()}) and search for {breed} to find detailed information.
266
 
267
  *Disclaimer: The external link provided leads to the American Kennel Club (AKC) dog breeds page.
 
271
  """
272
  return formatted_description
273
 
 
274
  def predict_single_dog(image):
 
275
  image_tensor = preprocess_image(image)
276
  with torch.no_grad():
277
  output = model(image_tensor)
 
283
  topk_probs_percent = [f"{prob.item() * 100:.2f}%" for prob in topk_probs[0]]
284
  return top1_prob, topk_breeds, topk_probs_percent
285
 
 
286
  def detect_multiple_dogs(image):
 
287
  results = model_yolo(image)
288
  dogs = []
289
  for result in results:
290
  for box in result.boxes:
291
+ if box.cls == 16: # COCO dataset class for dog is 16
292
  xyxy = box.xyxy[0].tolist()
293
  confidence = box.conf.item()
294
  cropped_image = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
295
  dogs.append((cropped_image, confidence, xyxy))
296
  return dogs
297
 
 
298
  def predict(image):
299
  if image is None:
300
  return "Please upload an image to start.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
 
303
  if isinstance(image, np.ndarray):
304
  image = Image.fromarray(image)
305
 
306
+ # Always start with single dog prediction
307
+ top1_prob, topk_breeds, topk_probs_percent = predict_single_dog(image)
308
+
309
+ # Check if we need to use YOLO for multiple dogs
310
  dogs = detect_multiple_dogs(image)
311
+
312
+ if len(dogs) <= 1: # Single dog or no dog detected
 
 
 
 
313
  breed = topk_breeds[0]
314
  description = get_dog_description(breed)
315
  formatted_description = format_description(description, breed)
316
+
317
+ if top1_prob >= 0.5:
318
+ return formatted_description, image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
319
+ elif 0.2 <= top1_prob < 0.5:
320
+ explanation = f"""
321
+ Detected with moderate confidence. Here are the top 3 possible breeds:
322
 
323
+ 1. **{topk_breeds[0]}** ({topk_probs_percent[0]})
324
+ 2. **{topk_breeds[1]}** ({topk_probs_percent[1]})
325
+ 3. **{topk_breeds[2]}** ({topk_probs_percent[2]})
 
 
 
 
326
 
327
+ Click on a button below to view more information about each breed.
328
+ """
329
+ return explanation, image, gr.update(visible=True, value=f"More about {topk_breeds[0]}"), gr.update(visible=True, value=f"More about {topk_breeds[1]}"), gr.update(visible=True, value=f"More about {topk_breeds[2]}")
330
+ else:
331
+ return "The image is unclear or the breed is not in the dataset. Please upload a clearer image of a dog.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
332
+
333
+ # Multiple dogs detected, process each dog
334
  explanations = []
335
  visible_buttons = []
336
  annotated_image = image.copy()
 
349
  elif 0.2 <= top1_prob < 0.5:
350
  explanation = f"""
351
  Dog {i+1}: Detected with moderate confidence. Here are the top 3 possible breeds:
352
+
353
  1. **{topk_breeds[0]}** ({topk_probs_percent[0]})
354
  2. **{topk_breeds[1]}** ({topk_probs_percent[1]})
355
  3. **{topk_breeds[2]}** ({topk_probs_percent[2]})
 
360
  explanations.append(f"Dog {i+1}: The image is unclear or the breed is not in the dataset.")
361
 
362
  final_explanation = "\n\n".join(explanations)
363
+ return final_explanation, annotated_image, gr.update(visible=len(visible_buttons) >= 1, value=visible_buttons[0] if visible_buttons else ""), gr.update(visible=True, value=visible_buttons[1] if len(visible_buttons) >= 2 else ""), gr.update(visible=True, value=visible_buttons[2] if len(visible_buttons) >= 3 else "")
364
 
365
  except Exception as e:
366
  return f"An error occurred: {e}", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
367
 
 
368
  def show_details(breed):
369
  breed_name = breed.split("More about ")[-1]
370
  description = get_dog_description(breed_name)
371
  return format_description(description, breed_name)
372
 
373
+ # Gradio interface setup
374
  with gr.Blocks(css="""
375
+ .container { max-width: 900px; margin: auto; padding: 20px; }
376
+ .gr-box { border-radius: 15px; }
377
+ .output-markdown { margin-top: 20px; padding: 15px; background-color: #f5f5f5; border-radius: 10px; }
378
+ .examples { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
379
+ .examples img { width: 100px; height: 100px; object-fit: cover; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  """) as iface:
381
 
382
+ gr.HTML("<h1 style='text-align: center;'>🐶 Dog Breed Classifier 🔍</h1>")
383
+ gr.HTML("<p style='text-align: center;'>Upload a picture of a dog, and the model will predict its breed, provide detailed information, and include an extra information link!</p>")
384
 
385
  with gr.Row():
386
  input_image = gr.Image(label="Upload a dog image", type="pil")
 
404
  inputs=input_image
405
  )
406
 
407
+ gr.HTML('For more details on this project and other work, feel free to visit my GitHub <a href="https://github.com/Eric-Chung-0511/Learning-Record/tree/main/Data%20Science%20Projects/Dog%20Breed_Classifier">Dog Breed Classifier</a>')
408
 
409
  if __name__ == "__main__":
410
  iface.launch()