dokoCame / utils /image_utils.py
Fumiya Imazato
Initial commit: どこカメ
57bc6ef
"""画像処理ユーティリティ"""
import base64
import io
from typing import Tuple
import cv2
import numpy as np
from PIL import Image
def resize_frame(
frame: np.ndarray, width: int = 640, height: int = 480
) -> np.ndarray:
"""フレームをリサイズ"""
return cv2.resize(frame, (width, height), interpolation=cv2.INTER_AREA)
def frame_to_base64(frame: np.ndarray, quality: int = 85) -> str:
"""フレームをBase64エンコード"""
# BGR -> RGB
if len(frame.shape) == 3 and frame.shape[2] == 3:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
else:
frame_rgb = frame
img = Image.fromarray(frame_rgb)
buffer = io.BytesIO()
img.save(buffer, format="JPEG", quality=quality)
return base64.b64encode(buffer.getvalue()).decode("utf-8")
def frame_to_pil(frame: np.ndarray) -> Image.Image:
"""NumPy配列をPIL Imageに変換"""
if len(frame.shape) == 3 and frame.shape[2] == 3:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
else:
frame_rgb = frame
return Image.fromarray(frame_rgb)
def pil_to_frame(img: Image.Image) -> np.ndarray:
"""PIL ImageをNumPy配列に変換"""
frame = np.array(img)
if len(frame.shape) == 3 and frame.shape[2] == 3:
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
return frame
def rotate_frame(frame: np.ndarray, angle: int) -> np.ndarray:
"""フレームを回転(0, 90, 180, 270度)"""
if angle == 90:
return cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
elif angle == 180:
return cv2.rotate(frame, cv2.ROTATE_180)
elif angle == 270:
return cv2.rotate(frame, cv2.ROTATE_90_COUNTERCLOCKWISE)
return frame
def get_frame_dimensions(frame: np.ndarray) -> Tuple[int, int]:
"""フレームの寸法を取得 (width, height)"""
return frame.shape[1], frame.shape[0]