# 実機とシミュの形の突き合わせと配光の検討 (Real vs Sim Shape Matching and LED Beam Pattern)

舌撮影デバイスの基準「最大を 1 としたときの最小 ≥ 0.9」に対し，実機を作る前にシミュレーションが
参考になるかを確かめるため，実機 DNG（全灯 1 枚・単灯 3 枚）とシミュを**同じノイズ処理**で
突き合わせた（2026-09-14〜15）．評価の決め手は集約指標（min 等）ではなく**輝度マップの形**
（全灯 + 単灯 3 灯）とした（ユーザー方針）．結論: **同心円方向（お椀）は材質で合うが，単灯で
明部が点灯基板の反対側へ寄る量がシミュは実機の半分以下**．これは壁の光沢（ω・α）では
形全体を崩さずに合わせられず，**LED の配光を狭める（spot，半値全幅 45〜60°）** ことで説明できる．
全構成に共通する「左上が暗い」傾き成分はどちらでも半分しか出ず，基板の位置・向きか
ISP の LSC 残差が残る課題である．

関連:

- 材質パラメータの確定（ρ≈0.81 純 diffuse）と傾き成分の分離: [TEST_14](TEST_14_材質パラメータ再スイープと残差の構造分解.md)
- 単灯の相対結論: [TEST_12 追補](TEST_12_シェーディング法線アーティファクトの発見と修正.md)
- 画像全体 min/max 比の定義: [SPEC_04 評価仕様](../04_SPEC/SPEC_04_評価仕様.md)，[TEST_18](TEST_18_照明配置依存性の球と立方体の比較.md)「均一性の指標」
- spp の指針: [TEST_19](TEST_19_sppと計算時間ノイズ指標安定性.md)
- 実行記録: [TEST_02_シミュレーション実行記録](TEST_02_シミュレーション実行記録.md)

## 実験条件 (Setup)

### 実機データ

| 構成 | ファイル | 備考 |
| --- | --- | --- |
| 全灯 18 灯 | `reference_measurement/quantitative/MiniTIAS_QM_20260601_124500.dng` | 定量モード・ISO 40・8.3 ms・LSC マップ付き |
| 下 / 左 / 右 単灯 | `lightsim/raw/SmTIAS_QM_20260615_{141420,150300,170948}.dng` | 同一セッション・露出固定 |

読み込みは TEST_14 と同じ経路（`load_image_dng` → lscMap 順適用 → Rec.709 → rot90(−1) → 白板 ROI
1400×1409 px）．ROI はシミュ ROI（464×450 px）へリサイズしてから同じ処理を掛ける（平滑化 σ を
画素で揃えるため．約 3×3 画素の平均でセンサノイズも落ちるが，ノイズ補正はリサイズ後の残差から
推定するので整合する）．

### シミュレーション

基準シーン `scene_baseline.yaml`（実機と同じ筐体・18 灯）から，単灯は `led_bottom_*` /
`led_left_*` / `led_right_*` の 6 灯だけを残して作る．材質は次の 2 つを主に使った．

- **採用材質**（TEST_15〜18 で使用）: blendbsdf ρ=0.85・ω=0.05・α=0.1（既存レンダ `full_base_fix` /
  `singles_fix`，spp 1024）
- **TEST_14 の確定値**: 純 diffuse ρ=0.81（本実験で spp 4096 でレンダ．`output/real_vs_sim/sim_*rho081*`）

レンダは研究室サーバ Newton GPU 0（cuda_ad_rgb・mitsuba 3.7.1）．

### 処理と指標（実機・シミュ共通）

- 形の比較: メディアン 5 px → ガウス σ=4 px → ROI 平均で正規化（=1）．差分（シミュ − 実機）の
  RMS・最大，SSIM，NCC．
- 形の記述子: σ=20 平滑化後のピーク位置（ROI 中心からのずれ，半幅比，+x 右・+y 上），
  上下比・左右比（上 1/3 と下 1/3 等の平均比），1 次平面フィットの傾き（振幅 %・方位），
  2 次成分（お椀）の振幅，方位フーリエ a1/b1/a2/a4（TEST_16 の機構）．
- min: 画像全体・ノイズ補正付き最小/最大比（σ=12．`evaluation/fullimage.py`）．参考に補正なし・
  輪帯平均・画素．
- 20 分割放射プロファイル（ROI 平均で正規化）の各ビンの差．

## 結果 1 — 全灯の min・放射プロファイル・形 (Full-Board: min, Profile, Shape)

`output/real_vs_sim/real_vs_sim_{legacy,rho081}.png`．

