Newer
Older
SmTIAS-Capture / docs / 05_TECH / TECH_01_定量撮影モード要求仕様.md

定量撮影モード要求仕様 (Quantitative Capture Mode Specification)

本ドキュメントは SmTIAS-LightSim プロジェクトから MiniTIAS プロジェクトに対する 撮影モード拡張の要求仕様 である.SmTIAS-LightSim のキャリブレーション作業 (Step 8 系) で判明した「実機 PNG が定量データとして揺らぐ」問題を解消するための撮影アプリ側改修を依頼する.

概要 (Overview)

MiniTIAS(MiniTias リポジトリ)の撮影アプリに,現状の通常撮影モードに加えて 「定量撮影モード (Quantitative Capture Mode)」 を追加することを要求する.

定量撮影モードでは:

  • Camera2 API のオート制御 (AE/AWB/NR/EDGE/TONEMAP) を すべて固定または OFF にする.
  • ISP が適用した LSC ゲインマップ を撮影ごとに同時保存する.
  • 可能なら出力フォーマットを RAW_SENSOR (DNG) に切り替えられるようにする.

これにより同じシーンを何度撮影しても再現性のある定量データが得られ,SmTIAS-LightSim 側のシミュレーション結果との突合が安定する.

背景 (Background)

SmTIAS-LightSim と MiniTIAS の関係

  • MiniTIAS: スマートフォンアプリ.AQUOS sense3 で白板・舌模型を撮影し PNG として保存する.
  • MiniTias-Evaluation: PC 側.MiniTIAS が保存した PNG を読み込み照明均一性 (CoV/勾配/C/P 等) を算出する.
  • SmTIAS-LightSim: PC 側.Mitsuba 3 で同じ筐体・LED 配置を仮想撮影し,MiniTias-Evaluation と同じ指標を計算する.

→ 3 つのプロジェクトで 同じ評価指標 を出すことで「シミュ vs 実機」を比較する.

現状の問題(Step 8 キャリブで判明)

Step 8 キャリブレーション (TEST_01 参照) で,シミュと実機の比較を試みた結果,以下の現象が観測された:

  • 形状指標残差 1.6〜1.9 倍 が解消されない(OETF 順方向適用後でも)
  • 輝度マップの「形」が実機(中央ピーク楕円)とシミュ(Y 軸単調勾配)で 構造的に違う (TEST_03 参照)
  • LED 位置・反射率・配光・センサ方向 (TEST_01 Step 8-9/8-10/8-11/8-12 系) すべてを試したが「形」は変わらず

「形を変える唯一の道」として LSC (Lens Shading Correction) モデル化 が候補に挙がったが,さらに調査した結果,より根本的な問題 が判明した:

  • 既存 baseline 画像 (MiniTIAS_20260408_144434) は MiniTIAS の通常撮影モードで取得されており,ISP がすべて自動制御で動作している.
  • 具体的には MiniTIAS/docs/04_SPEC/SPEC_01 のとおり:
    • AE/AF 安定 1 秒待ち → STILL_CAPTURE → YUV_420_888 取得 → BT.601 で RGB → PNG 保存
    • AE / AWB / NR / EDGE / TONEMAP / SHADING はすべて Camera2 API のデフォルト (オート/ON) のまま
  • これは「人間が見て自然な画像」用設定であり,定量解析向けではない
  • 撮影ごとに露光・WB・補正量が変動する可能性があり,同じシーンを 2 回撮っても同じ値にならない可能性 がある.

つまり「定量比較の対象である実機 PNG 自体が揺らいでいる」状態.まずここを固定化しない限り,シミュ側でいくらモデルを精緻化しても比較できない.

目的 (Objective)

定量撮影モードの導入により以下を達成する:

  1. 撮影再現性の確保: 同条件で繰り返し撮影しても mean / std / 形状指標が同じ値になる.
  2. ISP 介入の最小化: AE/AWB/NR/EDGE/TONEMAP/SHADING を固定/OFF し,センサ出力に近い値を取得する.
  3. メタデータの可視化: ISP が適用した LSC ゲインマップを取得して別ファイル保存する.
  4. シミュ比較の土台: SmTIAS-LightSim 側のキャリブレーション・LSC 検証が安定したデータで進められる.

要求仕様 (Requirements)

1. 撮影モード切替 UI

撮影画面 (S-01) に「定量撮影モード」のトグルスイッチを追加する.

  • デフォルト: OFF(既存通常モード)
  • ON 時: 後述の Camera2 API 設定をすべて適用
  • 後方互換: 既存ユーザー・既存撮影ワークフローには影響しない

2. Camera2 API 設定(定量モード ON 時)

