DawnC commited on
Commit
92f1b47
1 Parent(s): f0bc5f7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -78
app.py CHANGED
@@ -312,44 +312,50 @@ def _predict_single_dog(image):
312
  # return dogs
313
  # 此為如果後面調不好 使用的版本
314
 
315
- async def detect_multiple_dogs(image, conf_threshold=0.2, iou_threshold=0.45):
316
  results = model_yolo(image, conf=conf_threshold, iou=iou_threshold)[0]
317
  dogs = []
318
- all_boxes = []
319
-
320
- # 首先收集所有可能的狗的邊界框
321
  for box in results.boxes:
322
  if box.cls == 16: # COCO 資料集中狗的類別是 16
323
  xyxy = box.xyxy[0].tolist()
324
  confidence = box.conf.item()
325
- all_boxes.append((xyxy, confidence))
326
-
327
- # 按置信度排序
328
- all_boxes.sort(key=lambda x: x[1], reverse=True)
329
-
330
- # 應用非最大抑制
331
- for box, confidence in all_boxes:
332
- if not is_box_overlapping(box, [d[2] for d in dogs], iou_threshold):
333
- cropped_image = image.crop((box[0], box[1], box[2], box[3]))
334
- dogs.append((cropped_image, confidence, box))
335
-
336
- # 如果沒有檢測到狗,嘗試降低閾值再次檢測
337
- if len(dogs) == 0:
338
- results = model_yolo(image, conf=conf_threshold/2, iou=iou_threshold)[0]
339
- for box in results.boxes:
340
- if box.cls == 16:
341
- xyxy = box.xyxy[0].tolist()
342
- confidence = box.conf.item()
343
  cropped_image = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
344
  dogs.append((cropped_image, confidence, xyxy))
345
 
 
 
 
346
  return dogs
347
 
348
- def is_box_overlapping(box, existing_boxes, iou_threshold):
349
- for existing_box in existing_boxes:
350
- if calculate_iou(box, existing_box) > iou_threshold:
351
- return True
352
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
 
354
  def calculate_iou(box1, box2):
355
  # 計算兩個邊界框的交集面積
@@ -487,69 +493,32 @@ async def predict(image):
487
  if isinstance(image, np.ndarray):
488
  image = Image.fromarray(image)
489
 
490
- dogs = await detect_multiple_dogs(image, conf_threshold=0.05, iou_threshold=0.45)
 
 
 
 
491
 
492
  if len(dogs) == 0:
493
- # 沒有檢測到狗,使用原始圖像進行單狗處理
494
  return await process_single_dog(image)
495
  elif len(dogs) == 1:
496
- # 只檢測到一隻狗,使用裁剪後的圖像進行處理
497
  return await process_single_dog(dogs[0][0])
498
  else:
499
- # 多狗情境
500
- color_list = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF', '#800080', '#FFA500']
501
- explanations = []
502
- buttons = []
503
- annotated_image = image.copy()
504
- draw = ImageDraw.Draw(annotated_image)
505
- font = ImageFont.load_default()
506
-
507
- for i, (cropped_image, confidence, box) in enumerate(dogs):
508
- top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(cropped_image)
509
- color = color_list[i % len(color_list)]
510
- draw.rectangle(box, outline=color, width=3)
511
- draw.text((box[0], box[1]), f"Dog {i+1}", fill=color, font=font)
512
-
513
- breed = topk_breeds[0]
514
- if top1_prob >= 0.5:
515
- description = get_dog_description(breed)
516
- formatted_description = format_description(description, breed)
517
- explanations.append(f"Dog {i+1}: {formatted_description}")
518
- elif top1_prob >= 0.2:
519
- dog_explanation = f"Dog {i+1}: Top 3 possible breeds:\n"
520
- dog_explanation += "\n".join([f"{j+1}. **{breed}** ({prob} confidence)" for j, (breed, prob) in enumerate(zip(topk_breeds[:3], topk_probs_percent[:3]))])
521
- explanations.append(dog_explanation)
522
- buttons.extend([gr.update(visible=True, value=f"Dog {i+1}: More about {breed}") for breed in topk_breeds[:3]])
523
- else:
524
- explanations.append(f"Dog {i+1}: The image is unclear or the breed is not in the dataset.")
525
-
526
- final_explanation = "\n\n".join(explanations)
527
- if buttons:
528
- final_explanation += "\n\nClick on a button to view more information about the breed."
529
- initial_state = {
530
- "explanation": final_explanation,
531
- "buttons": buttons,
532
- "show_back": True
533
- }
534
- return (final_explanation, annotated_image,
535
- buttons[0] if len(buttons) > 0 else gr.update(visible=False),
536
- buttons[1] if len(buttons) > 1 else gr.update(visible=False),
537
- buttons[2] if len(buttons) > 2 else gr.update(visible=False),
538
- gr.update(visible=True),
539
- initial_state)
540
- else:
541
- initial_state = {
542
- "explanation": final_explanation,
543
- "buttons": [],
544
- "show_back": False
545
- }
546
- return final_explanation, annotated_image, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), initial_state
547
 
