import torch import cv2 import numpy as np from PIL import Image import gradio as gr from ultralytics import YOLO from transformers import AutoImageProcessor, ResNetForImageClassification # โหลด YOLOv8 โมเดลสำหรับตรวจจับบุคคล yolo_model = YOLO("yolov8n.pt") # ใช้เวอร์ชันเล็ก (nano) # โหลด ResNet-50 สำหรับจำแนกภาพ resnet_model_name = "microsoft/resnet-50" resnet_model = ResNetForImageClassification.from_pretrained(resnet_model_name) processor = AutoImageProcessor.from_pretrained(resnet_model_name) # ฟังก์ชันสำหรับ mapping class_id → BMI def map_to_bmi(class_id): if class_id < 250: return "Underweight" elif class_id < 500: return "Normal" elif class_id < 750: return "Overweight" else: return "Obese" # ฟังก์ชันสำหรับ mapping class_id → Body Type def map_to_body_type(class_id): if class_id % 3 == 0: return "Ectomorph (ผอมเพรียว)" elif class_id % 3 == 1: return "Mesomorph (สมส่วน/ล่ำ)" else: return "Endomorph (ล่ำอวบ)" # ฟังก์ชันตรวจจับและครอบตัดบุคคล def detect_and_crop_person(image_np): results = yolo_model(image_np) for result in results: for box in result.boxes: class_id = int(box.cls) if yolo_model.names[class_id] == 'person': x1, y1, x2, y2 = map(int, box.xyxy[0]) cropped = image_np[y1:y2, x1:x2] cropped_rgb = cv2.cvtColor(cropped, cv2.COLOR_BGR2RGB) return Image.fromarray(cropped_rgb) return None # ฟังก์ชันหลักสำหรับ Gradio def process_image(image): # Convert PIL to numpy image_np = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) # ตรวจจับและครอบตัดบุคคล cropped = detect_and_crop_person(image_np) if cropped is None: return "⚠️ ไม่พบบุคคลในภาพ" # วิเคราะห์ด้วย ResNet inputs = processor(images=cropped, return_tensors="pt") with torch.no_grad(): logits = resnet_model(**inputs).logits class_id = logits.argmax(-1).item() # แมปผลลัพธ์ bmi = map_to_bmi(class_id) body_type = map_to_body_type(class_id) label = resnet_model.config.id2label[class_id] return f"📷 ResNet Label: {label}\n🧍 Body Type: {body_type}\n📏 BMI Category: {bmi}" # สร้าง Gradio Interface demo = gr.Interface( fn=process_image, inputs=gr.Image(type="pil"), outputs="text", title="BMI + Body Type Estimator (with YOLOv8)", description="วิเคราะห์ BMI และลักษณะรูปร่างจากภาพถ่าย โดยใช้ YOLOv8 สำหรับตรวจจับบุคคล และ ResNet-50 สำหรับวิเคราะห์" ) if __name__ == "__main__": demo.launch()