| 指標 | 実機 | ρ=0.81 純 diffuse（spp 4096） | 採用材質 ρ=0.85 ω=0.05 α=0.1 |
| --- | --- | --- | --- |
| min（画像全体・補正） | **0.727** | 0.787（+0.060） | 0.803（+0.075） |
| min（輪帯平均） | 0.873 | 0.874（+0.001） | 0.901（+0.028） |
| 構造 CoV | 0.067 | 0.046 | 0.039 |
| 20 分割プロファイル RMSE / 最大差 | — | 0.0055 / 0.011 | 0.012 / — |
| 正規化マップ RMS 差 / 最大差 | — | 0.038 / 0.103 | 0.046 / — |
| SSIM / NCC | — | 0.996 / 0.858 | — / 0.858 |
| 方位 m=1 a1 / b1 | +3.8% / +7.1% | −0.3% / +4.0% | −0.2% / +3.6% |

- **同心円方向はよく合う**: 放射プロファイルの差は最大 0.011，輪帯平均の min は 0.001 差．
  ρ=0.81 が TEST_14 どおり妥当．
- **画像全体の min は 0.06 高く出る**．原因は方位方向の非対称で，実機は上（LED と反対側）が暗く
  左右も 6% 非対称なのに，シミュは上下差が半分・左右差ゼロ．TEST_14 で「材質では直せない傾き
  成分」と分離した残差そのもので，輪帯平均では見えず画像全体の min には出る．
- 基準 0.9 に対する判定（不合格）は一致するが，差 0.06 は境目付近では効く．
- シミュのノイズを spp 4096 で半分に下げても min は 0.792 → 0.787 でほぼ不変（補正が機能）．
  実機のノイズ CoV は 0.8% で補正の影響はゼロ．
- TEST_14 のグリッド 59 条件（ρ 0.75〜0.92 × ω × α）を同じ指標で当てても min は 0.774〜0.800 で，
  ω・α では差 0.06 は埋まらない（`output/real_vs_sim/bsdf_grid_vs_real.csv`）．ρ を下げると
  お椀が深くなりすぎて放射プロファイルが崩れるだけ．

## 結果 2 — 形の一致: 全灯 + 単灯 3 灯 (Shape Matching, 4 Configurations)

`output/real_vs_sim/shapes_{legacy,rho081}.png`（上 = 実機・中 = シミュ・下 = 差分）．

採用材質（ρ=0.85・ω=0.05・α=0.1）:

| 構成 | 差分 RMS | SSIM | NCC | 傾き 実機 / シミュ | お椀 実機 / シミュ | ピーク位置 実機 / シミュ |
| --- | --- | --- | --- | --- | --- | --- |
| 全灯 | 0.040 | 0.92 | 0.86 | 9.6% / 4.1% | −8.2% / −6.5% | (+0.41, −0.38) / (+0.03, −0.13) |
| 下 単灯 | 0.039 | 0.90 | 0.84 | 8.1% / 3.4% | −10.2% / −6.7% | (+0.14, −0.43) / (−0.07, −0.22) |
| 左 単灯 | 0.045 | 0.90 | 0.92 | 11.9% / 5.3% | −9.4% / −6.2% | (+0.65, −0.52) / (+0.25, −0.31) |
| 右 単灯 | **0.022** | 0.91 | **0.94** | 6.6% / 4.8%（方位一致） | −7.9% / −6.5% | (−1.00, −0.32) / (−0.28, −0.20) |

- **単灯の明部は点灯基板の反対側へ寄る**（左単灯なら右へ，右単灯なら左へ）．向きはシミュも
  実機も同じだが，**ずれの量はシミュが実機の半分以下**（左 +0.25 vs +0.65，右 −0.28 vs −1.00）．
- 差分は 4 構成すべてで「左上が赤・右下が青」の対角パターン＝実機は左上が暗く右下が明るい傾き
  を持ち，シミュはそれを半分しか再現しない（振幅 実機 8〜12% vs シミュ 3〜5%）．右単灯だけは
  方位も振幅もほぼ合う．TEST_14 の「傾きは下・左の基板に固有」と整合するが，右にも弱い同じ向きの
  傾きが残り，共通成分（カメラの LSC 残差）もゼロではない．
- ρ=0.81 純 diffuse にするとお椀の深さは実機と一致し（全灯 −8.3% vs −8.2%），SSIM は 0.92 → 0.97
  に上がるが，**傾きとピークのずれは変わらない**（むしろ拡散が増えてピークのずれが小さくなる）．

## 結果 3 — 壁の反射特性（ω・α）のスイープ (Wall BSDF Sweep)

`scripts/sweep_wall_bsdf_spot.py` フェーズ A．ρ ∈ {0.85, 0.81} × ω ∈ {0, 0.05, 0.15, 0.30, 0.50, 0.70}
× α ∈ {0.02, 0.05, 0.1, 0.3, 0.6}（ω=0 は純 diffuse）× 4 構成 = 208 レンダ（spp 2048）．
`output/wall_bsdf_spot/wall_bsdf_heatmap.png`・`shape_fit_a.csv`．

| ρ=0.85・α=0.1 | ω=0 | 0.05 | 0.15 | 0.30 | 0.50 |
| --- | --- | --- | --- | --- | --- |
| 左単灯 ピーク x（実機 +0.65） | +0.22 | +0.30 | **+0.61** | +0.72 | +0.80 |
| 右単灯 ピーク x（実機 −1.00） | −0.19 | −0.24 | −0.62 | −0.75 | −0.85 |
| 全灯 お椀（実機 −8.2%） | −7.1% | −6.4% | −5.2% | −3.6% | −2.0% |
| 全灯 傾き（実機 9.6%） | 4.2% | 4.0% | 3.4% | 1.9% | 2.3% |
| 4 構成の差分 RMS 平均 | 0.039 | 0.036 | 0.038 | 0.049 | 0.073 |

- ω を上げると単灯のピークは実機の方向へ大きくずれ，ω=0.15 で実機に届く．**しかし同時にお椀と
  傾きが消えて形全体は崩れる**（差分 RMS は ω=0.30 で 0.049，0.50 で 0.073）．
- α は ω ≥ 0.3 でのみ効く（小さい α ＝鏡面に近いほどピークが端まで飛ぶ）．採用域 ω ≤ 0.15 では
  ほぼ無関係．
- 4 構成の差分 RMS 平均の最良は ρ=0.81・ω=0.05・α=0.1（0.0336）．採用材質は 0.0364 で 7 位．
  ピークの折り合いも含めた最良は ρ=0.81〜0.85・ω=0.15・α=0.1（ピーク誤差 0.30，RMS 0.036〜0.038）．
  差はいずれも小さく，**ω・α では「ピークのずれ」と「お椀・傾き」を同時には合わせられない**．

## 結果 4 — LED 配光（spot）のスイープ (LED Beam Pattern Sweep)

同スクリプト フェーズ B．採用材質のまま LED を Mitsuba の `spot`（面光源と同じ位置・向き・全光束）
にし，半値全幅 FWHM ∈ {30, 45, 60, 90, 120}°（cutoff = 2/3 FWHM，beam = 1/3 FWHM）× 4 構成
= 20 レンダ（spp 4096）．`output/wall_bsdf_spot/spot_fwhm.png`・`shape_fit_b.csv`．

| FWHM | 30° | 45° | 60° | 90° | 120° | 面光源（ランバート） |
| --- | --- | --- | --- | --- | --- | --- |
| 左単灯 ピーク x（実機 +0.65） | **+0.68** | +0.60 | +0.51 | +0.38 | +0.29 | +0.30 |
| 右単灯 ピーク x（実機 −1.00） | −0.72 | −0.64 | −0.52 | −0.41 | −0.34 | −0.24 |
| 右単灯 傾き（実機 6.6%） | 8.3% | 7.4% | 6.2% | 5.0% | 4.7% | 4.8% |
| 左単灯 傾き（実機 11.9%） | 8.2% | 7.4% | 6.6% | 5.6% | 5.3% | 5.3% |
| 4 構成の差分 RMS 平均 | 0.035 | **0.034** | **0.034** | 0.036 | 0.037 | 0.036 |

- FWHM を狭めると単灯のピークが実機に近づき，30° で左は実機に一致．傾きも実機側へ寄る．
- ただし FWHM を狭めすぎると全灯・左単灯のピーク y（上下）が実機から離れる．
  **FWHM 45〜60° が全体のバランス点**（差分 RMS 平均 0.034 で面光源の 0.036 より良い）．
- 右単灯の差分 RMS は 90° で 0.022 と最良で，面光源と同等．

## 結論 (Conclusions)

- 実機との一致は「同心円方向（お椀）」「方位方向（ピークのずれ・傾き）」に分けて見る必要がある．
  材質（ρ）が決めるのは前者だけで，TEST_14 の ρ≈0.81 は妥当．
- 単灯の明部が反対側へ寄る量は，壁の光沢では形全体を崩さずに再現できず，**LED の配光を
  ランバートより狭くする（spot FWHM 45〜60°）** ことで説明できる．新しい基準候補は
  「採用材質（ρ=0.85・ω=0.05・α=0.1）+ spot FWHM 45〜60°」．
