# Image processing utilities for dwpose-editor import numpy as np import cv2 from PIL import Image from .coordinate_system import CoordinateTransformer from .notifications import notify_success, notify_error, NotificationMessages def process_uploaded_image(image, target_size=(640, 640)): """ アップロードされた画像を処理 Args: image: PIL Image or numpy array target_size: 表示用のターゲットサイズ Returns: tuple: (processed_image, original_size, scale_info) """ try: if image is None: return None, None, None # PIL ImageをNumPy配列に変換 if isinstance(image, Image.Image): original_image = np.array(image) else: original_image = image original_size = (original_image.shape[1], original_image.shape[0]) # (width, height) # アスペクト比を保持してリサイズ processed_image, scale_info = resize_with_aspect_ratio( original_image, target_size ) notify_success(NotificationMessages.IMAGE_UPLOADED) return processed_image, original_size, scale_info except Exception as e: notify_error(f"画像処理中にエラーが発生しました: {str(e)}") return None, None, None def resize_with_aspect_ratio(image, target_size): """ アスペクト比を保持してリサイズ Args: image: numpy array target_size: (width, height) Returns: tuple: (resized_image, scale_info) """ h, w = image.shape[:2] target_w, target_h = target_size # アスペクト比計算 scale = min(target_w / w, target_h / h) new_w = int(w * scale) new_h = int(h * scale) # リサイズ resized = cv2.resize(image, (new_w, new_h), interpolation=cv2.INTER_AREA) # パディング(必要に応じて) if new_w != target_w or new_h != target_h: # 中央配置でパディング pad_x = (target_w - new_w) // 2 pad_y = (target_h - new_h) // 2 if len(image.shape) == 3: padded = np.full((target_h, target_w, image.shape[2]), 128, dtype=image.dtype) else: padded = np.full((target_h, target_w), 128, dtype=image.dtype) padded[pad_y:pad_y+new_h, pad_x:pad_x+new_w] = resized resized = padded scale_info = { 'scale': scale, 'original_size': (w, h), 'resized_size': (new_w, new_h), 'final_size': target_size, 'padding': { 'x': pad_x if 'pad_x' in locals() else 0, 'y': pad_y if 'pad_y' in locals() else 0 } } return resized, scale_info def create_background_canvas(image, canvas_size=(640, 640)): """ 背景画像用のCanvasを作成 Args: image: 背景画像 canvas_size: Canvasサイズ Returns: numpy array: Canvas用背景画像 """ try: if image is None: # デフォルト背景 background = np.full((*canvas_size[::-1], 3), 240, dtype=np.uint8) return background # 画像をCanvasサイズに合わせてリサイズ processed_image, _ = resize_with_aspect_ratio(image, canvas_size) return processed_image except Exception as e: print(f"Background canvas creation error: {e}") # エラー時はデフォルト背景 background = np.full((*canvas_size[::-1], 3), 240, dtype=np.uint8) return background def image_to_base64(image): """ 画像をbase64文字列に変換(Canvas表示用) Args: image: numpy array or PIL Image Returns: str: base64エンコードされた画像データ """ try: import base64 import io if isinstance(image, np.ndarray): # NumPy配列をPIL Imageに変換 if image.dtype != np.uint8: image = (image * 255).astype(np.uint8) pil_image = Image.fromarray(image) else: pil_image = image # base64に変換 buffer = io.BytesIO() pil_image.save(buffer, format='PNG') img_str = base64.b64encode(buffer.getvalue()).decode() return f"data:image/png;base64,{img_str}" except Exception as e: print(f"Image to base64 conversion error: {e}") return None