File size: 5,515 Bytes
12f490a 9ac8c85 12f490a 9ac8c85 12f490a 9ac8c85 12f490a 9ac8c85 12f490a 81c7aed 9ac8c85 e284c36 12f490a 81c7aed 9ac8c85 81c7aed 9ac8c85 12f490a 9ac8c85 12f490a e284c36 12f490a e284c36 12f490a e284c36 12f490a 9ac8c85 12f490a 81c7aed 9ac8c85 81c7aed 9ac8c85 81c7aed 9ac8c85 81c7aed 9ac8c85 81c7aed 9ac8c85 12f490a 9ac8c85 e284c36 9ac8c85 81c7aed 9ac8c85 e284c36 12f490a 81c7aed 12f490a 9ac8c85 e284c36 9ac8c85 12f490a e284c36 9ac8c85 12f490a e284c36 9ac8c85 e284c36 9ac8c85 e284c36 9ac8c85 e284c36 12f490a 9ac8c85 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
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)
|