Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import torch | |
| from ultralyticsplus import YOLO | |
| from PIL import Image, ImageDraw, ImageFont | |
| import os | |
| from transformers import pipeline | |
| import numpy as np | |
| # Tải model YOLO (detection) | |
| yolo_model_path = "best.pt" # Thay đường dẫn model YOLO của bạn | |
| yolo_model = YOLO(yolo_model_path) | |
| # Tải pipeline classification | |
| class_pipe = pipeline("image-classification", model="Hemg/Acne-classification") | |
| # Mapping từ tiếng Anh sang tiếng Việt cho các lớp: Comedo, Acne, Clear | |
| label_mapping = { | |
| "Comedo": "Mụn cám", | |
| "Acne": "Mụn trứng cá", | |
| "Clear": "Vùng da sạch" | |
| } | |
| def detect_and_classify(image, image_size, conf_thresold=0.4, iou_thresold=0.5): | |
| # image là đường dẫn file, đọc thành PIL | |
| pil_image = Image.open(image).convert("RGB") | |
| # Detect với YOLO | |
| results = yolo_model.predict(pil_image, conf=conf_thresold, iou=iou_thresold, imgsz=image_size) | |
| boxes = results[0].boxes | |
| num_boxes = len(boxes) | |
| # Nếu không có vùng mụn | |
| if num_boxes == 0: | |
| severity = "Tốt" | |
| recommendation = "Làn da bạn khá ổn! Tiếp tục duy trì thói quen chăm sóc da." | |
| return image, f"Tình trạng mụn: {severity}", recommendation, "Không có loại mụn nào được phát hiện." | |
| # Chuyển boxes về array | |
| xyxy = boxes.xyxy.detach().cpu().numpy().astype(int) | |
| confidences = boxes.conf.detach().cpu().numpy() | |
| # Crop từng box và classify | |
| class_names = [] | |
| for box in xyxy: | |
| x1, y1, x2, y2 = box | |
| crop = pil_image.crop((x1, y1, x2, y2)) | |
| # Classification trên vùng crop | |
| results_class = class_pipe(crop) | |
| top_class = results_class[0]['label'] # tiếng Anh | |
| class_names.append(top_class) | |
| # Đánh giá tình trạng dựa trên số lượng mụn | |
| if num_boxes > 10: | |
| severity = "Nặng" | |
| recommendation = "Bạn nên đến gặp bác sĩ da liễu và sử dụng liệu trình trị mụn chuyên sâu." | |
| elif 5 <= num_boxes <= 10: | |
| severity = "Trung bình" | |
| recommendation = "Hãy duy trì skincare đều đặn với sữa rửa mặt dịu nhẹ và dưỡng ẩm phù hợp." | |
| else: | |
| severity = "Tốt" | |
| recommendation = "Làn da bạn khá ổn! Tiếp tục duy trì thói quen chăm sóc da hiện tại." | |
| # Vẽ bounding box và class name lên ảnh | |
| draw = ImageDraw.Draw(pil_image) | |
| font = ImageFont.load_default() | |
| # Tạo chuỗi kết quả loại mụn | |
| acne_types_str = "Danh sách mụn phát hiện:\n" | |
| for i, (box, cname, conf) in enumerate(zip(xyxy, class_names, confidences), start=1): | |
| x1, y1, x2, y2 = box | |
| # Lấy tên tiếng việt từ mapping (nếu không có, dùng tên cũ) | |
| vn_name = label_mapping.get(cname, cname) | |
| # Vẽ box | |
| draw.rectangle([x1, y1, x2, y2], outline="red", width=2) | |
| text = f"#{i}: {cname} ({vn_name}) ({conf:.2f})" | |
| # Sử dụng textbbox để lấy kích thước text | |
| bbox = draw.textbbox((0,0), text, font=font) | |
| text_w = bbox[2]-bbox[0] | |
| text_h = bbox[3]-bbox[1] | |
| # Vẽ nền cho text | |
| draw.rectangle([x1, y1 - text_h, x1 + text_w, y1], fill="red") | |
| # Vẽ text | |
| draw.text((x1, y1 - text_h), text, fill="white", font=font) | |
| # Thêm vào chuỗi mô tả | |
| acne_types_str += f"Mụn #{i}: {cname} ({vn_name})\n" | |
| # Lưu ảnh kết quả | |
| predicted_image_save_path = "predicted_image.jpg" | |
| pil_image.save(predicted_image_save_path) | |
| return predicted_image_save_path, f"Tình trạng mụn: {severity}", recommendation, acne_types_str | |
| description_md = """ | |
| ## Ứng dụng Nhận Diện & Phân Loại Mụn | |
| - Sử dụng YOLO để phát hiện các vùng mụn trên khuôn mặt. | |
| - Sử dụng mô hình phân loại (Hemg/Acne-classification) để xác định loại mụn. | |
| - Hiển thị bounding box kèm số thứ tự, tên tiếng Anh và tiếng Việt của loại mụn. | |
| - Đánh giá tình trạng da và đưa ra khuyến nghị. | |
| """ | |
| custom_css = """ | |
| #component-0, #component-1, #component-2, #component-3, #component-4 { | |
| font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
| text-align: center; | |
| } | |
| #component-0 h1 { | |
| color: #F15B2A; | |
| } | |
| #component-0 h2, h3 { | |
| color: #333; | |
| } | |
| .gr-button { | |
| background-color: #F15B2A !important; | |
| color: #fff !important; | |
| border: none !important; | |
| font-weight: bold !important; | |
| } | |
| .gr-button:hover { | |
| background-color: #d94c1f !important; | |
| } | |
| """ | |
| import gradio as gr | |
| inputs = [ | |
| gr.Image(type="filepath", label="Ảnh Khuôn Mặt"), | |
| gr.Slider(minimum=320, maximum=1280, step=32, value=640, label="Kích thước ảnh (Image Size)"), | |
| gr.Slider(minimum=0, maximum=1, step=0.05, value=0.4, label="Ngưỡng Confidence"), | |
| gr.Slider(minimum=0, maximum=1, step=0.05, value=0.5, label="Ngưỡng IOU") | |
| ] | |
| outputs = [ | |
| gr.Image(type="filepath", label="Ảnh Sau Khi Xử Lý"), | |
| gr.Textbox(label="Tình Trạng Mụn", interactive=False), | |
| gr.Textbox(label="Khuyến Nghị", interactive=False), | |
| gr.Textbox(label="Loại Mụn Phát Hiện", interactive=False) | |
| ] | |
| yolo_app = gr.Interface( | |
| fn=detect_and_classify, | |
| inputs=inputs, | |
| outputs=outputs, | |
| title="YOLOv8 + Classification: Nhận Diện & Phân Loại Mụn", | |
| description=description_md, | |
| css=custom_css, | |
| theme="default" | |
| ) | |
| yolo_app.launch(share=True) | |