548
  except Exception as e:
549
  error_msg = f"An error occurred: {str(e)}"
550
  print(error_msg) # 添加日誌輸出
551
  return error_msg, None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None
552
 
 
 
 
 
 
 
 
553
  async def process_single_dog(image):
554
  top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
555
  if top1_prob < 0.2:
 
312
  # return dogs
313
  # 此為如果後面調不好 使用的版本
314
 
315
+ async def detect_multiple_dogs(image, conf_threshold=0.3, iou_threshold=0.5):
316
  results = model_yolo(image, conf=conf_threshold, iou=iou_threshold)[0]
317
  dogs = []
 
 
 
318
  for box in results.boxes:
319
  if box.cls == 16: # COCO 資料集中狗的類別是 16
320
  xyxy = box.xyxy[0].tolist()
321
  confidence = box.conf.item()
322
+ area = (xyxy[2] - xyxy[0]) * (xyxy[3] - xyxy[1])
323
+ if area > 1000: # 過濾掉太小的檢測框
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  cropped_image = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
325
  dogs.append((cropped_image, confidence, xyxy))
326
 
327
+ # 合併重疊的檢測框
328
+ dogs = merge_overlapping_boxes(dogs, iou_threshold=0.6)
329
+
330
  return dogs
331
 
332
+ def merge_overlapping_boxes(dogs, iou_threshold=0.6):
333
+ merged_dogs = []
334
+ while dogs:
335
+ base = dogs.pop(0)
336
+ i = 0
337
+ while i < len(dogs):
338
+ if calculate_iou(base[2], dogs[i][2]) > iou_threshold:
339
+ # 合併重疊的框
340
+ base = merge_boxes(base, dogs.pop(i))
341
+ else:
342
+ i += 1
343
+ merged_dogs.append(base)
344
+ return merged_dogs
345
+
346
+ def merge_boxes(box1, box2):
347
+ xyxy1, conf1, _ = box1
348
+ xyxy2, conf2, _ = box2
349
+ merged_xyxy = [
350
+ min(xyxy1[0], xyxy2[0]),
351
+ min(xyxy1[1], xyxy2[1]),
352
+ max(xyxy1[2], xyxy2[2]),
353
+ max(xyxy1[3], xyxy2[3])
354
+ ]
355
+ merged_conf = max(conf1, conf2)
356
+ merged_image = Image.new('RGB', (int(merged_xyxy[2] - merged_xyxy[0]), int(merged_xyxy[3] - merged_xyxy[1])))
357
+ merged_image.paste(box1[0], (0, 0))
358
+ return (merged_image, merged_conf, merged_xyxy)
359
 
360
  def calculate_iou(box1, box2):
361
  # 計算兩個邊界框的交集面積
 
493
  if isinstance(image, np.ndarray):
494
  image = Image.fromarray(image)
495
 
496
+ dogs = await detect_multiple_dogs(image, conf_threshold=0.3, iou_threshold=0.5)
497
+
498
+ # 如果檢測到的狗的數量不合理,嘗試調整參數重新檢測
499
+ if len(dogs) > 5 or (len(dogs) == 0 and has_dog_features(image)):
500
+ dogs = await detect_multiple_dogs(image, conf_threshold=0.2, iou_threshold=0.4)
501
 
502
  if len(dogs) == 0:
 
503
  return await process_single_dog(image)
504
  elif len(dogs) == 1:
 
505
  return await process_single_dog(dogs[0][0])
506
  else:
507
+ # 多狗情境處理邏輯...
508
+ # (保持原有的多狗處理邏輯不變)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
 
510
  except Exception as e:
511
  error_msg = f"An error occurred: {str(e)}"
512
  print(error_msg) # 添加日誌輸出
513
  return error_msg, None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None
514
 
515
+ def has_dog_features(image):
516
+ # 使用簡單的啟發式方法來檢查圖像是否可能包含狗
517
+ # 這裡可以使用更複雜的方法,如特徵提取或輕量級模型
518
+ gray = image.convert('L')
519
+ edges = gray.filter(ImageFilter.FIND_EDGES)
520
+ return np.mean(np.array(edges)) > 10 # 假設邊緣檢測後的平均值大於 10 表示可能有狗
521
+
522
  async def process_single_dog(image):
523
  top1_prob, topk_breeds, topk_probs_percent = await predict_single_dog(image)
524
  if top1_prob < 0.2: