diff --git a/CLAUDE.md b/CLAUDE.md index eecb0a2..f13ee19 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,8 +6,8 @@ ## 開発進捗 現在の進捗: フェーズ 7(実装)— Step 1〜7 完了,Step 8(基準設計キャリブレーション)進行中. -Step 8 進捗: spp 校正完了(128→1024、ノイズ vs 物理差を切り分け済み).CoV 残差 4 倍の主因は ISP レンズシェーディング補正によるスケール差(構造的、spp 非依存)と判明.[SPEC_03「キャリブレーション経過」参照](docs/04_SPEC/SPEC_03_基準設計の物理構成.md). -次のアクション: レンズシェーディング補正の後処理適用、または筐体内壁反射率スイープ(0.85±0.05)で勾配・CoV を実測に近づける. +Step 8 進捗: spp 校正(128→1024、ノイズ/物理差を切り分け)→ 反射率スイープ(0.75〜0.92、弱い二次レバーと判明)→ **手法訂正**: シミュ linear と実測 sRGB を直接突合していた交絡を発見.標準 sRGB OETF 順方向適用+実測 mean アンカーで見かけ差の **約 2/3 が符号化ドメイン不一致**だったと判明.寄与順は OETF(最大)> ISP レンズシェーディング(残差主因候補)> 反射率(小).残差 1.6〜1.9 倍は調整せず正直に保持.副次: max_depth=8 は勾配を過大評価(キャリブは depth≥12).[SPEC_03「キャリブレーション経過」参照](docs/04_SPEC/SPEC_03_基準設計の物理構成.md). +次のアクション: ① OETF 順方向適用を sm-evaluate へ正規実装(`/implement`、現状 throwaway スクリプト).② 残差に LSC 順方向モデル(物理動機づけ低自由度形)を当てる. 実装済みモジュール: - `src/sm_tias_lightsim/uniformity.py` — Rec.709 輝度変換 + CoV/std/max-min(MiniTias-Evaluation コピー) diff --git "a/docs/04_SPEC/SPEC_03_\345\237\272\346\272\226\350\250\255\350\250\210\343\201\256\347\211\251\347\220\206\346\247\213\346\210\220.md" "b/docs/04_SPEC/SPEC_03_\345\237\272\346\272\226\350\250\255\350\250\210\343\201\256\347\211\251\347\220\206\346\247\213\346\210\220.md" index 8ea516e..d1a1691 100644 --- "a/docs/04_SPEC/SPEC_03_\345\237\272\346\272\226\350\250\255\350\250\210\343\201\256\347\211\251\347\220\206\346\247\213\346\210\220.md" +++ "b/docs/04_SPEC/SPEC_03_\345\237\272\346\272\226\350\250\255\350\250\210\343\201\256\347\211\251\347\220\206\346\247\213\346\210\220.md" @@ -87,7 +87,7 @@ | 項目 | 値 | 意味 | | --- | --- | --- | | `integrator` | `path` | **多重反射を考慮した** path tracing.LED → 内壁 → 評価板 のような間接照明経路もすべて積分する | -| `max_depth` | 8 | ray の最大反射回数.8 回までの反射を追跡(実用上 MiniTIAS の白筐体内多重反射には十分) | +| `max_depth` | 8 | ray の最大反射回数.**キャリブで判明: 8 はキャリブ精度には不足**(depth=12 比で勾配を約 +2.6pt 過大評価.下記「キャリブレーション経過」参照).確定 YAML は現状 8 のまま(既知の差分 #6).キャリブ用途は depth≥12 推奨 | | `spp` | 1024 | pixel あたりサンプル数.大きいほどノイズ減・計算重.**spp 校正済み**(下記「キャリブレーション経過」参照).llvm_ad_rgb・512×512 で 1 レンダ約 9.6 分 | | `variant` | `llvm_ad_rgb` | LLVM JIT による RGB レンダリング.LLVM-C.dll が PATH(または DRJIT_LIBLLVM_PATH)で参照可能なこと | @@ -106,7 +106,7 @@ ### 制限 - 現状 Phase A のベイク([visualize/baker.py](../../src/sm_tias_lightsim/visualize/baker.py))は直接照度のみで多重反射を考慮しない.多重反射込みの照度マップを得るには本ドキュメント記載の path tracer(`sm-render`)を使う. -- `max_depth` を超える反射は無視される.白筐体(reflectance 0.85)で 8 回反射した光のエネルギーは初期の `0.85^8 ≈ 27%` まで減衰しているため、無視しても影響は小さい. +- `max_depth` を超える反射は無視される.エネルギー的には `0.85^8 ≈ 27%` 減衰で小さいが、**キャリブ実測では無視できない**:同一条件で depth=8→12 にすると勾配が linear 空間で 24.65→22.08(−2.6pt)、sRGB 空間で 12.57→11.16(−1.4pt)下がった.8 回打ち切りはまさに均一化に効く後段反射を取りこぼし、勾配を系統的に過大評価する.キャリブ用途では depth≥12 を使うこと. ## 筐体(材料) @@ -166,15 +166,71 @@ - **spp→∞(ノイズゼロ)でも CoV は ≈ 0.174 までしか下がらない**(実測 0.0426 の約 4 倍) - ⇒ spp をさらに上げても CoV は 0.183→0.174 程度で頭打ち.**spp 増加は費用対効果なし**.spp=1024 を基準設定として確定. -### 残差の主因(物理モデル差) +### 筐体内壁反射率スイープ(2026-05-18、spp=256・depth=12・raw float linear) -CoV 4 倍差・勾配 4 倍差の主因は **シミュの照度が周辺へ急峻に落ちる構造的空間勾配**.これは実機との物理差というより **比較スケールの差** が支配的: +`printer_white`(5 メッシュ共有)の reflectance を 5 点振った結果(linear 空間): -実測 PNG は実機 ISP の **レンズシェーディング補正(周辺減光の電子補正)込み**で、シミュは線形放射輝度(補正なし).実測データ提供側 README(`reference_measurement/.../README.md` 注意点)も明示: +| R | CoV | 勾配% | C/P | 備考 | +| --- | --- | --- | --- | --- | +| 0.75 | 0.2173 | 25.91 | 1.3498 | | +| 0.80 | 0.2034 | 24.00 | 1.3157 | | +| 0.85 | 0.1893 | 22.08 | 1.2833 | 現基準反射率 | +| 0.90 | 0.1753 | 20.15 | 1.2523 | | +| 0.92 | 0.1697 | 19.42 | 1.2410 | マット白プラ実用上限 | -> レンズシェーディング補正が ON だと周辺光量低下の一部は ISP が補正している.**「シミュの勾配が実測より大きい」ことが期待される**(このため 6% は補正後の残存ムラ). +全指標が反射率と単調・線形に改善するが感度は低い(∂勾配/∂R ≈ −38 %/単位, linear).実測到達には R≈1.2〜1.4 が必要で物理範囲外.**反射率は弱い二次レバーで、これ単独では差を閉じられない**. -今回の観測(シミュ勾配 24.7% ≫ 実測 6.1%)はこの予測と整合.次の改善はレンズシェーディング補正の後処理適用、または筐体内壁反射率スイープ(次セッション着手). +### 手法訂正:linear vs sRGB の直接比較は不成立(OETF 順方向適用が必須) + +**それまでの「シミュ linear 放射輝度 vs 実測 PNG」の数値突合は交絡していた.** CoV・勾配・中心/周辺比が「無次元だからスケール任意」で不変なのは **光量→画素値が線形のときだけ**.実測 PNG は実機 ISP の **sRGB ガンマ(OETF, IEC 61966-2-1)** が掛かった非線形符号化値(Camera2 `YUV_420_888` → BT.601 は定義上ガンマ済み R'G'B' 上の量)であり、シミュの linear とは別ドメイン.非線形変換下でこれら指標は不変でない. + +実測データ提供側 README も明示していた: + +> シミュ側を線形放射輝度のまま比較する場合、**勾配/CoV の絶対値は変わる**(実測は ISP 補正込み).…ガンマ補正解除しない.実測は ISP 適用後の sRGB 表示輝度で評価している. +> +> レンズシェーディング補正が ON だと周辺光量低下の一部は ISP が補正している.「シミュの勾配が実測より大きい」ことが期待される(このため 6% は補正後の残存ムラ). + +**訂正手順(overfitting なし)**:標準 sRGB OETF を順方向適用し、露出は AE が制御する量=実測 ROI mean (146.71) にアンカー(線形ゲインなので形状指標には自由度を持ち込まない;OETF が非線形なため「曲線上の動作点」を合わせる原理的アンカーとして必須).データに合わせて回す係数はゼロ.無彩色シーン(LED・材料が RGB 等価)のため luminance への直接 OETF 適用はチャネル別適用後 luma と厳密一致. + +OETF 適用後の比較(係数調整なし、uint8 量子化、clip 0%): + +| ソース | 空間 | CoV | 勾配% | C/P | +| --- | --- | --- | --- | --- | +| R0.85 (d8,spp1024 = 確定基準) | linear | 0.183 | 24.65 | 1.327 | +| 〃 | **sRGB** | **0.089** | **12.57** | **1.144** | +| R0.85 (d12,spp256) | sRGB | 0.091 | 11.16 | 1.126 | +| R0.92 (d12,spp256) | sRGB | 0.081 | 9.72 | 1.108 | +| **実測 TARGET** | **sRGB** | **0.0427** | **6.10** | **1.0650** | + +確定基準で勾配 24.65→12.57(実測との差 18.6→6.5、**約 65% が符号化ドメイン不一致だった**)、CoV 0.183→0.089(差の **約 67%**).標準変換だけで見かけの「物理差」の約 2/3 が消えた. + +### luma vs luminance と演算順序(実測式との整合) + +実測 (MiniTias-Evaluation) の「輝度値」は厳密には **Rec.709 luma Y'** = ガンマ済み成分への加重和 `Y' = 0.2126R' + 0.7152G' + 0.0722B'`(README どおりガンマを戻さない=luminance ではなく luma).一方シミュ側は linear luminance に直接 OETF を当てている.OETF は非線形なので一般に演算順序が効く(`Σwᵢ·f(xᵢ) ≠ f(Σwᵢ·xᵢ)`)が、**矛盾しない**: + +- Rec.709 重みは合計 1(0.2126+0.7152+0.0722 = 1.0000).**R=G=B=x の無彩色画素**では「チャネル別 OETF→加重和」`Σwᵢ·f(x)=f(x)` も「加重和→OETF」`f(x·Σwᵢ)=f(x)` も**厳密に一致**. +- シミュのシーンは白色 LED(RGB 等価 radiance)+無彩色拡散材で**厳密に R=G=B**.よって「luminance に直接 OETF」=「実測の演算順(チャネル別 OETF→Rec.709 加重和)」と同値. +- 本質: **OETF は不整合を作る操作でなく消す操作**.OETF 前のシミュ=linear 空間 luma、実測=gamma 空間 luma で別ドメイン(=真の不整合).OETF 後は両者とも gamma 空間 luma で同種量になり、突合が初めて正当化される. + +残る近似(いずれも二次、調整しないモデル誤差に含む): +1. 無彩色等価が厳密なのはシミュ側のみ.実測白板画像は LED 分光・ISP ホワイトバランス・センサ応答で微小に非グレー(R'≈G'≈B' が完全でない分の luma vs luminance 差). +2. カメラ実 OETF ≠ 厳密 sRGB(独自トーンマップ). + +**実装時(productionization)の方針**: sm-evaluate への正規実装では「linear RGB をチャネル別 OETF → その後 Rec.709 luma」の順(実測の演算順そのもの)にする.無彩色シミュでは数値同一だが、将来カラー LED・色付き材料を入れても破綻しない忠実実装になる.今回の `apply_oetf.py` は無彩色前提の同値ショートカット. + +### 寄与順の訂正と残差 + +以前の「主因は ISP レンズシェーディング(83%)」は OETF を抜かした交絡判断で**誤り**.正しい寄与順: + +> **OETF(最大・約 2/3)> ISP レンズシェーディング補正(中・残差の主因候補)> 筐体内壁反射率(小・弱いレバー)** + +OETF 適用後も最良点(R0.92,d12,sRGB)で勾配 9.72/CoV 0.081 と実測 6.10/0.043 の **1.6〜1.9 倍**が残る.この残差は **ISP レンズシェーディング補正+スマホ独自トーンマップ+モデル誤差**.LSC は周辺を持ち上げる動径ゲインで勾配・C/P を下げる方向=残差の符号と整合.**残差はガンマ曲線いじりで消さず正直に残す**(OETF は標準で固定、調整対象は LSC 側). + +### 次アクション + +1. **OETF 順方向適用を sm-evaluate(または評価設定)へ正規実装**(`/implement`).以降の全シミュ vs 実測比較は OETF 後ドメインで行う(現状は throwaway 解析スクリプト `output/sweep_reflectance/apply_oetf.py`). +2. その後、残差に対し **LSC 順方向モデル**を当てる.overfitting 回避のため自由多項式ではなく物理動機づけ低自由度形(cos⁴ ベース等)に限定し取得パラメータ数を明記する. +3. 反射率は均一性からは一意に定まらない(物理範囲内で縮退)ため暫定 0.85 据え置き.実フィラメント分光反射率データ入手時に再校正. ## 想定どおりの挙動(追加対応不要) @@ -192,8 +248,11 @@ 2. **左右 LED 基板の正確な位置・向き**: STL から推定した座標で、Fusion 360 設計とのズレがある可能性. 3. **LED 1 個あたりの実 W 値**: 現状 `radiance=2807.25`(実測 mean=146.7 にスケール校正済み).mean は一致するが、実機 SMD 2835 の規格値(~0.2 W)からの物理的整合性は未検証. 4. **スマホホルダの実素材**: 推定 `holder_dark` (0.50).実物確認が必要. -5. **【最大の差・主因】ISP レンズシェーディング補正によるスケール差**: 実測 PNG は実機 ISP の周辺減光電子補正込み、シミュは線形放射輝度(補正なし).このため **シミュ勾配 24.7% ≫ 実測 6.1%**(実測データ提供側も予測済み).CoV 4 倍差の主因.spp 由来ノイズではなく構造的(「キャリブレーション経過」参照).対策はレンズシェーディング補正の後処理適用. -6. ~~**評価 ROI の不一致**~~(**解消済み**): ROI を実機と物理対応させ(`configs/eval_baseline.yaml` = pixel (24,37,464,450))、`sm-evaluate` は実測 PNG に対し MiniTias-Evaluation と小数点 14 桁レベルで一致を確認済み.評価ロジック起因の差はない. +5. **【最大要因・手法訂正済み、正規実装は未】linear vs sRGB のドメイン不一致(OETF 欠落)**: シミュ linear と実測 gamma 空間 luma を直接突合していた交絡.見かけ差の **約 2/3** がこれ.標準 sRGB OETF 順方向適用+実測 mean アンカーで対処(「キャリブレーション経過」参照).現状は throwaway スクリプト止まりで、**sm-evaluate への正規実装(`/implement`)が未完**.※ 旧版でここを「主因は ISP レンズシェーディング」としていたのは OETF を抜かした誤り. +6. **【残差の主因候補・未対処】ISP レンズシェーディング補正**: 実測 PNG は実機 ISP の周辺減光電子補正込み、シミュは未補正.OETF 適用後も残る 1.6〜1.9 倍差の主因候補.LSC 順方向モデル(物理動機づけ低自由度形、overfitting 回避)で対処予定. +7. **【残差・不確実・未対処】スマホ独自トーンマップ**: ISP は sRGB OETF に加え独自トーンマッピング/コントラストを掛けうる.真のトーンカーブ未知.残差の一部.調整で消さず正直に残す方針. +8. **【未対処】max_depth=8 が勾配を過大評価**: depth=8→12 で勾配 linear 24.65→22.08(−2.6pt)/ sRGB 12.57→11.16(−1.4pt).確定 YAML は現状 8 のまま(レンダコスト優先で変更保留).キャリブ用途は depth≥12 を使うこと. +9. ~~**評価 ROI の不一致**~~(**解消済み**): ROI を実機と物理対応させ(`configs/eval_baseline.yaml` = pixel (24,37,464,450))、`sm-evaluate` は実測 PNG に対し MiniTias-Evaluation と小数点 14 桁レベルで一致を確認済み.評価ロジック起因の差はない. ## 参照(References)