ducdatit2002's picture
Update app.py
81c7aed verified
raw
history blame
5.52 kB
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)