DawnC commited on
Commit
083c145
1 Parent(s): 3c27777

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -72
app.py CHANGED
@@ -251,107 +251,97 @@ def get_akc_breeds_link():
251
  # iface.launch()
252
 
253
 
254
- # 使用 YOLOv8 進行狗偵測
255
  def detect_dogs(image):
256
- results = yolo_model.predict(image)
257
  dogs = []
258
-
259
  for result in results:
260
  for box in result.boxes:
261
- if box.cls == 16: # COCO 資料集中的狗類別是16
262
- xyxy = box.xyxy
263
- confidence = box.conf
264
  cropped_image = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
265
  dogs.append((cropped_image, confidence, xyxy))
266
-
267
  return dogs
268
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  def predict(image):
270
  if image is None:
271
- return "Please upload an image to get started.", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
272
 
273
  try:
274
- # 確保圖片轉換為 PIL.Image 格式
275
  if isinstance(image, np.ndarray):
276
  image = Image.fromarray(image)
277
 
278
- # 使用 YOLO 偵測狗
279
  dogs = detect_dogs(image)
280
  if len(dogs) == 0:
281
- return "No dogs detected or the image is too unclear. Please upload a clearer image.", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
282
 
283
- # 開始處理每一隻狗
284
  explanations = []
285
  visible_buttons = []
286
  annotated_image = image.copy()
287
-
288
- for i, (cropped_image, confidence, box) in enumerate(dogs):
289
- image_tensor = preprocess_image(cropped_image)
290
-
291
- with torch.no_grad():
292
- output = model(image_tensor)
293
- logits = output[0] if isinstance(output, tuple) else output
294
-
295
- probabilities = F.softmax(logits, dim=1)
296
- topk_probs, topk_indices = torch.topk(probabilities, k=3)
297
-
298
- top1_prob = topk_probs[0][0].item()
299
- topk_breeds = [dog_breeds[idx.item()] for idx in topk_indices[0]]
300
- topk_probs_percent = [f"{prob.item() * 100:.2f}%" for prob in topk_probs[0]]
301
-
302
- # 標註狗的邊界框
303
- draw = ImageDraw.Draw(annotated_image)
304
- draw.rectangle(box.tolist(), outline="red", width=3)
305
- draw.text((box[0], box[1]), f"Dog {i+1}", fill="red")
306
-
307
- # 信心度大於 50%,顯示詳細品種資訊
308
- if top1_prob >= 0.5:
309
- breed = topk_breeds[0]
310
- description = get_dog_description(breed)
311
- explanations.append(f"Dog {i+1}: **{breed}**\n{format_description(description, breed)}")
312
- # 信心度 20%-49%,顯示 Top 3 品種
313
- elif 0.2 <= top1_prob < 0.5:
314
- explanation = (
315
- f"Dog {i+1}: Detected with moderate confidence. Here are the top 3 possible breeds:\n"
316
- f"1. **{topk_breeds[0]}** ({topk_probs_percent[0]})\n"
317
- f"2. **{topk_breeds[1]}** ({topk_probs_percent[1]})\n"
318
- f"3. **{topk_breeds[2]}** ({topk_probs_percent[2]})\n"
319
- )
320
- explanations.append(explanation)
321
- visible_buttons.extend([f"More about {topk_breeds[0]}", f"More about {topk_breeds[1]}", f"More about {topk_breeds[2]}"])
322
- else:
323
- explanations.append(f"Dog {i+1}: The image is unclear or the breed is not in the dataset.")
324
 
325
  final_explanation = "\n\n".join(explanations)
326
- return annotated_image, final_explanation, gr.update(visible=len(visible_buttons) >= 1), gr.update(visible=len(visible_buttons) >= 2), gr.update(visible=len(visible_buttons) >= 3)
327
 
328
  except Exception as e:
329
- return f"An error occurred: {e}", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
330
-
331
 
332
  def format_description(description, breed):
333
  if isinstance(description, dict):
334
- formatted_description = "\n\n".join([f"**{key}**: {value}" for key, value in description.items()])
335
  else:
336
  formatted_description = description
337
 
338
  akc_link = get_akc_breeds_link()
