fullseye

仮想マシンビジョン — パラメータの洗い出しとオブジェクト模型

観察光学系を物理空間に組んで画像を生成するために、何を与えれば像が決まるかを 洗い出した台帳。ここが曖昧なまま実装を足すと、見た目だけ合っていて実機と対応しない 生成器になる(2026-09-05 のユーザー指示「センサーのパラメータ、レンズのパラメータ、 光源のパラメータ、レイアウトのパラメータを洗い出してから進めてください。自ずとそれらが オブジェクトになると思います」)。

0. 一次情報(この台帳の根拠)

出典 そこから採った事実
SYNOSIS, arXiv:2410.14844(金属表面検査の画像合成) 粗い金属 BRDF(roughness 0.05–0.3)/表面地形は焦点変化顕微鏡の実測(横 0.44–1.75 µm・縦 410 nm)を法線マップ化(13107²・6.1 µm 間隔)/切削面は手続きモデル(工具回転リング・経路・余弦・振動ノイズ、リング径 4–8 mm・中心間 0.09 mm)/サンドブラストは ADSN + Efros–Freeman/欠陥は 3-D 形状をブーリアン差、マスクは 0.9–1.0 倍の工具形状との交差/path tracing 256 spp・8 bounce・1224×1025/トーラス型リングライト
Adimec / Vision Doctor(明視野 対 暗視野) 傷は明視野で暗く、暗視野で明るく写る(コントラストが反転する)。暗視野の入射角は 10–15° が定石
automatica Munich “Virtualising Machine Vision” 光学デジタルツイン × PBR × 欠陥モデル × 画素精度の自動アノテーション

RAD コーパスにはマシンビジョン光学の分野が無い(最も近いのは halcon_operators_corpus_v2fullseye_3d_vision_corpus_v2)。本ファイルがその穴を 埋める知識層で、以後の実装はここを起点にする。


1. センサー(Sensor)

パラメータ 記号・単位 像への効き方 fullseye の現状
画素ピッチ p [µm] 標本化限界 2p。回折限界とどちらが大きいかで律速が決まる optical_camera(pixel_um=)
解像度 W×H [px] 視野 = W·p·WD/f
量子効率 QE(λ) [-] 電子数 = 光子数 × QE。波長で変わる sensor_spec(quantum_efficiency=) ✓(定数)/QE(λ) の曲線は未実装
フルウェル FW [e⁻] 飽和。白飛びは折り返さない sensor_capture(full_well_e=)
読み出し雑音 σ_r [e⁻] 暗部の下限。暗視野で効く
ダーク電流 [e⁻/s] 長露光で効く。暗視野は露光が長い sensor_spec(dark_e_per_s=) ✓(layout_capture が露光時間と合成)/温度依存は未実装
ADC ビット深度 [bit] 量子化。8 bit だと微小コントラストが刻まれて消える
ゲイン [e⁻/DN] ショット雑音との比
シャッタ方式 rolling / global 動体の歪み。コンベア上の部品で効く sensor_spec(shutter=)記録のみ。ローリングの歪みは未実装
分光感度 S(λ) 光源スペクトルとの積で実効的な明るさが決まる 未実装

2. レンズ(Lens)

パラメータ 記号・単位 像への効き方 fullseye の現状
焦点距離 f [mm] 倍率 m = f/(WD−f)、視野
F 値 / NA N, NA = 1/(2N) 回折・被写界深度・明るさ。作動 F 値 N_w = (1+|m|)·N optical_budget(f_number=/na=)
作動距離 WD [mm] 倍率・レイアウト・照明の置き場所
許容錯乱円 c [µm] 被写界深度 DOF ≈ 2·N_w·c/m²(幾何)+ 2λN_w²/m²(波動)
エアリー半径 1.22·λ·N_w [µm] 微細欠陥の見え方の下限。画素と比べる airy_radius_um ✓ / optics.airy_pattern
MTF MTF(ν) コントラスト伝達。欠陥は高周波なのでここが効く optics.mtf_diffraction / psf_to_mtf
収差 Seidel / Zernike 視野端でぼける・非対称になる raytrace.seidel_coefficients / opd_map ✓(未配線)
歪曲 k1, k2 … 寸法測定に直接効く lensimage.distortion_map ✓(未配線)
周辺光量 cos⁴θ ほか 端が暗い=端の欠陥が見えない optics.relative_illumination ✓(未配線)
テレセントリック性 物側/両側 倍率が距離で変わらない=寸法測定の前提 未実装
色収差 Δf(λ) 波長ごとにピント位置が違う raytrace.chromatic_shift ✓(未配線)

3. 光源(Light)

パラメータ 単位 像への効き方 fullseye の現状
種別 LED / ハロゲン / レーザー スペクトル幅とコヒーレンスが違う light_spec(source=) ✓(LED 狭帯域 / ハロゲン広帯域 / レーザー単波長)。コヒーレンスは未実装
スペクトル S(λ) 材質の反射率が波長依存(金は短波長で落ちる)。粗さの鏡面割合 exp(−(4πσcosθ/λ)²) も波長依存 render_optscene(wavelength_nm=) 単波長 ✓/広帯域は layout_capture(spectral_samples=) で重ね合わせ ✓
コヒーレンス 空間・時間 レーザーはスペックル。ハロゲンは出ない 未実装optics.gaussian_beam / angular_spectrum_propagate が土台)
放射強度分布 I(θ) = I₀cosⁿθ 均一性。端の照度落ち light_source(cos_exponent=)
器具の実体寸法 [mm] 鏡像として写るかどうか=明視野/暗視野の本体 light["size_mm"] ✓(2026-09-05 追加)
偏光 直線/円 映り込み除去。Jones/Mueller optics.jones_* / mueller_* ✓(未配線)
パルス/連続 [µs] 動体ブレの抑制 未実装

