Newer
Older
SmTIAS-Evaluation / scripts / compare_ambient_maps.py
"""暗闇 vs 室内(外乱光)の輝度マップを共通スケールで並べるスライドを生成する.

REPORT_03(外乱光影響評価)に対応.compare_ambient_radial.py(動径オーバーレイ)の
輝度マップ版で,同一 DNG 定量モード(linear + LSC 補正,露出/ISO 固定)の 2 枚を
**共通の絶対カラースケール** で並置し,空間パターンがほぼ同じこと(外乱光ロバスト性)を示す.

共通スケールにする理由(各自正規化しない):
- 両者は同じ linear 単位・同じ露出/ISO・同じ LSC 補正なので絶対値が正当に比較可能.
- 共通カラースケールでないと「2 枚がほぼ同じ」が言えない(各自スケールだと差が誇張/隠蔽される).

対象(REPORT_03 の条件 A/B):
- 暗闇 (lights OFF) : SmTIAS_QM_20260601_124500
- 室内 (lights ON)  : SmTIAS_QM_20260601_102753

使い方:
    python scripts/compare_ambient_maps.py
"""

import sys
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np

PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT))

from src.config import load_roi_config  # noqa: E402
from src.io.dng_pipeline import dng_luminance  # noqa: E402
from src.io.loader import extract_roi  # noqa: E402

# REPORT_03 の条件 A(暗闇=室内灯OFF)/ 条件 B(室内=室内灯ON)
DARK_PATH = PROJECT_ROOT / "data" / "smtias" / "quantitative" / "SmTIAS_QM_20260601_124500.dng"
INDOOR_PATH = PROJECT_ROOT / "data" / "smtias" / "quantitative" / "SmTIAS_QM_20260601_102753.dng"
ROI_CONFIG = PROJECT_ROOT / "config" / "roi_config.json"
ROI_KEY = "smtias.whiteboard"
OUTPUT_PATH = PROJECT_ROOT / "output" / "figures" / "compare_ambient_maps.png"


def _roi_luminance(path: Path, roi: dict) -> np.ndarray:
    """DNG(linear + LSC)の ROI 輝度画像を返す."""
    luma = dng_luminance(str(path), apply_lsc=True)
    return extract_roi(luma, roi["x"], roi["y"], roi["width"], roi["height"])


def main() -> None:
    """共通スケールの 2 枚並べスライドを生成して保存する."""
    roi = load_roi_config(str(ROI_CONFIG), ROI_KEY)
    if roi is None:
        raise SystemExit(f"ROI '{ROI_KEY}' が config に見つかりません")

    dark = _roi_luminance(DARK_PATH, roi)
    indoor = _roi_luminance(INDOOR_PATH, roi)

    # 共通カラースケール: 2 枚を結合した 1〜99 パーセンタイル(ノイズ外れ値にロバスト)
    both = np.concatenate([dark.ravel(), indoor.ravel()])
    vmin = float(np.percentile(both, 1))
    vmax = float(np.percentile(both, 99))

    fig, axes = plt.subplots(1, 2, figsize=(13, 6))
    panels = [
        (axes[0], dark, "Dark (lights OFF)  124500"),
        (axes[1], indoor, "Indoor (lights ON)  102753"),
    ]
    im = None
    for ax, luminance, title in panels:
        im = ax.imshow(
            luminance, cmap="hot", interpolation="nearest", vmin=vmin, vmax=vmax
        )
        ax.set_title(title, fontsize=11)
        ax.set_xlabel("X (px)")
        ax.set_ylabel("Y (px)")

    cbar = fig.colorbar(im, ax=axes, fraction=0.025, pad=0.02)
    cbar.set_label("Luminance (absolute, linear 0-255 scale)")

    fig.suptitle(
        "Ambient light effect on luminance map (DNG, linear + LSC, shared scale)",
        fontsize=13, y=0.98,
    )

    OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True)
    fig.savefig(str(OUTPUT_PATH), dpi=150, bbox_inches="tight")
    plt.close(fig)
    print(f"共通スケール比較スライドを保存しました: {OUTPUT_PATH}")
    print(f"  共通カラースケール vmin={vmin:.1f}  vmax={vmax:.1f}")
    print(f"  Dark   (124500) ROI mean = {dark.mean():.2f}")
    print(f"  Indoor (102753) ROI mean = {indoor.mean():.2f}")


if __name__ == "__main__":
    main()