| import numpy as np |
| import cv2 |
| import base64 |
| from io import BytesIO |
| from PIL import Image |
|
|
| class VirtualTryOn: |
| def __init__(self): |
| self.body_keypoints = [ |
| 'nose', 'neck', 'left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow', |
| 'left_wrist', 'right_wrist', 'left_hip', 'right_hip', 'left_knee', 'right_knee', |
| 'left_ankle', 'right_ankle' |
| ] |
| |
| def try_on(self, avatar_image: np.ndarray, clothing_image: np.ndarray) -> dict: |
| avatar_height, avatar_width = avatar_image.shape[:2] |
| clothing_height, clothing_width = clothing_image.shape[:2] |
| |
| scale_factor = min(avatar_width / clothing_width, avatar_height / clothing_height) * 0.7 |
| new_width = int(clothing_width * scale_factor) |
| new_height = int(clothing_height * scale_factor) |
| |
| resized_clothing = cv2.resize(clothing_image, (new_width, new_height)) |
| |
| result = avatar_image.copy() |
| |
| x_offset = (avatar_width - new_width) // 2 |
| y_offset = avatar_height // 3 |
| |
| if y_offset + new_height > avatar_height: |
| y_offset = avatar_height - new_height - 10 |
| |
| x_end = min(x_offset + new_width, avatar_width) |
| y_end = min(y_offset + new_height, avatar_height) |
| |
| alpha = 0.85 |
| roi = result[y_offset:y_end, x_offset:x_end] |
| clothing_roi = resized_clothing[:y_end-y_offset, :x_end-x_offset] |
| |
| blended = cv2.addWeighted(roi, 1-alpha, clothing_roi, alpha, 0) |
| result[y_offset:y_end, x_offset:x_end] = blended |
| |
| result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) |
| pil_img = Image.fromarray(result_rgb) |
| |
| buffered = BytesIO() |
| pil_img.save(buffered, format="PNG") |
| img_base64 = base64.b64encode(buffered.getvalue()).decode() |
| |
| return { |
| "image_base64": img_base64, |
| "fit_score": 0.85, |
| "placement_accuracy": 0.90, |
| "warnings": ["Lighting may affect appearance"], |
| "suggestions": ["Adjust position for better fit", "Try different angle"] |
| } |