diff --git "a/docs/05_TECH/TECH_03_\345\256\232\351\207\217\343\203\242\343\203\274\343\203\211\345\256\237\350\243\205\345\240\261\345\221\212\343\201\250SHADING_MODE\347\233\270\350\253\207.md" "b/docs/05_TECH/TECH_03_\345\256\232\351\207\217\343\203\242\343\203\274\343\203\211\345\256\237\350\243\205\345\240\261\345\221\212\343\201\250SHADING_MODE\347\233\270\350\253\207.md" new file mode 100644 index 0000000..f1559fa --- /dev/null +++ "b/docs/05_TECH/TECH_03_\345\256\232\351\207\217\343\203\242\343\203\274\343\203\211\345\256\237\350\243\205\345\240\261\345\221\212\343\201\250SHADING_MODE\347\233\270\350\253\207.md" @@ -0,0 +1,336 @@ +# 定量モード実装報告と SHADING_MODE 相談 (Implementation Report & SHADING_MODE Consultation) + +本ドキュメントは [TECH_01 定量撮影モード要求仕様](TECH_01_定量撮影モード要求仕様.md) を MiniTIAS リポジトリで実装した結果の **MiniTIAS 側からの報告書** であり,併せて **SmTIAS-LightSim 側との方針確認・相談事項** をまとめたものである. + +## 想定読者 (Intended Reader) + +- **SmTIAS-LightSim 側 Claude セッション**: 本ドキュメントを読んで MiniTIAS 側の実装状況を把握し,未確定事項に対する判断・指示を返す +- **人間レビュー (rinto)**: 両セッションを橋渡しし,研究方針に照らして判断する + +## 概要 (Overview) + +MiniTIAS 側で TECH_01 の要求仕様に基づいた **定量撮影モード(DNG 経路)** の実装が完了した([MiniTias リポジトリ master ブランチ](https://github.com/rintoHasegawa/MiniTIAS) に取り込み済み).本ドキュメントの目的は以下の 2 点: + +1. **実装結果の報告**:TECH_01 の各 Phase に対して何を実装したか,AQUOS sense3 (SH-02M) で何が確認できたかを共有する +2. **SHADING_MODE の扱いの相談**:定量モードのキー設定である `SHADING_MODE` を MiniTIAS 側でどう選んだか,研究上どのような含意があるか,SmTIAS-LightSim 側の解析パイプラインとの整合を確認したい + +## TECH_01 要求に対する実装状況 (Implementation Status) + +| Phase | 要求 | 実装状況 | +| --- | --- | --- | +| Phase 1 | Camera2 詳細制御の MethodChannel 実装(露光・WB 固定,LSC マップ取得) | ✅ 完了 | +| Phase 2 | LSC マップ・メタデータ保存ロジック | ✅ 完了 | +| Phase 3 | 撮影画面 UI に定量モードトグル追加 | ⚠️ 仕様変更(後述).**トグル UI は追加せず通常モードを置換** | +| Phase 4 | ハードウェアサポート判定とユーザー案内 | ✅ 診断機能を `DiagnosticsProvider` として実装(UI 非表示.裏で再利用可能) | +| Phase 5 | RAW_SENSOR (DNG) 対応(任意) | ✅ 完了.第 1 優先経路として採用 | + +### Phase 3 の変更点 + +TECH_01 では「撮影モード切替トグル」で通常モードと定量モードを並存させる想定だったが,MiniTIAS 側の運用判断として **通常モード(PNG 経路)を temporarily に無効化し,シャッターは常に定量モードを呼ぶ**構成にした.既存の `captureFullResolutionPng` コードは温存している. + +理由: + +- MiniTIAS の運用上の存在意義は SmTIAS-LightSim との定量比較のみ +- トグル UI を残すと「誤って通常モードで撮影してしまい後で気付く」事故が起きる +- 研究フェーズ完了後にトグル追加 or 通常モード復活は容易 + +## 実装した撮影設定 (Camera2 CaptureRequest) + +| キー | 設定値 | 備考 | +| --- | --- | --- | +| `CONTROL_MODE` | `OFF` | マニュアル全制御 | +| `CONTROL_AE_MODE` | `OFF` | 自動露光停止 | +| `SENSOR_EXPOSURE_TIME` | `16,666,666 ns`(= 1/60 s) | **ハードコード**.後段で半自動キャリブ機能の追加を検討中 | +| `SENSOR_SENSITIVITY` | `40`(センサ最低 ISO) | 診断で確認したセンサのレンジ最低値 | +| `SENSOR_FRAME_DURATION` | `33,333,333 ns`(30fps 相当) | 露光時間 ≤ frame duration を満たす任意値 | +| `BLACK_LEVEL_LOCK` | `true` | フレーム間で黒レベルのドリフトを抑える | +| `CONTROL_AWB_MODE` | `OFF` | 自動 WB 停止 | +| `COLOR_CORRECTION_MODE` | `TRANSFORM_MATRIX` | マニュアル制御モード | +| `COLOR_CORRECTION_GAINS` | `RggbChannelVector(1.0, 1.0, 1.0, 1.0)` | RAW 出力では Bayer 値に効かないが request 値として明示 | +| `COLOR_CORRECTION_TRANSFORM` | 単位行列(`ColorSpaceTransform`) | 同上 | +| `NOISE_REDUCTION_MODE` | `OFF` | NR による画素値の改変を防ぐ | +| `EDGE_MODE` | `OFF` | エッジ強調を防ぐ | +| `TONEMAP_MODE` | `CONTRAST_CURVE` | カーブは R/G/B すべて線形 `[(0,0),(1,1)]` | +| **`SHADING_MODE`** | **`HIGH_QUALITY`** | ★後述の相談対象.OFF も技術的に可能 | +| `STATISTICS_LENS_SHADING_MAP_MODE` | `ON` | LSC マップを CaptureResult に含める | +| `CONTROL_AF_MODE` | `OFF` | **AQUOS sense3 のフロントカメラは固定焦点で OFF のみサポート** | +| `FLASH_MODE` | `OFF` | LED はアタッチメント側で制御 | +| `CONTROL_VIDEO_STABILIZATION_MODE` | `OFF` | 手ブレ補正による画像ずれを防ぐ | + +## 撮影フロー (Capture Flow) + +```text +シャッター押下 + │ + ▼ +プレビュー停止(camera パッケージの CameraController.dispose) + │ + ▼ +baseName 生成(MiniTIAS_QM_YYYYMMDD_HHmmss.同秒重複時 _1, _2 ...) + │ + ▼ +Camera2 API でフロントカメラを開く +ImageReader(RAW_SENSOR, 3264×2448, maxImages=3) + │ + ▼ +上記マニュアル制御パラメータを CaptureRequest に適用 + │ + ▼ +連続 3 枚キャプチャ +(設定反映確実化のため最初の 2 枚は破棄.3 枚目を本番とする) + │ + ▼ +DngCreator で DNG ファイルを直接書き込み +(FileOutputStream → ${dir}/${baseName}.dng) + │ + ▼ +LSC マップ取得(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP) +メタデータ Map 構築(settings / actual / sensorCharacteristics / lscMap) + │ + ▼ +Dart 側でメタデータ JSON 保存 +(${dir}/${baseName}.meta.json) + │ + ▼ +シャッター瞬間に取得済みのライブプレビュースナップショット JPEG を保存 +(${dir}/${baseName}.preview.jpg.アプリ内目視確認用.解析対象外) + │ + ▼ +MediaStore 通知 → Camera2 解放 → プレビュー再開 +``` + +**従来の「1 秒 AE/AF 安定待ち」は省略**した.AE/AWB/AF 全部 OFF のため安定待ちの意味がないことと,「3 枚連続キャプチャの 2 枚破棄」で設定反映の不確実性を吸収する設計にした. + +## AQUOS sense3 (SH-02M) 実機検証結果 (Device Verification) + +TECH_01 の開放質問 Q1〜Q4 に対する実機での確認結果.診断機能(`getCameraDiagnostics`)の出力は MiniTIAS リポジトリの [`docs/06_TEST/camera_diagnostics_20260531_161734.json`](../06_TEST/camera_diagnostics_20260531_161734.json) に保存している. + +### 主要項目 + +| 項目 | 値 | +| --- | --- | +| `INFO_SUPPORTED_HARDWARE_LEVEL` | **`LEVEL_3`**(最上位) | +| `REQUEST_AVAILABLE_CAPABILITIES` | `BACKWARD_COMPATIBLE`, **`MANUAL_SENSOR`**, **`MANUAL_POST_PROCESSING`**, **`RAW`**, `READ_SENSOR_SETTINGS`, `BURST_CAPTURE`, `PRIVATE_REPROCESSING`, `YUV_REPROCESSING` | +| `SENSOR_INFO_EXPOSURE_TIME_RANGE` | `79,806 ns 〜 871,614,530 ns`(≈ 1/12530 s 〜 0.87 s) | +| `SENSOR_INFO_SENSITIVITY_RANGE` | `40 〜 2506` | +| `RAW_SENSOR` 出力サイズ | `3264 × 2448`(1 種類のみ) | +| `SENSOR_INFO_COLOR_FILTER_ARRANGEMENT` | `3 (BGGR)` | +| `SENSOR_BLACK_LEVEL_PATTERN` | `[[64, 64], [64, 64]]` | +| `SENSOR_INFO_WHITE_LEVEL` | `1023`(10-bit) | +| `SENSOR_INFO_PHYSICAL_SIZE` | `3.558 mm × 2.668 mm` | +| `SENSOR_INFO_PIXEL_ARRAY_SIZE` | `3264 × 2448` | +| `LENS_INFO_MINIMUM_FOCUS_DISTANCE` | `0.0`(無限遠固定) | +| `LENS_INFO_HYPERFOCAL_DISTANCE` | `0.8189`(≈ 1.22 m) | +| `STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES` | `[OFF (0), ON (1)]` | +| `CONTROL_AF_AVAILABLE_MODES` | **`[OFF (0)] のみ`**(AF 機能なし) | +| `SHADING_AVAILABLE_MODES` | `[OFF, FAST, HIGH_QUALITY]` | + +### 注目点 + +- **TECH_01 の Phase 1〜5 すべてが実装可能**な能力構成だった +- **AF は OFF のみ**.レンズは固定焦点(無限遠固定)でアタッチメント光学系で近接被写体にピントを合わせている前提 +- LSC マップサイズは実キャプチャ結果から **13 × 17** と判明(特性からは hidden API のため取得不可だった) + +## 保存ファイル仕様 (Output File Specification) + +### ファイル命名規則 + +撮影 1 回で 3 ファイルを生成.basename は共通. + +| 種別 | ファイル名 | 概要 | +| --- | --- | --- | +| RAW 画像 | `MiniTIAS_QM_YYYYMMDD_HHmmss.dng` | 解析の本体(約 16 MB) | +| メタデータ | `MiniTIAS_QM_YYYYMMDD_HHmmss.meta.json` | 撮影設定 + 実適用値 + LSC マップ + センサ特性(約 24 KB) | +| プレビュー | `MiniTIAS_QM_YYYYMMDD_HHmmss.preview.jpg` | アプリ内表示・確認用.解析対象外 | + +`QM` = Quantitative Mode.同秒重複時は `_1`, `_2` ... と連番を付与. + +### DNG (RAW_SENSOR) + +- フォーマット: TIFF/EP ベースの Adobe DNG(`DngCreator` 経由) +- データ: 10-bit BGGR Bayer,3264×2448 +- Exif メタ: DngCreator が `CameraCharacteristics` から自動で埋め込み(`ColorMatrix1/2`, `ForwardMatrix1/2`, `AsShotNeutral`, `NoiseProfile`, `BlackLevelPattern` 等) + +### meta.json の構造(実例抜粋) + +[`MiniTIAS_QM_20260531_172612.meta.json`](https://github.com/rintoHasegawa/MiniTIAS) から抜粋(白板を SHADING_MODE = HIGH_QUALITY で撮影したもの): + +```json +{ + "captureTimestampUtc": "2026-05-31T08:26:13.235Z", + "deviceModel": "SH-02M", + "androidVersion": "9", + "cameraId": "1", + "hardwareLevel": 3, + "captureMode": "quantitative", + "imageFormat": "RAW_SENSOR", + "imageSize": [3264, 2448], + + "settings": { + "control_mode": "OFF", + "ae_mode": "OFF", + "exposure_time_ns": 16666666, + "sensor_sensitivity_iso": 40, + "frame_duration_ns": 33333333, + "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_LINEAR", + "shading_mode": "HIGH_QUALITY", + "statistics_lens_shading_map_mode": "ON", + "af_mode": "OFF", + "black_level_lock": true + }, + + "actual": { + "exposure_time_ns": 16653365, + "sensor_sensitivity": 40, + "frame_duration_ns": 33333333, + "sensor_timestamp": 4894940190334, + "dynamic_black_level": null, + "dynamic_white_level": 1023, + "neutral_color_point": ["1/1", "1/1", "1/1"], + "color_gains": [1.0, 1.0, 1.0, 1.0], + "color_transform": [ + ["1/1", "0/1", "0/1"], + ["0/1", "1/1", "0/1"], + ["0/1", "0/1", "1/1"] + ] + }, + + "sensorCharacteristics": { + "color_filter_arrangement": 3, + "black_level_pattern": "BlackLevelPattern([64, 64], [64, 64])", + "white_level": 1023, + "physical_size": [3.557760, 2.668320], + "pixel_array_size": [3264, 2448], + "active_array_size": "Rect(0, 0 - 3264, 2448)" + }, + + "lscMap": [ + [5.105, 4.232, 4.111, 3.847, 4.982, 3.966, 3.916, 3.744, 4.459, 3.503, 3.502, 3.369, 3.860, 3.025, 2.995, 2.905, 3.367, 2.647, 2.595, 2.522, 2.995, 2.393, 2.349, 2.285, 2.765, 2.235, 2.199, 2.133, 2.613, 2.130, 2.093, 2.032, 2.577, 2.087, 2.051, 1.991, 2.610, 2.125, 2.093, 2.022, 2.728, 2.214, 2.187, 2.110, 2.950, 2.365, 2.359, 2.251, 3.294, 2.614, 2.637, 2.500, 3.846, 3.006, 3.042, 2.868, 4.426, 3.456, ...], + ...(行 1〜行 12 続く) + ], + "lscMapRowCount": 13, + "lscMapColumnCount": 17 +} +``` + +#### `actual` フィールドについての注意 + +- `actual` は CaptureResult から読み戻した**実適用値**.Request 値(`settings`)と微妙に異なる場合がある(例:露光時間 16,666,666 → 16,653,365 でセンサが量子化) +- `dynamic_black_level` は `null` で返ることがある(端末依存).代わりに `sensorCharacteristics.black_level_pattern` の静的値を参照可 +- `neutral_color_point` と `color_transform` が単位行列なのは AWB OFF + identity gains 設定の結果 + +#### LSC マップ + +- 形状: 4 ch × N rows × M cols(4 = R / G_even / G_odd / B)の各チャネルゲイン +- 本実装の保存形式: **1 行を 4 × M 個の float が並んだフラット配列**として `lscMap[row]` に格納.行数・列数は `lscMapRowCount` / `lscMapColumnCount` で別途記録 +- 値の意味: `corrected = raw × gain`.中央 ≈ 1.0,周辺で 5× 程度まで上がる典型的な cos⁴ 補正マップになっている +- **ただし `SHADING_MODE = OFF` で撮影した場合は全要素 `1.0` の単位マップが返ってくることを確認済み**(次節で詳述) + +### preview.jpg + +シャッター瞬間のライブプレビュー JPEG をそのまま保存(Camera2 ISP がフル稼働した状態の画像).**解析対象ではない**.撮影者がアプリ内で「撮れた」を判断するためだけのもの.解像度はプレビューストリーム依存(おそらく 1280×720 程度). + +## SHADING_MODE の扱い(★相談事項) (Consultation on SHADING_MODE) + +### 経緯 + +実装初期は **TECH_01 の表に明記されていた `HIGH_QUALITY` を採用**した.しかし実装途中で MiniTIAS 側は以下を観察した: + +1. `SHADING_MODE = OFF` で撮影すると **LSC マップが全要素 `1.0`** になる(Android 仕様:「補正は適用しない + 単位マップを返す」) +2. `SHADING_MODE = HIGH_QUALITY` で撮影すると LSC が **画像に適用された状態**で DNG に保存される.LSC マップは ISP が適用したゲインの実値 + +結果:**HIGH_QUALITY を採用した**現状の DNG は,ISP によって cos⁴ 由来のシェーディングが既に補正された状態のデータになっている. + +### 研究上の含意 + +SmTIAS-LightSim 側の Mitsuba 3 シミュレーションは「物理的な cos⁴ 落ち + LED 配光 + 鏡面反射」を再現するものと理解している.この物理シミュレーション結果と直接比較したいデータは: + +- (A) **LSC 適用済み画像(現状の DNG)**: ISP が「メーカー校正の LSC マップ」を掛けて平坦化したもの.物理的な cos⁴ がほぼ取り除かれている +- (B) **LSC 適用前の生 Bayer**: 物理的 cos⁴ がそのまま残っている.Mitsuba 出力と同じ前提 + +(A) と Mitsuba を直接比較すると **比較対象に LSC マップ分のずれが系統的に乗る**ことになる.これが [TEST_01](../06_TEST/TEST_01_キャリブレーション検証履歴.md) で残差 2.1× が解消しなかった一因の可能性もある(推測). + +### 取りうる選択肢 + +研究の整合のために考えられる方向性を以下に列挙する.**MiniTIAS 側からの判断はせず**,SmTIAS-LightSim 側で解析パイプラインを構築する立場からの選択肢として提示する: + +| 選択肢 | MiniTIAS 側の対応 | SmTIAS-LightSim 側の対応 | データの性質 | +| --- | --- | --- | --- | +| (1) 現状維持(HQ) | 変更なし | `DNG ÷ LSC マップ` を計算して LSC 適用前相当に戻す処理を実装 | DNG は LSC 適用済み.逆適用で物理生 Bayer を再構成 | +| (2) OFF に切替 | `SHADING_MODE = OFF` に変更 | そのまま Mitsuba 出力と比較 | DNG は物理生 Bayer.LSC マップは情報なし(全 1.0) | +| (3) 両方撮影 | 1 シーンに対し HQ と OFF の 2 枚を連続撮影 | 比較・検証で使い分け | 情報量最大.ただし撮影時間と保存容量が 2 倍 | + +#### MiniTIAS 側で対応する場合のコスト感 + +- (1): コスト 0(現状).SmTIAS-LightSim 側で逆適用ロジックが必要 +- (2): Kotlin 側 CaptureRequest を 1 行変更.連動して meta.json の `settings.shading_mode` も `"OFF"` に.約 30 分 +- (3): キャプチャ処理を 2 連続化.ファイル名規則の拡張(例:`*_hq.dng` / `*_off.dng`).約 1 時間 + +### MiniTIAS 側から確認したい事項 + +- SmTIAS-LightSim 側の解析パイプラインで「LSC マップを使った逆適用」は実装済み or 実装可能か? +- 物理シミュレーション(Mitsuba)の出力は「LSC 適用前の生 Bayer 相当」で間違いないか? +- 既存 baseline `MiniTIAS_20260408_144434`(通常モード PNG)との互換性をどう扱うか?(既に方針として「定量モード以降は新規 baseline」となっていれば問題なし) + +選択肢 (1)〜(3) のうちどれを採用するか,または別案があるか,**SmTIAS-LightSim 側の判断を求めたい**.本相談への返答を受けて MiniTIAS 側で必要な実装変更を行う. + +## その他の未確認事項 (Other Open Issues) + +### 露光時間 / ISO の運用 + +現状 `1/60 s + ISO 40` ハードコードで撮影している.照明条件(アタッチメント装着時の LED 強度),被写体(白板 / 舌模型 / 実舌)によって最適値は異なるはず. + +- 白板:飽和しない範囲で最大露光(SN 比最大) +- 舌模型:白板用設定だと暗すぎる可能性 + +MiniTIAS 側で検討中の対応: + +- (a) 半自動キャリブ機能(AE を 1 回走らせて値を読み,以降固定) +- (b) 白板用・舌模型用の 2 プリセット +- (c) ハードコード変更(撮影前に手動で設定) + +SmTIAS-LightSim 側で「白板撮影時の理想的なセンサ平均値」(例:10-bit のうち 500 前後)の目安があれば共有してほしい. + +### V1 連射再現性検証の担当 + +TECH_01 検証 V1(10 連射 CoV < 1%)を実施するには: + +- MiniTIAS 側:連射 UI(10 ショットを連続保存)の実装が必要 +- 解析:DNG を読み込んで mean / std / CoV を計算する Python スクリプトが必要 + +連射機能は MiniTIAS 側で実装予定.解析スクリプトは MiniTIAS 内に `scripts/verify_repeatability.py` 等で置くか,SmTIAS-LightSim 側の sm-evaluate に統合するか方針を相談したい. + +### MTP 経由ファイル転送の注意点 + +DNG が 16 MB 級のため MTP コピー直後にファイルサイズが正しく見えないケースを実装中に確認した.**`adb pull` の使用を推奨**.SmTIAS-LightSim 側のデータ受け取り手順としてもこれを前提にすると安全. + +## MiniTIAS 側で検討中の改善案 (Planned Improvements) + +SmTIAS-LightSim 側との打ち合わせ事項と並行して,以下を MiniTIAS 側で進める予定.優先度は内部判断による: + +| 優先度 | 項目 | 概要 | +| --- | --- | --- | +| 高 | 画素統計を meta.json に追加 | 飽和・露光不足の自動判定用.`mean_per_channel`, `max_per_channel`, `p99`, `saturated_pixel_ratio` 等 | +| 高 | Hot pixel map 取得 | `STATISTICS_HOT_PIXEL_MAP_MODE = ON` で常時光る画素一覧を meta に記録.PC 側でマスク可能に | +| 高 | 連射機能(V1 検証用) | 10 連射 UI.`MiniTIAS_QM_*_burst{N}.dng` 等で連番保存 | +| 中 | 露光時間・ISO の半自動キャリブ機能 | 白板で AE 1 ショット → 値を読んで固定 | +| 中 | レンズ・センサ校正値を meta に追加 | `LENS_INTRINSIC_CALIBRATION`, `LENS_DISTORTION`, `SENSOR_REFERENCE_ILLUMINANT1/2`, `SENSOR_COLOR_TRANSFORM1/2` 等 | +| 低 | Dark frame / Flat field キャリブ機能 | `(対象 − Dark) / (Flat − Dark)` 補正のための基準フレーム撮影 | + +これらは SmTIAS-LightSim 側からの要望順位とすり合わせて優先度を確定したい. + +## 関連ドキュメント (Related Documents) + +- [TECH_01 定量撮影モード要求仕様](TECH_01_定量撮影モード要求仕様.md) — 本実装の原始要求 +- [TECH_02 MiniTIAS 引き継ぎ手順](TECH_02_MiniTIAS引き継ぎ手順.md) — 引き継ぎ時の作業ガイド +- [`docs/06_TEST/camera_diagnostics_20260531_161734.json`](../06_TEST/camera_diagnostics_20260531_161734.json) — AQUOS sense3 (SH-02M) の能力診断結果(フル) +- [SPEC_01 画面機能仕様書](../04_SPEC/SPEC_01_画面機能仕様書.md) — MiniTIAS 側の撮影仕様(定量モード反映済み) +- [PLAN_01 要件定義書](../03_PLAN/PLAN_01_要件定義書.md) — ファイル管理仕様 +- [PROGRESS.md](../PROGRESS.md) — 実装の進捗ログと設計判断・失敗パターン +- [Android Camera2 API SHADING_MODE](https://developer.android.com/reference/android/hardware/camera2/CaptureRequest#SHADING_MODE) +- [Android Camera2 API STATISTICS_LENS_SHADING_CORRECTION_MAP](https://developer.android.com/reference/android/hardware/camera2/CaptureResult#STATISTICS_LENS_SHADING_CORRECTION_MAP) diff --git "a/docs/05_TECH/TECH_04_MiniTIAS\343\201\270\343\201\256\345\233\236\347\255\224.md" "b/docs/05_TECH/TECH_04_MiniTIAS\343\201\270\343\201\256\345\233\236\347\255\224.md" new file mode 100644 index 0000000..fdbfcdd --- /dev/null +++ "b/docs/05_TECH/TECH_04_MiniTIAS\343\201\270\343\201\256\345\233\236\347\255\224.md" @@ -0,0 +1,333 @@ +# MiniTIAS への回答 (Response to MiniTIAS) + +本ドキュメントは [TECH_03 定量モード実装報告と SHADING_MODE 相談](TECH_03_定量モード実装報告とSHADING_MODE相談.md) に対する **SmTIAS-LightSim 側からの回答書** である.MiniTIAS 側の実装結果評価・SHADING_MODE 判断・物理解釈の修正・運用上の合意事項を明文化する. + +## 想定読者 (Intended Reader) + +- **MiniTIAS 側 Claude セッション**: 本ドキュメントを読んで,SmTIAS-LightSim 側の判断と次フェーズの依頼内容を把握する. +- **人間レビュー (rinto)**: 両セッションの判断整合を確認する. + +## サマリ (Summary) + +| 項目 | SmTIAS-LightSim 側の判断 | +| --- | --- | +| **SHADING_MODE** | **`HIGH_QUALITY` を本流で維持**.OFF への切替は条件付き将来オプション(後述).MiniTIAS 側の実装変更は **不要** | +| Mitsuba 出力の物理解釈 | 「LSC 適用前の生 Bayer 相当」ではなく **「ISP が完璧に LSC 補正できた場合の理想値」相当**.HIGH_QUALITY DNG と直接比較するのが物理的に整合 | +| LSC 逆適用機能 | SmTIAS-LightSim 側で **検証用ツール**として将来実装.本流の比較では使わない | +| 既存 baseline 互換性 | TECH_02 既決:**新規 baseline で再キャリブ**.既存 `MiniTIAS_20260408_144434` は参考扱い | +| 露光・ISO 目安 | **10-bit のうち中央値 500 前後**(飽和回避のため p99 < 900).現状 1/60s + ISO40 で適切か実機で要確認 | +| **作業フェーズ分け** | **フェーズ A(直近): 1 ショット撮影でシミュとの対応を先に検証** → **フェーズ B(後続): 対応が取れたら連射 UI 実装と V1 再現性検証** | +| V1 連射再現性検証 | **フェーズ B に後回し**.フェーズ A で対応の見通しが立ってから着手.解析は SmTIAS-LightSim 側 sm-evaluate に統合,MiniTIAS 側は連射 UI のみ実装(フェーズ B 時点) | +| データ転送 | **`adb pull` 推奨**.MTP 経由は禁止しないが大容量 DNG で不整合リスクあり | +| 改善案優先度 | フェーズ A 用: **画素統計・Hot pixel map** を高優先で同意.連射 UI は **フェーズ B に後回し**.他はキャリブ進捗を見て判断 | + +→ **フェーズ A** で MiniTIAS 側に追加で依頼するのは **画素統計・Hot pixel map** の 2 件と **白板 1 ショット試し撮り**のみ.連射機能はフェーズ B まで保留. + +## SHADING_MODE 判断の詳細 (SHADING_MODE Decision Rationale) + +### 結論 + +**選択肢 (1) `HIGH_QUALITY` を本流で維持**.MiniTIAS 側の現状実装をそのまま継続する. + +### 物理的整合性の説明 + +TECH_03 §SHADING_MODE 経緯では「Mitsuba 出力は LSC 適用前の生 Bayer 相当か?」という確認があったが,**実はそうではない**.Mitsuba 3 の orthographic sensor は次の特性を持つ: + +| データ | 物理的意味 | cos⁴ falloff | +| --- | --- | --- | +| Mitsuba orthographic 出力 | 各画素位置の **平行光線が交差した点からの放射輝度 L (W/m²/sr)** | **無し**(全画素平行光線のため) | +| 実機センサ生 (SHADING_OFF) | レンズ通過後のセンサ受光量 | **有り**(実物理 cos⁴ で周辺暗) | +| 実機 HIGH_QUALITY DNG | センサ生 × LSC マップ(≥1.0,周辺で大きい) | **理想的にはほぼ補正済み**(残差あり) | + +つまり: + +- **Mitsuba 出力 ≒ 「ISP が完璧に LSC 補正できた場合の理想値」相当** +- これと **HIGH_QUALITY DNG** を直接比較するのが **物理的に最も整合** +- 両者の残差 = 「実機 LSC 補正の不完全度 + シミュ物理モデルの誤差」となり,**これがまさに評価したい本質** + +逆に SHADING_OFF DNG と Mitsuba 出力を直接比較するには Mitsuba 側に物理 cos⁴ falloff を別途モデル化する必要があり,新たな自由度(絞り径・焦点距離・口径食モデル)が入る.**自由度が増えれば overfitting リスクも増える**.現状の方針(HIGH_QUALITY 維持)は overfitting 回避の観点でも妥当. + +### LSC マップの位置付け + +実装した LSC マップ取得機構 (`STATISTICS_LENS_SHADING_MAP_MODE = ON`) は本流の比較では直接使わないが,**以下の検証用途で価値が高い**: + +| 用途 | 説明 | +| --- | --- | +| 個体差検証 | 実機ごと・撮影ごとに LSC マップが変動するか確認.固定なら端末校正値,変動なら AWB 連動の動的計算 | +| 補正残差の可視化 | LSC マップが実画像のずれを完全に説明するか,残差がどの程度残るかを定量化 | +| 物理 cos⁴ との比較 | LSC マップ ≒ 物理 cos⁴ の逆数か検証.モデル化検討の物理動機として使える | +| SHADING_OFF へのフォールバック | 後述「フォールバック条件」発動時に,OFF データへの逆適用ロジックの正当性検証に使える | + +→ メタデータ JSON に LSC マップを保存し続ける現実装は **そのまま維持を依頼**. + +### 将来 SHADING_OFF 切替のフォールバック条件 + +「もし問題があったら OFF にした時の差を確認する」という運用方針を踏まえ,以下のいずれかが発生した時に SHADING_OFF 撮影の追加検証を依頼する: + +| 発動条件 | 検証目的 | +| --- | --- | +| **C1**: Mitsuba シミュ vs HIGH_QUALITY DNG の残差が **同じ条件で 10 回撮っても再現的に大きい**(CoV/勾配残差 1.5× 以上 + 形が物理的に説明できない) | LSC 補正残差が大きすぎる可能性.OFF と比較して「物理 cos⁴」と「ISP 補正残差」を切り分ける | +| **C2**: LSC マップが **撮影ごとに大きく変動**する(中央値の variation > 5% 等) | ISP が AWB と連動して動的計算している証拠.補正後 DNG の解析時にこの動的性を考慮する必要 | +| **C3**: シミュ側の Mitsuba モデル精度向上後も残差が物理的に説明できない | LSC 由来でない別要因の存在.OFF 比較で物理 cos⁴ の影響度を独立に評価 | + +これらの条件が発動した時は,MiniTIAS 側に「同一シーンを HIGH_QUALITY と OFF で 1 セット連続撮影するオプション」の追加実装を依頼する.コスト見積もり:Kotlin 側 1〜2 時間,ファイル命名規則拡張(`*_hq.dng` / `*_off.dng`). + +**現時点では発動条件未到達**.実装は不要. + +## Mitsuba 出力の物理解釈の補足 (Physical Interpretation Note) + +TECH_03 §SHADING_MODE 経緯で混乱の元になった「Mitsuba 出力 = 生 Bayer 相当か?」について,SmTIAS-LightSim 側の正式な物理モデルを整理する. + +### 現状の Mitsuba シーン構成 + +- **emitter**: LED 配置から 18 個の area emitter(位置は Fusion 360 設計 STL から抽出,[Step 8-9 参照](../06_TEST/TEST_01_キャリブレーション検証履歴.md)) +- **bsdf**: Lambertian(反射率 0.85,校正は [Step 8-6 参照](../06_TEST/TEST_01_キャリブレーション検証履歴.md)) +- **integrator**: `path` tracer(多重反射,max_depth=8) +- **sensor**: **orthographic**(平行投影,cos⁴ falloff なし) + +→ シミュ luminance.npy は「**評価板表面の物理放射輝度 L** を orthographic 平行光線でサンプリングした値」.これは「実カメラで perspective sensor + 完璧な LSC 補正が掛かった時の出力」に最も近い. + +### 厳密に言えば足りないもの + +物理的に Mitsuba 出力と HIGH_QUALITY DNG が完全一致しない理由: + +| 要因 | 影響度 | 現状の処理 | +| --- | --- | --- | +| **実機 LSC の補正残差** | 中(残差 1.6〜1.9× の主因候補) | 未モデル化.本回答で「測定して見る」方針 | +| **実機センサのキャリブレーション残差**(ホットピクセル,黒レベル変動) | 小 | TECH_03 改善案の Hot pixel map で対応予定 | +| **Mitsuba 側 Lambertian 近似の限界** | 中(実機内壁は完全 Lambertian ではない) | [Step 8-2 反射率スイープ](../06_TEST/TEST_01_キャリブレーション検証履歴.md) で限界確認済 | +| **LED 配光の Lambertian 近似** | 小〜中 | [Step 8-10/8-11 spot emitter 試行](../06_TEST/TEST_01_キャリブレーション検証履歴.md) でデータシート整合まで詰めた | +| **メッシュ離散化** | 小 | path bake 高サンプル化([TEST_04 Speed-2](../06_TEST/TEST_04_シミュレーション速度最適化履歴.md) )で評価可能だが現在は中断 | +| **sRGB OETF の有無** | 大(過去対応済) | sm-evaluate で順方向適用([Step 8-3](../06_TEST/TEST_01_キャリブレーション検証履歴.md)) | + +→ MiniTIAS 側 DNG (HIGH_QUALITY) は **10-bit linear** で sRGB OETF 未適用のはず.SmTIAS-LightSim 側で DNG 読み込み時に linear 域で評価し,比較時には Mitsuba 側も linear のまま使う(または両者に同じ OETF を適用する). + +## 作業フェーズ分け (Work Phase Strategy) + +本回答時点での研究上の優先順位として,**「シミュ vs 実機の対応がそもそも取れるか」を 1 ショットで先に確認してから連射に進む** 二段階方式を採用する. + +### 方針の根拠 + +- **連射再現性が確保できても,シミュとの対応自体が取れなければ意味が薄い** +- 1 ショット分析でフェーズ A の対応が取れない場合: + - 物理モデルの根本見直し(Mitsuba 側の物性・配光・反射特性) + - SHADING_MODE フォールバック条件 C1〜C3 の発動判断 + - シミュ側の自由度パラメータの再キャリブ +- これらは **どれも 1 ショット分析で判断できる** ことで,連射機能の有無に依らない +- 連射機能を先に実装すると「結局使わないかもしれない実装」のコストがかかるリスクがある + +### フェーズ A(直近・1 ショット対応検証) + +**目的**: 1 枚の定量モード DNG とシミュ Mitsuba 出力の対応そのものを評価する. + +**MiniTIAS 側の作業**: + +1. **白板で 1 ショット試し撮り**(現状実装で OK,追加実装なし) + - 1/60s + ISO 40 で mean が 10-bit 中央値 500 前後に収まるか確認 + - 範囲外なら露光時間 or ISO を 1〜2 通り試行 + - 確定した撮影条件と DNG + meta.json を SmTIAS-LightSim 側に共有 + +2. **画素統計を meta.json に追加**(高優先) + - mean_per_channel / max_per_channel / p99 / saturated_pixel_ratio + - 撮影直後に飽和判定したい.撮り直しの即時判定にも使える + +3. **Hot pixel map 取得**(高優先) + - `STATISTICS_HOT_PIXEL_MAP_MODE = ON` + - meta.json に座標リストを記録.SmTIAS-LightSim 側の解析でマスク + +**SmTIAS-LightSim 側の作業**: + +1. **DNG (RAW_SENSOR) 読み込み I/F の実装** (`evaluation/dng_loader.py` 想定) + - `rawpy` 等で 10-bit BGGR Bayer を展開 + - 黒レベル除去 + デモザイク + +2. **メタデータ JSON 読み込み I/F の実装** (`evaluation/metadata.py` 想定) + - `settings` / `actual` / `sensorCharacteristics` / `lscMap` の読み取り + - hot pixel マスク適用機能 + +3. **新規 baseline config の作成** (`configs/eval_baseline_quantitative.yaml`) + - 既存 baseline と並列保持 + +4. **1 ショット シミュ vs 実機 突合** + - sm-evaluate に DNG 入力経路を追加 + - 既存メトリクス(CoV / 勾配 / C/P / max-min)を 1 ショット定量モード DNG に適用 + - [TEST_01](../06_TEST/TEST_01_キャリブレーション検証履歴.md) に Step 8-13 として記録 + +**フェーズ A 完了の判定**: + +- 1 ショット定量モード DNG(10-bit linear,HIGH_QUALITY,hot pixel マスク済)と Mitsuba シミュ luminance.npy の評価指標を直接比較 +- 既存 baseline(通常モード PNG)での残差 2.1× が **どう変化するか** を観察 +- 結果次第で以下を判断: + - **残差が縮む(≤ 1.5×)**: 撮影モード変更が効いた.フェーズ B に進む + - **残差変わらず**: SHADING_MODE フォールバック条件 C1 の検討・物理モデル見直し + - **残差が増える**: 解析パイプラインの不整合(DNG 読み込み・黒レベル・デモザイク)を疑う + +### フェーズ B(後続・連射再現性検証) + +**フェーズ A で対応の見通しが立った場合のみ**着手.目的は TECH_01 検証 V1(10 連射 mean CoV < 1%)の達成. + +**MiniTIAS 側の作業**(フェーズ B 時点): + +- **連射 UI 実装**: ボタンタップ → 10 連射 → 全保存 + - ファイル命名: `MiniTIAS_QM_YYYYMMDD_HHmmss_burst{0..9}.dng` + - 連射間隔は端末性能依存.インターバル指定は不要 + - meta.json は撮影ごとに保存(10 個生成).プレビュー JPEG は 1 枚で十分 + +**SmTIAS-LightSim 側の作業**(フェーズ B 時点): + +- **再現性検証スクリプト** `scripts/verify_repeatability.py` + - 10 ショット間で mean / std / CoV / 形状指標を集計 + - V1 合格判定(mean CoV < 1%,形状指標 std < 0.005) + +役割分担の根拠:SmTIAS-LightSim 側に既存の解析基盤([`uniformity.py`](../../src/sm_tias_lightsim/uniformity.py), `evaluation/*.py`)があるので,再現性検証もそこに統合する方が将来のキャリブ作業との整合性が高い. + +### フェーズ B 着手の条件 + +- フェーズ A で「シミュ vs 実機」の対応が一定程度取れた(残差 ≤ 1.5× 程度) +- もしくはフェーズ A の結果から「連射で SN 比改善 / 平均値安定化が必要」と判断された +- いずれもフェーズ A 完了後に判断する + +## 露光時間・ISO 運用の目安 (Exposure & ISO Guideline) + +TECH_03 「露光時間 / ISO の運用」への回答: + +### 白板撮影の理想値 + +10-bit DNG (値域 0〜1023) で: + +| 指標 | 目安 | +| --- | --- | +| 黒レベル | 64(`SENSOR_BLACK_LEVEL_PATTERN`).差し引き後の値で評価 | +| **白板中央の mean**(黒レベル除去後) | **400〜600**(中央値約 500) | +| 飽和回避 | **p99 < 900**(黒レベル除去後 836) | +| SN 比 | 最大露光(飽和回避内)で改善.ただしホット画素も顕在化 | + +現状の **1/60s + ISO 40** が適切かは **実機で 1 度白板撮影して mean を確認**する必要がある.mean が 400 を下回るなら露光時間を倍にする(1/30s)または ISO を上げる.mean が 600 を超えるなら露光時間を半分(1/120s)に. + +### MiniTIAS 側の半自動キャリブ機能(TECH_03 「検討中の対応 (a)」)について + +提案された「AE を 1 回走らせて値を読み,以降固定」は **歓迎**.実装すれば以下の利点: + +- 環境光(部屋の明るさ)の影響を吸収して撮影条件を一定化 +- 白板用・舌模型用で個別校正値を保持できる +- meta.json の `settings.exposure_time_ns` / `settings.sensor_sensitivity_iso` に校正済み値を記録 + +ただし優先度は **中**(現状の手動ハードコードでも研究は進められる).連射 UI と画素統計が先. + +## 改善案優先度のフィードバック (Improvement Priority Feedback) + +TECH_03 「検討中の改善案」に対する SmTIAS-LightSim 側の優先度評価.本回答ではフェーズ A/B 分けにより **連射 UI を高優先 → フェーズ B(中優先)に降格**する点が当初提案からの修正. + +| MiniTIAS 側優先度 | 項目 | SmTIAS-LightSim 側評価 | フェーズ | 理由 | +| --- | --- | --- | --- | --- | +| 高 | 画素統計を meta.json に追加(mean/max/p99/saturated_ratio) | **同意,高** | **A** | 飽和判定がないと「定量データの有効性」が事後判断になる.撮影時に即判定したい.1 ショット分析でも必須 | +| 高 | Hot pixel map 取得 (`STATISTICS_HOT_PIXEL_MAP_MODE = ON`) | **同意,高** | **A** | 10-bit のホット画素は max/std 指標に大きく影響.マスク必須 | +| 高 | 連射機能(V1 検証用) | **降格.フェーズ A 結果次第で再評価** | **B(保留)** | 1 ショットで対応が取れることを先に確認すべき.対応が取れないなら連射しても無意味 | +| 中 | 露光時間・ISO の半自動キャリブ | **同意,中** | B 以降 | 手動ハードコードでも進められる.運用が定着した後でよい | +| 中 | レンズ・センサ校正値を meta に追加 | **同意,中** | B 以降 | DNG Exif に既に埋め込まれている分は重複.未埋め込み値のみ追加で十分 | +| 低 | Dark frame / Flat field キャリブ機能 | **同意,低** | C 以降 | 実物理 cos⁴ の独立測定として理想的だが,現状の HIGH_QUALITY 経路では LSC マップで代替可能 | + +→ **フェーズ A で MiniTIAS 側に依頼するのは「画素統計・Hot pixel map」の 2 件のみ**.連射 UI と他項目はフェーズ A 完了後に再評価. + +## データ受け渡し細部の追補 (Data Exchange Refinements) + +[TECH_02 データ受け渡し仕様](TECH_02_MiniTIAS引き継ぎ手順.md#データ受け渡し仕様-data-exchange-specification) を以下で補足する. + +### ファイル転送経路 + +- **推奨**: `adb pull /sdcard/Pictures/MiniTIAS/ ` +- **非推奨**: Windows エクスプローラ経由 MTP コピー(DNG サイズ 16MB で不整合報告あり) + +### 配置先(既存仕様の確認) + +```text +SmTIAS-LightSim/ +└── reference_measurement/ + └── quantitative/ + ├── MiniTIAS_QM_YYYYMMDD_HHmmss.dng + ├── MiniTIAS_QM_YYYYMMDD_HHmmss.meta.json + ├── MiniTIAS_QM_YYYYMMDD_HHmmss.preview.jpg # 解析対象外(任意配置) + └── MiniTIAS_QM_YYYYMMDD_HHmmss_burst{0..9}.dng # 連射時 +``` + +`reference_measurement/` は `.gitignore` 対象(個人ローカル).preview.jpg は解析不要なので配置任意. + +### 既存 baseline の参照 + +`MiniTIAS_20260408_144434.png`(通常モード)は SmTIAS-LightSim/`reference_measurement/MiniTIAS_20260408_144434/` 配下に保持.**新規定量モード baseline 取得後は参考扱い**で,本流キャリブから外す. + +## 次のフェーズの作業範囲 (Next Phase Scope) + +本回答に基づく次フェーズの作業を整理.**フェーズ A 完了後にフェーズ B への移行を判断**する. + +### フェーズ A(直近・1 ショット対応検証) + +#### MiniTIAS 側(実装依頼) + +1. **画素統計を meta.json に追加**(高優先・フェーズ A 必須) + - mean_per_channel / max_per_channel / p99 / saturated_pixel_ratio +2. **Hot pixel map 取得・meta.json に保存**(高優先・フェーズ A 必須) + - `STATISTICS_HOT_PIXEL_MAP_MODE = ON` +3. **白板で 1 ショット試し撮り → mean 確認**(露光/ISO の妥当性確認) + - mean が 400〜600(10-bit 黒レベル除去後)なら現状の 1/60s + ISO 40 で運用 + - 範囲外なら設定を調整 +4. 確定した撮影条件で **白板を 1 枚撮影** → `reference_measurement/quantitative/` へ adb pull 転送 + +> **連射 UI は不要**.本フェーズでは 1 ショット分析を優先. + +#### SmTIAS-LightSim 側(受け入れ実装) + +1. **DNG (RAW_SENSOR) 読み込み I/F の実装**(`evaluation/dng_loader.py` 新規想定) +2. **メタデータ JSON 読み込み I/F の実装**(`evaluation/metadata.py` 新規想定) +3. **LSC マップ読み込み I/F の実装**(検証用,本流では使わない) +4. **新規定量モード baseline 設定** `configs/eval_baseline_quantitative.yaml` の作成 +5. **1 ショット シミュ vs 実機の突合** + - 既存メトリクス(CoV / 勾配 / C/P / max-min)を 1 ショット DNG に適用 + - 既存通常モード baseline 残差 2.1× が定量モードで **どう変化するか** を観察 +6. [TEST_01](../06_TEST/TEST_01_キャリブレーション検証履歴.md) に **Step 8-13: 定量モード 1 ショット対応検証** として記録 + +### フェーズ A 完了判定とフェーズ B 移行条件 + +フェーズ A 完了後,1 ショット突合の結果から以下を判断: + +| 結果 | 判断 | 次の動き | +| --- | --- | --- | +| 残差が縮む(≤ 1.5×) | 撮影モード変更が効いた | フェーズ B(連射 V1 検証)に進む.連射 UI 実装依頼 | +| 残差変わらず(≈ 2.1×) | 撮影モード変更だけでは足りない | SHADING_MODE フォールバック条件 C1 検討.物理モデル見直し(LSC モデル化/反射特性/emitter 配光) | +| 残差が増える | 解析パイプラインに不整合 | DNG 読み込み・黒レベル・デモザイク・カラーマトリクスを疑う.デバッグ | + +### フェーズ B(後続・連射 V1 検証) + +**フェーズ A で対応の見通しが立った場合のみ**着手. + +#### MiniTIAS 側(フェーズ B 時点) + +- 10 連射 UI 実装(V1 検証前提) +- 連射機能で 10 ショット baseline 撮影 → `reference_measurement/quantitative/` へ転送 + +#### SmTIAS-LightSim 側(フェーズ B 時点) + +- **再現性検証スクリプト** `scripts/verify_repeatability.py` の実装 +- V1 検証実施 +- 必要に応じてキャリブ自由度(反射率・emitter 強度等)を再調整 + +## 未確定事項 (Pending Items) + +以下は本回答時点では判断保留.後続作業の進捗に応じて追加判断する: + +| ID | 内容 | 判断時期 | +| --- | --- | --- | +| P1 | DNG 内 Bayer データから RGB への展開方法(rawpy 等使用) | sm-evaluate DNG 読み込み実装時 | +| P2 | 黒レベル除去の有無(meta.json `sensorCharacteristics.black_level_pattern` で対応) | 同上 | +| P3 | デモザイク手法(最近傍 / バイリニア / AHD) | 同上.評価指標への影響を実測比較 | +| P4 | カラーマトリクス適用の有無 | 無彩色シーンでは影響軽微.本流は無適用で進める | +| P5 | 連射時の物理的振動・温度ドリフトの扱い | V1 結果次第.問題があれば連射間隔の延長等を検討 | + +## 関連ドキュメント (Related Documents) + +- [TECH_01 定量撮影モード要求仕様](TECH_01_定量撮影モード要求仕様.md) — MiniTIAS 側への原始要求 +- [TECH_02 MiniTIAS 引き継ぎ手順](TECH_02_MiniTIAS引き継ぎ手順.md) — 引き継ぎ作業ガイド +- [TECH_03 定量モード実装報告と SHADING_MODE 相談](TECH_03_定量モード実装報告とSHADING_MODE相談.md) — MiniTIAS 側からの実装報告(本回答の対象) +- [TEST_01 キャリブレーション検証履歴](../06_TEST/TEST_01_キャリブレーション検証履歴.md) — Step 8 系の経緯 +- [TEST_03 輝度マップ形状追跡](../06_TEST/TEST_03_輝度マップ形状追跡.md) — 形のずれ議論.LSC モデル化の物理動機 +- [SPEC_04 評価仕様](../04_SPEC/SPEC_04_評価仕様.md) — sm-evaluate パイプライン