キー目的
CONTROL_MODEOFF(マニュアル全制御)ISP オート制御の完全停止
CONTROL_AE_MODEOFF自動露光停止
SENSOR_EXPOSURE_TIME固定値(要キャリブ,例 1/60 s)露光時間固定
SENSOR_SENSITIVITY最低 ISO(端末依存,例 50)ノイズ最小化 + ゲイン固定
CONTROL_AWB_MODEOFF自動 WB 停止
COLOR_CORRECTION_GAINS固定値 (R=G=B=1.0 推奨)チャネルゲイン固定
COLOR_CORRECTION_TRANSFORM単位行列カラーマトリクス無効化
NOISE_REDUCTION_MODEOFFNR 無効化(アーティファクト排除)
EDGE_MODEOFFエッジ強調無効化
TONEMAP_MODECONTRAST_CURVE (線形カーブ) または PRESET_CURVE (SRGB)トーンマッピング固定
SHADING_MODEHIGH_QUALITY (LSC 補正適用) または OFF (LSC 無効化) のいずれか選択可LSC の挙動制御(次節参照)
STATISTICS_LENS_SHADING_MAP_MODEONLSC ゲインマップ取得有効化

SHADING_MODE = OFF を選んだ場合は cos⁴ falloff が画像に残る.後段のシミュ側で物理 cos⁴ を加える前提なら有用.通常運用では HIGH_QUALITY を推奨.

3. LSC ゲインマップの保存

撮影成功時に CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP から LensShadingMap を取得して保存する.

項目仕様
取得 APIresult.get(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP)
データ形状4 × N × M float 配列(4 = R/Geven/Godd/B チャネル,N = 列,M = 行)
値の意味≥ 1.0 のゲイン係数.corrected = raw × gain
保存形式NPZ(推奨)または JSON.画像ファイル名と同 prefix で <basename>.lsc.npz
保存先画像と同ディレクトリ
マップサイズCameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE から取得

4. 撮影メタデータの保存(撮影パラメータの可視化)

LSC マップに加えて,撮影時の Camera2 API パラメータを JSON で保存する.後段でシミュレーションの境界条件を再現するために必要.

{
  "capture_timestamp_utc": "2026-05-28T10:00:00Z",
  "device_model": "SH-02M",
  "android_version": "9",
  "camera_id": "1",
  "hardware_level": "LIMITED",
  "capture_mode": "quantitative",
  "settings": {
    "control_mode": "OFF",
    "ae_mode": "OFF",
    "exposure_time_ns": 16666666,
    "sensor_sensitivity_iso": 50,
    "awb_mode": "OFF",
    "color_correction_gains": [1.0, 1.0, 1.0, 1.0],
    "color_correction_transform": "identity",
    "noise_reduction_mode": "OFF",
    "edge_mode": "OFF",
    "tonemap_mode": "CONTRAST_CURVE",
    "shading_mode": "HIGH_QUALITY",
    "statistics_lens_shading_map_mode": "ON"
  },
  "image_format": "YUV_420_888",
  "image_size": [4000, 3000],
  "yuv_to_rgb_matrix": "BT.601"
}

ファイル名規則: <image_basename>.meta.json

5. 推奨出力フォーマット

優先順位は以下:

優先度フォーマット説明
第 1RAW_SENSOR (DNG)ISP 介入ゼロ.センサ出力そのまま.DNG GainMap 仕様 と整合
第 2YUV_420_888 + 上記メタデータ + LSC マップ現状フォーマットに情報追加.後段で逆処理可能
第 3PNG(現状) + メタデータ + LSC マップ最小実装.BT.601 YUV→RGB 経由のため情報量は最小

第 1 は実機が DNG 出力をサポートしている必要がある(AQUOS sense3 で要確認).サポートしていない場合は第 2 を採用.

6. ハードウェアサポート判定

定量モード起動時に CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL を取得して以下を判定:

  • LEGACY: 定量モード 不可(マニュアル制御サポートなし)→ ユーザーに警告表示
  • LIMITED: 部分サポート.SHADING_MODE と LSC マップ取得が可能か個別確認
  • FULL / LEVEL_3: 完全サポート

必要な能力フラグ:

  • REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR (露光・ISO 固定)
  • REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING (NR/EDGE/TONEMAP/SHADING 固定)
  • REQUEST_AVAILABLE_CAPABILITIES_RAW (DNG 出力,第 1 優先時のみ必須)

判定結果は前述メタデータ JSON の hardware_level フィールドに記録する.

Flutter / camera パッケージの限界

camera パッケージ は AE/AWB/SHADING_MODE 等の詳細制御を 直接公開していない ことが多い.定量モードを実現するには以下のいずれかが必要:

  • Platform Channel で Camera2 API を直接制御(推奨)
    • Android Kotlin/Java 側で Camera2 API を直接叩く
    • Flutter 側は MethodChannel で「定量モード撮影」要求を送る
  • camerax_android など低レベル制御を公開した代替パッケージへの移行
  • Native Plugin の自作

