3D reconstruction
面の向きから、
高さを組み立てる。
フォトメトリックステレオが出すのは、画素ごとの面の向きです。 それをつないで高さにする工程が 3D 再構成。当社は、勾配の場を 全体で一度に積分する方法を使っています。
なぜ「端から順に足す」のではだめなのか。積分で増える誤差はどこに溜まるのか。 このページは、その 2 つを読むのではなく触って確かめるためにあります。
◀ ドラッグして比べる ▶
同じ 1 回の撮像。左が面の向き、右がそれを積分して起伏にした製品の 3D Surface 出力。 このページでは、この硬貨の法線だけを使って最後まで追いかけます。
Experiment 01
端から足すと筋が出る。
全体で解くと、形になる。
下の立体は写真でも CG モデルでもありません。FORESIGHT STEREO が実測した表面法線 n から勾配 (p, q) を作り、ブラウザ上で積分して高さにし、 その高さをそのまま面として描いたものです。積分の方法を切り替えて、ドラッグで回してみてください。
積分した高さ(高さの単位は画素。ドラッグで視点が回ります)
積分の方法
×2.0
35°
55°
勾配場の「閉じなさ」 —
入力は硬貨の表面法線マップ(512px に縮小)。計算は 256×256 に落とした勾配 p = −nx/nz・q = −ny/nz に対して行い、 全体で一度に解く側は、当社の実装と同じ考え方で計算しています。 立体は 128×128 の格子に高さを置き、勾配から計算した陰影で描いています。
経路積分で筋が出る理由。
実測した勾配の場は、厳密には「閉じて」いません。ある画素の右隣へ行ってから下へ行くのと、 下へ行ってから右へ行くのとで、足し上がる高さがわずかに違います(ノイズ、鏡面、影がその原因です)。 1 行ずつ足していくと、この小さな食い違いが行ごとに別々に溜まり、横方向の筋になります。 どの経路を選ぶかで答えが変わる── それが経路積分の限界です。
全体で一度に解くとは。
経路を選ぶ代わりに、「この勾配にいちばん近い、閉じた勾配を持つ面」を全画素について一度に探します。 最小二乗の問題として一度に解くので、どこから足し始めるかという選択そのものが無くなります。 食い違いは特定の経路に押し付けられず、画面全体に薄く散らされます。
※ 当社はこの方法を GPU 上で実装しています(推論の前処理として、3D Surface 出力を作る工程)。
The equation
傾きを積んで、
高さにする。
面の向き n = (nx, ny, nz) が分かっていれば、 その画素の傾き(高さの変化率)は次で決まります。
求めたいのは、傾きがこの (p, q) にいちばん近くなる高さ z です。 当社は、これを画素ごとに順番に決めるのではなく、面全体についてまとめて解いています。
この解き方には、避けられない性質が 1 つあります。 誤差が長い波長に集まるということです。勾配のわずかな誤りは、細かい凹凸としてではなく 面全体のゆるやかなうねりとして現れます。次の体験②は、それを実際に測るためのものです。
当社の実装は、この解き方の前後に手当てを入れています(縁の扱い、全体の傾きの除去、 表示用の正規化など)。具体的な手順と定数は公開していません。
実測した勾配は「閉じて」いない。右へ行ってから下へ行くのと、下へ行ってから右へ行くのとで、 同じ画素に着いたはずの高さが違う。経路を選ばず、全体でいちばん近い面を探すのが当社のやり方です。
Experiment 02
誤差は、細部ではなく
うねりに溜まる。
法線にわざと一様な傾きとノイズを加えてから積分してみてください。 細かい凹凸はほとんど変わらないのに、長い波長のうねりだけが大きく動きます。 それを、当社の実装と同じ「平面を引く」「うねりを除く」で落としていきます。
上: 積分した高さの陰影 下: 中央の行の断面(細い線=乱していない結果、太い線=乱した結果)
0.0°
0.0°
24 px
乱していない結果とのずれ(RMS・画素) —
うち、うねり(長い波長) —
うち、細部(短い波長) —
傾きとノイズは模擬です(実測の法線を p, q に直したあと、一様な傾きは定数を足し、ノイズは画素ごとに正規乱数を足しています)。 「ずれ」は同じ後処理をかけた乱していない結果との差で、うねりと細部の分け目は右のスライダの波長です (当社の実装の既定値は元の解像度で σ = 30 px。ここは 256 px に落として計算しているので目盛りの意味が違います)。 高さの単位は画素で、実寸ではありません。
1° の傾きが、面全体の坂になる。
法線を一様に 1° 傾けると、勾配には tan 1° ≈ 0.017 が足されます。 1 画素では何も見えませんが、256 画素積もれば約 4 画素分の坂です。 上の式の分母がそれを増幅する── 誤差は距離とともに溜まり、低い周波数に集まる。 だから当社の実装は、積分のあとに必ず平面を引きます。
細部だけを残す、という選択。
「うねりを除く」を入れると、残るのはキズや刻印のような短い波長の起伏だけになります。 当社の 3D Surface 出力が、反った板でもキズだけを浮かび上がらせるのはこの理由です。 裏を返せば、板全体の反りや絶対的な高さはこの方法の得意ではないということでもあります (→ 苦手なこと)。
Four outputs
積分の前と後が、
そのまま製品の出力になる。
体験①②で触ったものは、FORESIGHT STEREO の出力として 1 回の撮像から同時に出ます。
積分の、入力。
式の n。ここから (p, q) を作る。
積分して、うねりを除いたもの。
体験②で「うねりを除く」を入れた状態に当たる。細部の起伏だけが残る。
高さを、面として回して見る。
体験①と同じこと。高さの倍率と視点を変えて、起伏を目で確かめる。
面に乗せる、素材の明るさ。
形とは別に持っているので、体験①の「面に乗せる」のようにあとから重ねられる。
※ 02 の画像は当社製品の出力そのもので、このページの計算結果ではありません。 作り方は上の「当社の実装が行っていること」の 09〜12 です。 ここでの対応づけは手順の説明であり、画素値が一致することを示すものではありません。
Strengths and limits
積分で得られる高さは、
何の高さか。
端から足す方法と、全体で一度に解く方法の違いは、体験①のとおりです。 どちらも「傾きから高さを組み立てる」方法である以上、共通の限界も持っています。
| 経路積分 | 全体で一度に解く | |
|---|---|---|
| 解き方 | 経路を 1 つ決めて、傾きを順に足す | 全画素をまとめて最小二乗で解く |
| 閉じていない勾配への応答 | 経路ごとに別々に溜まり、筋になる | 画面全体に薄く散らされる |
| 計算量 | 画素数に比例。ただし並列化しにくい | GPU で一括して解ける |
| 境界の扱い | 始点の選び方に依存 | 端の扱いに手当てが要る |
| 共通の限界 | 相対的な高さしか出ない/低い周波数(うねり・反り)に誤差が集まる/法線の誤りはそのまま高さの誤りになる | |
※ 方法どうしの一般的な比較であり、個別の製品の性能を示すものではありません。
苦手なことも、はっきりあります。
この方法は「傾きが正しく測れている」ことと、「傾きをつなげば面になる」ことの上に立っています。
積分で決まるのは高さの差です。定数(どこを 0 とするか)は決まらず、単位も画素の傾きから来る相対値です。 μm に直すには、画素の実寸と別の基準が要ります。
体験②のとおり、誤差は長い波長に集まります。板全体の反りや大きな形は、 三角測量のような別の方法の仕事です。当社の 3D Surface は、この成分をあえて除いて細部を残しています。
鏡面反射や影で法線が嘘をつくと、積分はその嘘をまじめに積み上げます。 積分は誤差を作らない代わりに、消すこともしません。手当ては法線を解く側で行います。
面全体をまとめて解く以上、画像の端をどう扱うかで結果が変わります。 当社の実装は端に偽の段差が立たないよう手当てを入れ、マスクの縁もなめらかにしてから渡しています。
だから当社は、3D 再構成を「寸法を測る道具」としてではなく、 反射に埋もれていた起伏を、人と AI の目に見える形にする道具として使っています。 キズの深さを μm で保証するのではなく、キズがそこにあることを形として立たせる── それがこの工程の役割です。
Where it sits
この工程は、どこにあるか。
3D 再構成はセンサ側の工程です。法線を解く工程(フォトメトリックステレオ)の直後にあり、 3D Surface 出力と Viewer の 3D 表示を作ります。
TR シリーズ
センサと判定を、現場で動く 1 台にまとめたもの。卓上の観察機 TR-55 には、この 3D 表示を回して見る Viewer が付く。
※ 単体ソフトウェアの AI SMART MASK は、この 3 層の外側にあります(「どこを見るか」を決める前処理で、良否判定はしません)。
Contact
あなたの対象物で、
起伏は立つか。
立つかどうかは、表面仕上げと、見たい欠陥の高さと波長で決まります。 画面の上で確かめられるのは、ここまでです。サンプルをお預かりして撮り、3D Surface と Viewer の 3D 表示をお返しするところからご相談ください。