339
- formatted_description += f"\n\n**Want to learn more about dog breeds?** [Visit the AKC dog breeds page]({akc_link}) and search for {breed} to find detailed information."
340
 
341
- disclaimer = ("\n\n*Disclaimer: The external link provided leads to the American Kennel Club (AKC) dog breeds page. "
342
- "You may need to search for the specific breed on that page. "
343
- "I am not responsible for the content on external sites. "
344
- "Please refer to the AKC's terms of use and privacy policy.*")
345
  formatted_description += disclaimer
346
 
347
  return formatted_description
348
 
349
  def show_details(breed):
350
- breed_name = breed.split("More about ")[-1]
351
  description = get_dog_description(breed_name)
352
  return format_description(description, breed_name)
353
 
354
-
355
  with gr.Blocks(css="""
356
  .container {
357
  max-width: 900px;
@@ -383,20 +373,21 @@ with gr.Blocks(css="""
383
  }
384
  """) as iface:
385
 
386
- gr.HTML("<h1 style='font-family:Roboto; font-weight:bold; color:#2C3E50; text-align:center;'>🐶 Dog Breed Classifier 🔍</h1>")
387
- 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>")
388
 
389
  with gr.Row():
390
- input_image = gr.Image(label="Upload a dog image", type="numpy")
391
- output_image = gr.Image(label="Annotated Image")
392
- output = gr.Markdown(label="Prediction Results")
 
393
 
394
  with gr.Row():
395
- btn1 = gr.Button("View More 1", visible=False)
396
- btn2 = gr.Button("View More 2", visible=False)
397
- btn3 = gr.Button("View More 3", visible=False)
398
 
399
- input_image.change(predict, inputs=input_image, outputs=[output_image, output, btn1, btn2, btn3])
400
 
401
  btn1.click(show_details, inputs=btn1, outputs=output)
402
  btn2.click(show_details, inputs=btn2, outputs=output)
@@ -407,10 +398,8 @@ with gr.Blocks(css="""
407
  inputs=input_image
408
  )
409
 
410
- 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>')
411
 
412
- # launch the program
413
  if __name__ == "__main__":
414
  iface.launch()
415
 
416
-
 
251
  # iface.launch()
252
 
253
 
 
254
  def detect_dogs(image):
255
+ results = yolo_model(image)
256
  dogs = []
 
257
  for result in results:
258
  for box in result.boxes:
259
+ if box.cls == 16: # COCO 資料集中的狗類別是 16
260
+ xyxy = box.xyxy[0].tolist()
261
+ confidence = box.conf.item()
262
  cropped_image = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
263
  dogs.append((cropped_image, confidence, xyxy))
 
264
  return dogs
265
 
266
+ def predict_breed(cropped_image):
267
+ image_tensor = preprocess_image(cropped_image)
268
+ with torch.no_grad():
269
+ output = model(image_tensor)
270
+ logits = output[0] if isinstance(output, tuple) else output
271
+ probabilities = F.softmax(logits, dim=1)
272
+ topk_probs, topk_indices = torch.topk(probabilities, k=3)
273
+ top1_prob = topk_probs[0][0].item()
274
+ topk_breeds = [dog_breeds[idx.item()] for idx in topk_indices[0]]
275
+ topk_probs_percent = [f"{prob.item() * 100:.2f}%" for prob in topk_probs[0]]
276
+ return top1_prob, topk_breeds, topk_probs_percent
277
+
278
  def predict(image):
279
  if image is None:
280
+ return "請上傳一張圖片來開始。", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
281
 
282
  try:
 
283
  if isinstance(image, np.ndarray):
284
  image = Image.fromarray(image)
285
 
 
286
  dogs = detect_dogs(image)
287
  if len(dogs) == 0:
288
+ return "未檢測到狗或圖片不清晰。請上傳一張更清晰的狗的圖片。", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
289
 
 
290
  explanations = []
291
  visible_buttons = []
292
  annotated_image = image.copy()