実装規模が大きい場合は段階的に:

  1. Phase 1: Camera2 詳細制御の MethodChannel 実装(露光・WB 固定,LSC マップ取得)
  2. Phase 2: LSC マップ・メタデータ保存ロジック
  3. Phase 3: 撮影画面 UI に定量モードトグル追加
  4. Phase 4: ハードウェアサポート判定とユーザー案内
  5. Phase 5: RAW_SENSOR (DNG) 対応(任意)

ディレクトリ構成提案

MiniTIAS 既存構造に従い:

android/app/src/main/kotlin/<package>/
└── camera/
    └── QuantitativeCameraController.kt   # Camera2 直接制御

lib/services/
├── quantitative_camera_service.dart      # Platform Channel ラッパ
├── lsc_map_service.dart                  # LSC マップ NPZ 保存
└── capture_metadata_service.dart         # メタデータ JSON 保存

lib/providers/
└── camera_provider.dart                  # 定量モード状態追加(既存 Provider 拡張)

期待される効果 (Expected Effects)

項目改善内容
撮影再現性同条件 10 連射で mean / std が ±1% 以内に揃う
色温度ドリフトAWB 固定により無彩色撮影で色シフト排除
LSC 補正可視化ISP が適用したゲインマップが取得でき,シミュ側で逆適用可能
物理 cos⁴ 検証SHADING_MODE = OFF モードで実機 raw 相当を取得し,シミュ + cos⁴ と比較可能
RAW 比較 (任意)DNG 経路が確立すれば,ISP 完全排除でセンサ生値 vs Mitsuba 直接比較
キャリブ作業の安定化SmTIAS-LightSim 側で同じ baseline を繰り返し再撮影しても結果が動かない

後方互換 (Backward Compatibility)

  • 通常撮影モードは現状仕様のまま維持(既存撮影ワークフローを壊さない)
  • 既存 baseline 画像 (MiniTIAS_20260408_144434) は 「通常モードで撮影された」 ことを SmTIAS-LightSim 側で明示記録(TEST_03 に追記予定)
  • 新規定量モード撮影は別命名規則を推奨:
    • 例: MiniTIAS_QM_YYYYMMDD_HHmmss.png(QM = Quantitative Mode)
    • メタデータ: MiniTIAS_QM_YYYYMMDD_HHmmss.meta.json
    • LSC マップ: MiniTIAS_QM_YYYYMMDD_HHmmss.lsc.npz

検証方法 (Verification)

定量モード実装完了後,以下を実施して受け入れ判定とする:

V1. 再現性検証

同条件(光源 ON・同じ白板・三脚固定)で 10 回連続撮影 し,全画像で:

  • mean / std の変動係数 (CoV of means) < 1%
  • 形状指標 (CoV/勾配/C/P) の標準偏差 < 0.005

V2. LSC マップ取得検証

  • 全撮影で <basename>.lsc.npz が保存されている
  • マップサイズが CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE と一致
  • ゲイン値がすべて ≥ 1.0
  • 中央 (col=N/2, row=M/2) のゲインが ≈ 1.0

V3. SHADING_MODE 切替検証

  • SHADING_MODE = OFF で撮影した画像が HIGH_QUALITY より周辺で明らかに暗い(cos⁴ falloff 可視化)
  • HIGH_QUALITY × (1 / LSC マップ)OFF の関係性が成立する(数値差 < 5%)

V4. SmTIAS-LightSim 側での突合

  • 定量モード白板撮影 (SHADING_MODE = HIGH_QUALITY) を baseline として再キャリブ
  • シミュ vs 実機の残差が現状 2.1× → 1.5× 以下に縮むこと(仮目標)

開放質問 (Open Questions)

実装着手時に確認が必要な事項:

ID質問確認方法
Q1AQUOS sense3 のハードウェアレベルは何かデバッグビルドで CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL を読みログ出力
Q2SH-02M のフロントカメラで REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING がサポートされているか同上.未サポートなら定量モードは部分実装
Q3DNG (RAW_SENSOR) 出力は可能かREQUEST_AVAILABLE_CAPABILITIES_RAW を確認
Q4LSC マップサイズはどの程度か(例 13×17 等)実機でログ出力.データ量設計の参考
Q5露光時間・ISO の最適値(固定値の決定)白板撮影で被写体の明るさが適切かを実機で試行錯誤
Q6既存 MiniTIAS_20260408_144434 を定量モードで再撮影するか研究方針との整合(再撮影なら現 baseline は参考扱い)
Q7既存 PNG 保存形式 (BT.601 経由) を維持するか YUV/RAW 直接保存に変えるかSmTIAS-LightSim 側読み込みコストとのトレードオフ