File size: 4,581 Bytes
4555cad |
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 |
# 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 |