DawnC commited on
Commit
1ce85e8
1 Parent(s): b663fd0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +222 -128
app.py CHANGED
@@ -325,117 +325,117 @@ async def detect_multiple_dogs(image, conf_threshold=0.25, iou_threshold=0.4, me
325
  # 如果沒有檢測到狗狗,返回整張圖片
326
  return [(image, 1.0, [0, 0, image.width, image.height])]
327
 
328
- async def predict(image):
329
- if image is None:
330
- return "Please upload an image to start.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None
331
 
332
- try:
333
- if isinstance(image, np.ndarray):
334
- image = Image.fromarray(image)
335
 
336
- dogs = await detect_multiple_dogs(image)
337
 
338
- # 如果沒有檢測到狗狗或只檢測到一隻,使用整張圖像進行分類
339
- if len(dogs) <= 1:
340
- top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
341
- if top1_prob >= 0.5:
342
- return await process_single_dog(image)
343
- else:
344
- dogs = [(image, 1.0, [0, 0, image.width, image.height])]
345
 
346
- # 多狗情境處理保持不變
347
- color_list = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF', '#800080', '#FFA500']
348
- explanations = []
349
- buttons = []
350
- annotated_image = image.copy()
351
- draw = ImageDraw.Draw(annotated_image)
352
- font = ImageFont.load_default()
353
 
354
- for i, (cropped_image, _, box) in enumerate(dogs):
355
- top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(cropped_image)
356
- color = color_list[i % len(color_list)]
357
- draw.rectangle(box, outline=color, width=3)
358
- draw.text((box[0], box[1]), f"Dog {i+1}", fill=color, font=font)
359
 
360
- breed = topk_breeds[0]
361
- if top1_prob >= 0.5:
362
- description = get_dog_description(breed)
363
- formatted_description = format_description(description, breed)
364
- explanations.append(f"Dog {i+1}: {formatted_description}")
365
- else:
366
- dog_explanation = f"Dog {i+1}: Top 3 possible breeds:\n"
367
- dog_explanation += "\n".join([f"{j+1}. **{breed}** ({prob} confidence)" for j, (breed, prob) in enumerate(zip(topk_breeds[:3], topk_probs_percent[:3]))])
368
- explanations.append(dog_explanation)
369
- buttons.extend([gr.update(visible=True, value=f"Dog {i+1}: More about {breed}") for breed in topk_breeds[:3]])
370
 
371
- final_explanation = "\n\n".join(explanations)
372
- if buttons:
373
- final_explanation += "\n\nClick on a button to view more information about the breed."
374
- initial_state = {
375
- "explanation": final_explanation,
376
- "buttons": buttons,
377
- "show_back": True
378
- }
379
- return (final_explanation, annotated_image,
380
- buttons[0] if len(buttons) > 0 else gr.update(visible=False),
381
- buttons[1] if len(buttons) > 1 else gr.update(visible=False),
382
- buttons[2] if len(buttons) > 2 else gr.update(visible=False),
383
- gr.update(visible=True),
384
- initial_state)
385
- else:
386
- initial_state = {
387
- "explanation": final_explanation,
388
- "buttons": [],
389
- "show_back": False
390
- }
391
- return final_explanation, annotated_image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
392
 
393
- except Exception as e:
394
- error_msg = f"An error occurred: {str(e)}"
395
- print(error_msg) # 添加日誌輸出
396
- return error_msg, None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None
397
 
398
 
399
- async def process_single_dog(image):
400
- top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
401
- if top1_prob < 0.2:
402
- initial_state = {
403
- "explanation": "The image is unclear or the breed is not in the dataset. Please upload a clearer image of a dog.",
404
- "buttons": [],
405
- "show_back": False
406
- }
407
- return initial_state["explanation"], None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
408
 
409
- breed = topk_breeds[0]
410
- description = get_dog_description(breed)
411
 
412
- if top1_prob >= 0.5:
413
- formatted_description = format_description(description, breed)
414
- initial_state = {
415
- "explanation": formatted_description,
416
- "buttons": [],
417
- "show_back": False
418
- }
419
- return formatted_description, image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
420
- else:
421
- explanation = (
422
- f"The model couldn't confidently identify the breed. Here are the top 3 possible breeds:\n\n"
423
- f"1. **{topk_breeds[0]}** ({topk_probs_percent[0]} confidence)\n"
424
- f"2. **{topk_breeds[1]}** ({topk_probs_percent[1]} confidence)\n"
425
- f"3. **{topk_breeds[2]}** ({topk_probs_percent[2]} confidence)\n\n"
426
- "Click on a button to view more information about the breed."
427
- )
428
- buttons = [
429
- gr.update(visible=True, value=f"More about {topk_breeds[0]}"),
430
- gr.update(visible=True, value=f"More about {topk_breeds[1]}"),
431
- gr.update(visible=True, value=f"More about {topk_breeds[2]}")
432
- ]
433
- initial_state = {
434
- "explanation": explanation,
435
- "buttons": buttons,
436
- "show_back": True
437
- }
438
- return explanation, image, buttons[0], buttons[1], buttons[2], gr.update(visible=True), initial_state
439
 
440
  # def show_details(choice, previous_output, initial_state):
441
  # if not choice:
@@ -488,7 +488,6 @@ async def process_single_dog(image):
488
  # lambda state: (state["explanation"],
489
  # state["buttons"][0] if len(state["buttons"]) > 0 else gr.update(visible=False),
490
  # state["buttons"][1] if len(state["buttons"]) > 1 else gr.update(visible=False),
491
- # state["buttons"][2] if len(state["buttons"]) > 2 else gr.update(visible=False),
492
  # gr.update(visible=state["show_back"])),
493
  # inputs=[initial_state],
494
  # outputs=[output, btn1, btn2, btn3, back_button]
@@ -504,13 +503,110 @@ async def process_single_dog(image):
504
  # if __name__ == "__main__":
505
  # iface.launch()
506
 
507
- def safe_predict(image):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  try:
509
- return predict(image)
 
 
 
510
  except Exception as e:
511
- error_msg = f"An error occurred: {str(e)}\n\n{traceback.format_exc()}"
512
- print(error_msg) # 打印詳細錯誤信息到控制台
513
- return error_msg, None, *[gr.update(visible=False) for _ in range(9)], gr.update(visible=False), None
514
 
515
  with gr.Blocks() as iface:
516
  gr.HTML("<h1 style='text-align: center;'>🐶 Dog Breed Classifier 🔍</h1>")
@@ -522,43 +618,41 @@ with gr.Blocks() as iface:
522
 
523
  output = gr.Markdown(label="Prediction Results")
524
 
525
- with gr.Row():
526
- buttons = [gr.Button(f"View More {i+1}", visible=False) for i in range(9)]
527
 
528
  back_button = gr.Button("Back", visible=False)
529
 
530
  initial_state = gr.State()
531
 
532
- def show_details(button_text, current_output, state):
533
- breed = button_text.split("More about ")[-1]
534
- description = get_dog_description(breed)
535
- formatted_description = format_description(description, breed)
536
- state["current_breed"] = breed
537
- return formatted_description, gr.update(visible=True), state
538
-
539
- def go_back(state):
540
- return (state["explanation"],
541
- *[btn if i < len(state["buttons"]) else gr.update(visible=False)
542
- for i, btn in enumerate(state["buttons"])],
543
- gr.update(visible=state["show_back"]))
544
 
545
  input_image.change(
546
- safe_predict,
547
  inputs=input_image,
548
- outputs=[output, output_image] + buttons + [back_button, initial_state]
549
  )
550
 
551
- for btn in buttons:
552
- btn.click(
553
- show_details,
554
- inputs=[btn, output, initial_state],
555
- outputs=[output, back_button, initial_state]
556
- )
 
 
557
 
 
 
 
 
558
  back_button.click(
559
  go_back,
560
  inputs=[initial_state],
561
- outputs=[output] + buttons + [back_button]
562
  )
563
 
564
  gr.Examples(
 
325
  # 如果沒有檢測到狗狗,返回整張圖片
326
  return [(image, 1.0, [0, 0, image.width, image.height])]
327
 
328
+ # async def predict(image):
329
+ # if image is None:
330
+ # return "Please upload an image to start.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None
331
 
332
+ # try:
333
+ # if isinstance(image, np.ndarray):
334
+ # image = Image.fromarray(image)
335
 
336
+ # dogs = await detect_multiple_dogs(image)
337
 
338
+ # # 如果沒有檢測到狗狗或只檢測到一隻,使用整張圖像進行分類
339
+ # if len(dogs) <= 1:
340
+ # top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
341
+ # if top1_prob >= 0.5:
342
+ # return await process_single_dog(image)
343
+ # else:
344
+ # dogs = [(image, 1.0, [0, 0, image.width, image.height])]
345
 
346
+ # # 多狗情境處理保持不變
347
+ # color_list = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF', '#800080', '#FFA500']
348
+ # explanations = []
349
+ # buttons = []
350
+ # annotated_image = image.copy()
351
+ # draw = ImageDraw.Draw(annotated_image)
352
+ # font = ImageFont.load_default()
353
 
354
+ # for i, (cropped_image, _, box) in enumerate(dogs):
355
+ # top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(cropped_image)
356
+ # color = color_list[i % len(color_list)]
357
+ # draw.rectangle(box, outline=color, width=3)
358
+ # draw.text((box[0], box[1]), f"Dog {i+1}", fill=color, font=font)
359
 
360
+ # breed = topk_breeds[0]
361
+ # if top1_prob >= 0.5:
362
+ # description = get_dog_description(breed)
363
+ # formatted_description = format_description(description, breed)
364
+ # explanations.append(f"Dog {i+1}: {formatted_description}")
365
+ # else:
366
+ # dog_explanation = f"Dog {i+1}: Top 3 possible breeds:\n"
367
+ # dog_explanation += "\n".join([f"{j+1}. **{breed}** ({prob} confidence)" for j, (breed, prob) in enumerate(zip(topk_breeds[:3], topk_probs_percent[:3]))])
368
+ # explanations.append(dog_explanation)
369
+ # buttons.extend([gr.update(visible=True, value=f"Dog {i+1}: More about {breed}") for breed in topk_breeds[:3]])
370
 
371
+ # final_explanation = "\n\n".join(explanations)
372
+ # if buttons:
373
+ # final_explanation += "\n\nClick on a button to view more information about the breed."
374
+ # initial_state = {
375
+ # "explanation": final_explanation,
376
+ # "buttons": buttons,
377
+ # "show_back": True
378
+ # }
379
+ # return (final_explanation, annotated_image,
380
+ # buttons[0] if len(buttons) > 0 else gr.update(visible=False),
381
+ # buttons[1] if len(buttons) > 1 else gr.update(visible=False),
382
+ # buttons[2] if len(buttons) > 2 else gr.update(visible=False),
383
+ # gr.update(visible=True),
384
+ # initial_state)
385
+ # else:
386
+ # initial_state = {
387
+ # "explanation": final_explanation,
388
+ # "buttons": [],
389
+ # "show_back": False
390
+ # }
391
+ # return final_explanation, annotated_image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
392
 
393
+ # except Exception as e:
394
+ # error_msg = f"An error occurred: {str(e)}"
395
+ # print(error_msg) # 添加日誌輸出
396
+ # return error_msg, None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None
397
 
398
 
399
+ # async def process_single_dog(image):
400
+ # top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
401
+ # if top1_prob < 0.2:
402
+ # initial_state = {
403
+ # "explanation": "The image is unclear or the breed is not in the dataset. Please upload a clearer image of a dog.",
404
+ # "buttons": [],
405
+ # "show_back": False
406
+ # }
407
+ # return initial_state["explanation"], None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
408
 
409
+ # breed = topk_breeds[0]
410
+ # description = get_dog_description(breed)
411
 
412
+ # if top1_prob >= 0.5:
413
+ # formatted_description = format_description(description, breed)
414
+ # initial_state = {
415
+ # "explanation": formatted_description,
416
+ # "buttons": [],
417
+ # "show_back": False
418
+ # }
419
+ # return formatted_description, image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
420
+ # else:
421
+ # explanation = (
422
+ # f"The model couldn't confidently identify the breed. Here are the top 3 possible breeds:\n\n"
423
+ # f"1. **{topk_breeds[0]}** ({topk_probs_percent[0]} confidence)\n"
424
+ # f"2. **{topk_breeds[1]}** ({topk_probs_percent[1]} confidence)\n"
425
+ # f"3. **{topk_breeds[2]}** ({topk_probs_percent[2]} confidence)\n\n"
426
+ # "Click on a button to view more information about the breed."
427
+ # )
428
+ # buttons = [
429
+ # gr.update(visible=True, value=f"More about {topk_breeds[0]}"),
430
+ # gr.update(visible=True, value=f"More about {topk_breeds[1]}"),
431
+ # gr.update(visible=True, value=f"More about {topk_breeds[2]}")
432
+ # ]
433
+ # initial_state = {
434
+ # "explanation": explanation,
435
+ # "buttons": buttons,
436
+ # "show_back": True
437
+ # }
438
+ # return explanation, image, buttons[0], buttons[1], buttons[2], gr.update(visible=True), initial_state
439
 
440
  # def show_details(choice, previous_output, initial_state):
441
  # if not choice:
 
488
  # lambda state: (state["explanation"],
489
  # state["buttons"][0] if len(state["buttons"]) > 0 else gr.update(visible=False),
490
  # state["buttons"][1] if len(state["buttons"]) > 1 else gr.update(visible=False),
 
491
  # gr.update(visible=state["show_back"])),
492
  # inputs=[initial_state],
493
  # outputs=[output, btn1, btn2, btn3, back_button]
 
503
  # if __name__ == "__main__":
504
  # iface.launch()
505
 
506
+
507
+ async def predict(image):
508
+ if image is None:
509
+ return "Please upload an image to start.", None, [], gr.update(visible=False), None
510
+
511
+ try:
512
+ if isinstance(image, np.ndarray):
513
+ image = Image.fromarray(image)
514
+
515
+ dogs = await detect_multiple_dogs(image)
516
+
517
+ if len(dogs) <= 1:
518
+ return await process_single_dog(image)
519
+
520
+ color_list = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF', '#800080', '#FFA500']
521
+ explanations = []
522
+ buttons = []
523
+ annotated_image = image.copy()
524
+ draw = ImageDraw.Draw(annotated_image)
525
+ font = ImageFont.load_default()
526
+
527
+ for i, (cropped_image, _, box) in enumerate(dogs):
528
+ top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(cropped_image)
529
+ color = color_list[i % len(color_list)]
530
+ draw.rectangle(box, outline=color, width=3)
531
+ draw.text((box[0], box[1]), f"Dog {i+1}", fill=color, font=font)
532
+
533
+ breed = topk_breeds[0]
534
+ if top1_prob >= 0.5:
535
+ description = get_dog_description(breed)
536
+ formatted_description = format_description(description, breed)
537
+ explanations.append(f"Dog {i+1}: {formatted_description}")
538
+ else:
539
+ dog_explanation = f"Dog {i+1}: Top 3 possible breeds:\n"
540
+ dog_explanation += "\n".join([f"{j+1}. **{breed}** ({prob} confidence)" for j, (breed, prob) in enumerate(zip(topk_breeds[:3], topk_probs_percent[:3]))])
541
+ explanations.append(dog_explanation)
542
+ buttons.extend([f"Dog {i+1}: More about {breed}" for breed in topk_breeds[:3]])
543
+
544
+ final_explanation = "\n\n".join(explanations)
545
+ if buttons:
546
+ final_explanation += "\n\nClick on a button to view more information about the breed."
547
+
548
+ initial_state = {
549
+ "explanation": final_explanation,
550
+ "buttons": buttons,
551
+ "show_back": bool(buttons)
552
+ }
553
+ return final_explanation, annotated_image, buttons, gr.update(visible=bool(buttons)), initial_state
554
+
555
+ except Exception as e:
556
+ error_msg = f"An error occurred: {str(e)}"
557
+ print(error_msg) # 添加日誌輸出
558
+ return error_msg, None, [], gr.update(visible=False), None
559
+
560
+ async def process_single_dog(image):
561
+ top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
562
+ if top1_prob < 0.2:
563
+ initial_state = {
564
+ "explanation": "The image is unclear or the breed is not in the dataset. Please upload a clearer image of a dog.",
565
+ "buttons": [],
566
+ "show_back": False
567
+ }
568
+ return initial_state["explanation"], None, [], gr.update(visible=False), initial_state
569
+
570
+ breed = topk_breeds[0]
571
+ description = get_dog_description(breed)
572
+
573
+ if top1_prob >= 0.5:
574
+ formatted_description = format_description(description, breed)
575
+ initial_state = {
576
+ "explanation": formatted_description,
577
+ "buttons": [],
578
+ "show_back": False
579
+ }
580
+ return formatted_description, image, [], gr.update(visible=False), initial_state
581
+ else:
582
+ explanation = (
583
+ f"The model couldn't confidently identify the breed. Here are the top 3 possible breeds:\n\n"
584
+ f"1. **{topk_breeds[0]}** ({topk_probs_percent[0]} confidence)\n"
585
+ f"2. **{topk_breeds[1]}** ({topk_probs_percent[1]} confidence)\n"
586
+ f"3. **{topk_breeds[2]}** ({topk_probs_percent[2]} confidence)\n\n"
587
+ "Click on a button to view more information about the breed."
588
+ )
589
+ buttons = [f"More about {breed}" for breed in topk_breeds[:3]]
590
+ initial_state = {
591
+ "explanation": explanation,
592
+ "buttons": buttons,
593
+ "show_back": True
594
+ }
595
+ return explanation, image, buttons, gr.update(visible=True), initial_state
596
+
597
+ def show_details(choice, previous_output, initial_state):
598
+ if not choice:
599
+ return previous_output, gr.update(visible=True), initial_state
600
+
601
  try:
602
+ breed = choice.split("More about ")[-1]
603
+ description = get_dog_description(breed)
604
+ formatted_description = format_description(description, breed)
605
+ return formatted_description, gr.update(visible=True), initial_state
606
  except Exception as e:
607
+ error_msg = f"An error occurred while showing details: {e}"
608
+ print(error_msg) # 添加日誌輸出
609
+ return error_msg, gr.update(visible=True), initial_state
610
 
611
  with gr.Blocks() as iface:
612
  gr.HTML("<h1 style='text-align: center;'>🐶 Dog Breed Classifier 🔍</h1>")
 
618
 
619
  output = gr.Markdown(label="Prediction Results")
620
 
621
+ button_container = gr.Column()
 
622
 
623
  back_button = gr.Button("Back", visible=False)
624
 
625
  initial_state = gr.State()
626
 
627
+ def create_buttons(button_texts):
628
+ with button_container:
629
+ button_container.clear()
630
+ buttons = [gr.Button(text) for text in button_texts]
631
+ return buttons
 
 
 
 
 
 
 
632
 
633
  input_image.change(
634
+ predict,
635
  inputs=input_image,
636
+ outputs=[output, output_image, button_container, back_button, initial_state]
637
  )
638
 
639
+ def on_button_click(button_text, output, state):
640
+ return show_details(button_text, output, state)
641
+
642
+ button_container.select(
643
+ on_button_click,
644
+ inputs=["selected", output, initial_state],
645
+ outputs=[output, back_button, initial_state]
646
+ )
647
 
648
+ def go_back(state):
649
+ buttons = create_buttons(state["buttons"])
650
+ return state["explanation"], gr.update(visible=state["show_back"]), state
651
+
652
  back_button.click(
653
  go_back,
654
  inputs=[initial_state],
655
+ outputs=[output, back_button, initial_state]
656
  )
657
 
658
  gr.Examples(