- 全構成に共通する「左上が暗い」傾き（実機 8〜12%）はどの設定でも半分しか出ない．下・左の
  基板で大きく右で小さいので，基板の位置・向き（または基板ごとの出力差）が第一候補．
- シミュの min（画像全体）は実機より 0.05〜0.07 高く出る．基準 0.9 の合否をシミュ単独で断定する
  には，この傾き成分を詰めるか，余裕を持った判定基準（例: シミュで 0.95 以上）にする必要がある．

## 限界・注意点 (Limitations)

- 実機は各構成 1 枚（全灯は 2026-06-01，単灯は 2026-06-15 の別セッション）．実機側のノイズ
  フロアは撮り直しが無く測れていない（ノイズ CoV は 0.8% で小さい）．
- ISO の min の定義（画像全体か輪帯平均か）は未確認．本実験は画像全体を主，輪帯平均を参考にした．
- spot は点光源で，面光源の 2.8×3.5 mm の広がりは無い．FWHM の cutoff/beam の分け方（2:1）は
  仮置きで，データシートの配光曲線には合わせていない．
- 傾きの共通成分が LSC 残差か幾何かは未切り分け．
- 壁スイープは spp 2048（ノイズ CoV 約 7%）．ピーク位置は σ=20 の平滑化後なので影響は小さいが，
  差分 RMS の 0.002 程度の差は有意ではない．

## 失敗パターン・方法論の学び (Pitfalls and Methodology)

- **集約指標（min）だけで材質を選ぶと誤る**．ρ を下げれば min は実機に寄るが，それは
  お椀を深くして帳尻を合わせているだけで放射プロファイルは崩れる．形（全灯 + 単灯 3 灯）で
  見ることで「材質で合わせられる成分」と「光源・幾何で合わせる成分」を分離できた．
- **単灯 3 灯は方位方向の診断に必須**．全灯だけでは 3 基板の寄与が混ざって傾きの原因を
  切り分けられない．
- サーバの push は `--only scripts` だけだと新しい src モジュールが無くて落ちる（TEST_19 と同じ）．
  `configs/_tmp_*` は push 対象外なので，スイープ用 YAML はサーバ上で生成する設計にした．

## 次にやること (Next Steps)

1. 「採用材質 + spot FWHM 45〜60°」で下・左基板の向き（数度）と位置を振り，共通の傾きが
   埋まるかを見る．
2. LED データシートの配光曲線で spot の cutoff/beam を決め直す．
3. 傾きの共通成分の切り分け: 実機で白板を 180° 回転して撮る（傾きが回れば筐体，回らなければ
   カメラ側）．
4. 単灯の実機データを全灯と同一セッションで撮り直し，絶対振幅も横並びにする．

## 再現コマンド (Reproduction)

```bash
# 全灯: min・放射プロファイル・形（ρ=0.81 は事前にサーバでレンダ）
uv run python scripts/compare_real_vs_sim_metrics.py --sim output/real_vs_sim/sim_rho081_spp4096/luminance.npy \
    --label "ρ=0.81 純 diffuse・spp4096" --tag rho081
# 形の一致（全灯 + 単灯 3 灯）
uv run python scripts/compare_real_vs_sim_shapes.py --sim-set legacy
uv run python scripts/compare_real_vs_sim_shapes.py --sim-set rho081
# 壁反射特性・spot スイープ（サーバ．YAML はサーバ上で生成）
uv run sm-remote push --only scripts
uv run sm-remote run --name wall --gpu 0 --threads 16 -- python scripts/sweep_wall_bsdf_spot.py --phase all --workers 2
uv run sm-remote pull wall_bsdf_spot
uv run python scripts/build_shape_fit_comparison.py
```

出力: `output/real_vs_sim/`（`real_vs_sim_*.png/csv`・`shapes_*.png/csv`・`bsdf_grid_vs_real.csv`・
ρ=0.81 のレンダ 4 本），`output/wall_bsdf_spot/`（228 レンダ + `shape_fit_a.csv` / `shape_fit_b.csv` +
`wall_bsdf_heatmap.png` / `spot_fwhm.png`）．

## 参照 (References)

- [TEST_14_材質パラメータ再スイープと残差の構造分解](TEST_14_材質パラメータ再スイープと残差の構造分解.md): ρ の確定と傾き成分
- [TEST_18_照明配置依存性の球と立方体の比較](TEST_18_照明配置依存性の球と立方体の比較.md): 画像全体 min/max 比の導入
- [SPEC_04_評価仕様](../04_SPEC/SPEC_04_評価仕様.md): 指標の定義
- [TEST_02_シミュレーション実行記録](TEST_02_シミュレーション実行記録.md): 出力ディレクトリの索引