293
+ draw = ImageDraw.Draw(annotated_image)
294
+
295
+ for i, (cropped_image, _, box) in enumerate(dogs):
296
+ top1_prob, topk_breeds, topk_probs_percent = predict_breed(cropped_image)
297
+
298
+ draw.rectangle(box, outline="red", width=3)
299
+ draw.text((box[0], box[1]), f"狗 {i+1}", fill="red")
300
+
301
+ if top1_prob >= 0.5:
302
+ breed = topk_breeds[0]
303
+ description = get_dog_description(breed)
304
+ explanations.append(f"狗 {i+1}: **{breed}**\n{format_description(description, breed)}")
305
+ elif 0.2 <= top1_prob < 0.5:
306
+ explanation = (
307
+ f"狗 {i+1}: 中等置信度檢測。以下是前3個可能的品種:\n"
308
+ f"1. **{topk_breeds[0]}** ({topk_probs_percent[0]})\n"
309
+ f"2. **{topk_breeds[1]}** ({topk_probs_percent[1]})\n"
310
+ f"3. **{topk_breeds[2]}** ({topk_probs_percent[2]})\n"
311
+ )
312
+ explanations.append(explanation)
313
+ visible_buttons.extend([f"更多關於 {topk_breeds[0]}", f"更多關於 {topk_breeds[1]}", f"更多關於 {topk_breeds[2]}"])
314
+ else:
315
+ explanations.append(f"狗 {i+1}: 圖片不清晰或品種不在數據集中。")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
 
317
  final_explanation = "\n\n".join(explanations)
318
+ 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 "")
319
 
320
  except Exception as e:
321
+ return f"發生錯誤:{e}", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
 
322
 
323
  def format_description(description, breed):
324
  if isinstance(description, dict):
325
+ formatted_description = "\n".join([f"**{key}**: {value}" for key, value in description.items()])
326
  else:
327
  formatted_description = description
328
 
329
  akc_link = get_akc_breeds_link()
330
+ formatted_description += f"\n\n**想了解更多狗品種資訊?** [訪問 AKC 狗品種頁面]({akc_link})並搜尋 {breed} 以獲取詳細資訊。"
331
 
332
+ disclaimer = ("\n\n*免責聲明:提供的外部連結指向美國養犬俱樂部(AKC)的狗品種頁面。"
333
+ "您可能需要在該頁面上搜索特定品種。"
334
+ "我對外部網站的內容不負責任。"
335
+ "請參閱 AKC 的使用條款和隱私政策。*")
336
  formatted_description += disclaimer
337
 
338
  return formatted_description
339
 
340
  def show_details(breed):
341
+ breed_name = breed.split("更多關於 ")[-1]
342
  description = get_dog_description(breed_name)
343
  return format_description(description, breed_name)
344
 
 
345
  with gr.Blocks(css="""
346
  .container {
347
  max-width: 900px;
 
373
  }
374
  """) as iface:
375
 
376
+ gr.HTML("<h1 style='font-family:Roboto; font-weight:bold; color:#2C3E50; text-align:center;'>🐶 狗狗品種分類器 🔍</h1>")
377
+ gr.HTML("<p style='font-family:Open Sans; color:#34495E; text-align:center;'>上傳一張狗狗的照片,模型將預測其品種,提供詳細資訊,並包含額外的資訊連結!</p>")
378
 
379
  with gr.Row():
380
+ input_image = gr.Image(label="上傳狗狗圖片", type="pil")
381
+ output_image = gr.Image(label="標註後的圖片")
382
+
383
+ output = gr.Markdown(label="預測結果")
384
 
385
  with gr.Row():
386
+ btn1 = gr.Button("查看更多 1", visible=False)
387
+ btn2 = gr.Button("查看更多 2", visible=False)
388
+ btn3 = gr.Button("查看更多 3", visible=False)
389
 
390
+ input_image.change(predict, inputs=input_image, outputs=[output, output_image, btn1, btn2, btn3])
391
 
392
  btn1.click(show_details, inputs=btn1, outputs=output)
393
  btn2.click(show_details, inputs=btn2, outputs=output)
 
398
  inputs=input_image
399
  )
400
 
401
+ gr.HTML('如需了解本項目的更多詳情和其他作品,歡迎訪問我的 GitHub <a href="https://github.com/Eric-Chung-0511/Learning-Record/tree/main/Data%20Science%20Projects/Dog%20Breed%20Classifier">狗狗品種分類器</a>')
402
 
 
403
  if __name__ == "__main__":
404
  iface.launch()
405