4. レイアウト(Layout)

パラメータ 単位 像への効き方 fullseye の現状
照明の仰角 [deg] 明視野(器具が鏡像に入る)/ 暗視野(入らない、10–15°)の分かれ目 light_source(height_mm, radius_mm)
照明の方位 [deg] 傷の向きとの関係でコントラストが変わる
照明の形 同軸/リング/ドーム/バー/バックライト 何が鏡像に入るか
カメラの傾き [deg] 平面を真上から見ると反射方向が天頂に集中し、加工目が出ない(実測) optical_camera(tilt_deg=)
作動距離 [mm] 倍率・照明の置き場所・被写界深度
視野 [mm] 部品が収まるか camera["fov_mm"]
部品の姿勢ばらつき [mm], [deg] ドメインランダム化の主軸 inspection_dataset(jitter_mm=, tilt_jitter_deg=)
背景・治具 誤検出の主因 scene_plane / scene_box / CSG のみ(CAD メッシュ未対応)

5. オブジェクト模型(実装済み)

洗い出すと、パラメータは 4 つの塊に自然に分かれる。塊ごとに 1 オブジェクトにして、 レイアウトが残り 3 つを束ねる形にする。

sensor_spec / lens_spec / light_spec / vision_layout / layout_capture

Layout ─┬─ Sensor  (画素・雑音・飽和・分光感度)
        ├─ Lens    (f, NA/F, WD, 収差, 歪曲, MTF)
        ├─ Light[] (スペクトル, コヒーレンス, 配光, 実体寸法, 姿勢)
        └─ Scene   (部品 + 材質 + 仕上げ + 欠陥)   ← 既存の scene_* op

導出量(倍率・作動 F 値・エアリー半径・被写界深度・視野・分解限界)は optical_budget閉じた式で返す。撮る前にここを見て構成の可否を判断する のが、この層を持つ目的。

6. PoC の順序(基本形から)

  1. 基本形: アルミ + ヘアライン + 同軸照明 + 単波長。observe_surface で 1 行。 合否は「明視野で傷が暗く写る」こと(教科書と符号が合う)。
  2. 暗視野を足し、コントラストの反転が出ることを確認 ✓(§7 参照。欠陥の粗さが鍵)。
  3. 波長を振り、粗さと波長の関係 exp(−(4πσcosθ/λ)²) が効くことを確認。
  4. 広帯域(ハロゲン)=複数波長の重ね合わせ、LED=狭帯域、レーザー=単波長 + スペックルへ拡張。
  5. 収差・歪曲・周辺光量は lensimage.render_through_lens を後段に掛けて合流。

7. 解決したこと / 残る未達(2026-09-05 時点)

解決: 明視野 / 暗視野のコントラスト反転

鏡面だけのモデルでは暗視野は原理的に成立しない。低角 12° の照明を真上のカメラへ 返すには面法線が (90−12)/2 = 39° 傾く必要があり、傷の傾斜(5–15°)では届かない。 実際の暗視野が光るのは、傷が材料を削り取った跡で局所的に粗く、散乱で返すから。

欠陥に roughness_um を持たせ、粗さ 1 つで 「鏡面割合 exp(−(4πσcosθ/λ)²) が下がる → 明視野で暗い」と 「散乱ローブが広がる(RMS 傾き √2σ/T)→ 暗視野で明るい」を同時に起こす。 実測 粗さ 0.4 µm で 明視野 −59% / 暗視野 +91%

線引き: 厳密な散乱計算ではなく「鏡面割合 × 表面テクスチャの粒度」による擬似生成。 反転が出るのは欠陥の粗さ 0.2–0.6 µm。それより粗いと散乱が広がりすぎて暗視野でも 周囲より暗くなる。表現の分担は「解像できる凹凸 = 法線、解像できない凹凸 = 粗さ」で、 surface_finish の加工目は前者を数オクターブの雑音に圧縮した表現にあたる。

解決: ラインスキャン / TDI

linescan_capture で搬送しながら積む。縦横比 =(速度/ラインレート)/(画素ピッチ·WD/f) が 1 からずれると画像が歪む(光学では直せない、ラインスキャン固有の故障モード)。 TDI は電荷が被写体と一緒に送られるので完全同期なら全段が同じ物点を見る (明るくなるだけ)。同期誤差のぶんだけスメアする。

解決: 伝送帯域

interface_budget が CXP / Camera Link / CLHS / GigE / Opt-C:Link の帯域から 帯域律速のレートを返す。16k・8bit を CXP-12 ×4 で 324 kHz ―― Vieworks VT の 公称 300 kHz と整合する。エリアスキャンでは逆に帯域が余る(IMX541 は 262 fps 可能で センサが 18–42 fps)。律速がどちらかは構成で入れ替わる

残る未達