"""ROI(関心領域)抽出モジュール.
SPEC_02 の evaluation.roi 仕様に基づき,輝度画像または RGB 画像から
矩形 ROI を切り出す.現在は image_pixel 型のみ対応.
"""
from __future__ import annotations
import numpy
from sm_tias_lightsim.scene.schema import RoiConfig
def extract_roi(image: numpy.ndarray, roi: RoiConfig) -> numpy.ndarray:
"""画像から ROI(関心領域)を矩形クロップで抽出する.
image_pixel 型の ROI 設定に従い,`roi.x`, `roi.y`, `roi.width`, `roi.height` で
矩形領域を切り出す.2D(輝度)・3D(RGB)どちらの配列も受け付ける.
Args:
image: 輝度画像(H x W, float64)または RGB 画像(H x W x 3).
先頭 2 軸が H, W であること.
roi: ROI 設定(RoiConfig).type は "image_pixel" のみ対応.
Returns:
ROI でクロップされた配列.入力と同じ次元数を持つ.
Raises:
NotImplementedError: roi.type が "image_pixel" 以外の場合.
ValueError: ROI が画像の範囲外にはみ出す場合.
"""
# scene_face 等の将来型は NotImplementedError で明示的に未対応を伝える(SPEC_02 参照)
if roi.type != "image_pixel":
msg = f"ROI type '{roi.type}' は未対応です.現在は 'image_pixel' のみサポートしています."
raise NotImplementedError(msg)
img_height, img_width = image.shape[:2]
x_end = roi.x + roi.width
y_end = roi.y + roi.height
if roi.x < 0 or roi.y < 0:
msg = (
f"ROI の開始座標 (x={roi.x}, y={roi.y}) が負の値です."
"ROI 設定を確認してください."
)
raise ValueError(msg)
if x_end > img_width or y_end > img_height:
msg = (
f"ROI (x={roi.x}, y={roi.y}, width={roi.width}, height={roi.height}) が "
f"画像サイズ (width={img_width}, height={img_height}) を超えています."
"ROI 設定を確認してください."
)
raise ValueError(msg)
return image[roi.y : y_end, roi.x : x_end]