33  レーザー三角測量

構造化光(structured light、チャプター 32)は物体全体に符号化されたテクスチャを投影し、1回の露光で全視野の高さを取得する。レーザー三角測量(laser triangulation)は別のアプローチをとる:1本のレーザーラインのみを投影し、1回の露光では物体がこのラインで切断された1つのプロファイル(断面)のみを測定する。得られる情報ははるかに少ないように見えるが、物体またはカメラの等速運動と組み合わせ、走査方向にプロファイルを順に積み重ねることで、同様に物体全体の3次元形状を再構成できる。しかも単一ラインの方式は光エネルギーが集中し、抽出が単純で、動作が極めて高速であるため、工業用オンライン3次元検査の主力となっている。リチウム電極のバリ高さ測定、溶接ビードの余盛とアンダーカット、レールのプロファイル摩耗などの背後には、生産ライン上でキロヘルツ級のプロファイルレートで走査するレーザープロファイラが多く存在する。本章では合成された「プロファイルターゲット」のシーンをすべての実験で用いる(図 33.1)。平らなベルトコンベア上に三角柱と円弧状の凸部が置かれ、ラインレーザーが上方から斜めに照射され、カメラは別の角度から物体によって持ち上げられ、曲げられた輝線を俯瞰する。

図 33.1: ラインレーザーカメラの視野像(\(640\times480\)、反転表示前の生の輝線)。平らなベルトコンベアは水平な基線を与え、三角柱はレーザーラインを鋭い頂点に折り曲げ(頂上の短い区間は鏡面反射により過露光となり、台形状に切り取られている)、円弧状の凸部はラインを滑らかな弓形に曲げる。三角柱の右下の斜面は自身の頂稜によってレーザーが遮られ、輝線のない影の隙間が残っている。

33.1 三角測量の原理

レーザーが射出するのは1本の光線ではなく、シリンドリカルレンズによって広げられた1枚のレーザー平面(laser plane)であり、被測定表面と交差して空間曲線を形成する。カメラはレーザー平面と一定の角度をなす方向からこのラインを観測する。表面上のある点が高くなると、交点はレーザー平面に沿って移動し、カメラの像面上ではその列におけるレーザーラインの行方向の変位として現れる。高さと変位の間には1対1の幾何学的関係がある——これがまさに「三角測量」の名前の由来である:レーザー平面、カメラの光軸、被測定点が三角形を構成し、基線(カメラとレーザーの相対姿勢)と観測角が既知であれば、3番目の頂点の奥行きを解くことができる。

較正後、この幾何学的関係は単純な較正定数に圧縮される。本章の合成データでは、レーザー基線行 \(\text{BASEROW}=360\)(高さがゼロのコンベアベルトに対応するレーザーの行)とし、行の変位と高さが比例係数 \(k=0.8\ \text{px/mm}\) で比例するとする。このとき、ある列のレーザーラインが第 \(r\) 行に位置する場合、その列の高さは

\[ h = \frac{\text{BASEROW} - r}{k}. \]

実際のシステムの較正曲線はこれほど線形である必要はないが、形式は変わらない:レーザーラインの行位置を抽出することは、高さを測定することと等価である。したがって、レーザー三角測量の精度は、最終的に1つの事柄——各列のレーザーラインの中心をどれだけ正確に見つけられるか——に依存する。

斜めに照射されるレーザー平面はカメラの像面と平行ではないため、通常の焦点調整ではレーザーラインの短い区間だけが鮮明になり、両端はぼやける。シャインプフルーグの原理は、レンズ平面、像面、レーザー平面の3つを共通の線上で交わらせることで、レーザーライン全体を同時に被写界深度内に収める——これがプロファイラのレンズが一般的に傾けて取り付けられる理由である。

構造化光と比較すると、レーザー三角測量は「単一ライン vs 全視野」のトレードオフである:構造化光は1回の露光で全視野を測定できるが、複数の符号化パターンを投影し、位相をアンラップし、クロストークを防ぐ必要がある。レーザー三角測量は1フレームあたり1本のラインしか測定せず、走査によって面情報を得る代わりに、各ラインの信号対雑音比と抽出精度を極限まで高める。両者は能動三角測量(チャプター 30)に属し、「情報量」と「取得速度」を天秤の両端に置いているに過ぎない。

33.2 レーザーライン抽出

レーザーライン抽出(laser line extraction)は、列ごとに独立した1次元のサブピクセルピーク位置決め問題である:各列の濃淡プロファイルにおいて、レーザーラインはガウス分布に近い明るいピークであり、推定するのはこのピークのサブピクセル行座標である。これは チャプター 14 のエッジサブピクセル補間や、チャプター 20 のキャリパ定位と同じ思想である——高コストな2次元定位を一連の低コストな1次元推定に分解し、サブピクセル補間によってピクセル格子をはるかに超える精度を引き出す。主なアルゴリズムは2種類ある。

重心法(center of gravity, CoG) は、レーザーのピークを「質量分布」と見なし、その輝度重み付き重心を線の中心とする。第\(r\)行の輝度を\(I_r\)、背景推定値を\(b\)とし、ピーク付近のウィンドウ内で

\[ \hat r_{\text{CoG}} = \frac{\sum_r (I_r - b)\, r}{\sum_r (I_r - b)}. \]

と計算する。モデルの仮定が不要で計算量が極めて少ないため、工業用輪郭計の標準的な実装となっている。

ガウスフィッティング(Gaussian fit) は、レーザー断面がガウスピーク\(I_r - b \approx a\,\exp[-(r-\mu)^2/2\sigma^2]\)であると仮定する。両辺の対数を取ると\(r\)に関する二次式となるため、\(\ln(I_r-b)\)\(\ln(I_r-b)=A+B(r-c_0)+C(r-c_0)^2\)として重み付き放物線フィッティングを行い、頂点からピーク位置を

\[ \hat r_{\text{fit}} = c_0 - \frac{B}{2C}. \]

と求める。フィッティングはモデル事前情報を一層追加するため、理論上はノイズに対してより頑健であるが、計算量の増加と「ピークが本当にガウス分布である」という仮定への依存が代償となる。

本章で合成したレーザー断面はガウス分布(\(\sigma=2\ \text{px}\)、ピーク値220、背景値30)であり、乗法的スペックルノイズが重畳されている——これは可干渉性のレーザーが粗面に照射された際に生じるランダムな干渉斑であり、その強度は信号自身に比例する。この点は後述のCoGとフィッティングの勝敗に決定的な影響を与える:乗法的ノイズはピーク頂点で最も強く、そこはフィッティングが最も重視する標本点なのである。

直感的にはガウスフィッティングが「より高度」であるように思えるが、実測結果は直感に反するものとなった。図 33.1 の正常区間(飽和も遮蔽もない列)で列ごとに真値と比較すると、CoGの平均\(|\text{误差}|=0.072\ \text{px}\)、ガウスフィッティングは\(0.111\ \text{px}\)となり、重心法の方がわずかに優れている。その理由はまさにスペックルの乗法的性質にある:フィッティングの対数変換は弱信号標本の重みを増幅し、かつピーク頂点付近の高輝度点を最も重視するが、そこは乗法的スペックルが最も激しい場所である。一方、CoGはウィンドウ全体で重み付き平均を取るため、ランダムな斑点が平均化されてむしろ安定する。これは誠実な詳細である:万人に通用する最適な抽出アルゴリズムは存在せず、ノイズの統計的構造に依存する。次節で見るように、フィッティングの真の価値はCoGが完全に機能しなくなったときに初めて明らかになる。

33.3 飽和:CoG のアキレス腱

工学的には「レーザーは明るいほど良い」と考えられがちである。これは明るさが高い信号対雑音比を意味するためである。しかし、階調値には上限が存在する:8 ビットセンサーでは 255 でクリッピング(頂部切断)が発生する。レーザーのピークが平坦に切断されると、災害が生じる。図 33.2 は 2 列の断面を比較している:通常の列は完全で対称なガウスピークであるのに対し、鏡面反射により過露光となった角柱頂部の列は、ピークの頂上が一直線に切断されて平坦な台地となっており、ピーク形状が持つ対称性の情報が失われている。

図 33.2: 2 列のレーザー断面の比較(横軸は 8 倍に拡大した行座標、縦軸は階調値)。青は通常区間の完全なガウスピーク;赤は角柱頂部の飽和列で、頂上が 255 の台地に切断され、対称なピーク先端の情報が失われている。

CoG は切断されたプロファイル上で系統的に偏倚する。CoG は最大画素を中心にウィンドウを設定して重み付き平均を求めるが、台地により「最大画素」が並んだ最高点の連続区間に縮退するため、重心が台地の片側に引き寄せられ、抽出された線全体が下方に引っ張られる。列ごとの統計は衝撃的である:飽和区間 49 列において、CoG の平均 \(|\text{误差}|=0.387\ \text{px}\)、偏倚 \(-0.387\ \text{px}\) であり、通常区間の \(5.4\) 倍、かつ完全に一方向の偏倚(ランダムな揺らぎではなく、系統的な低値化)である。高さに換算すると、角柱頂部の CoG 推定値は真値に対して\(+0.585\ \text{mm}\) 過大推定される。一方、ガウスフィッティングはフィッティング時に\(I\ge250\) の切断サンプルを除外し、台地の両側にある飽和していない「ガウスの肩部」のみを用いてピーク位置を逆算するため、飽和区間の平均 \(|\text{误差}|\)\(0.078\ \text{px}\)、偏倚はわずか \(+0.005\ \text{px}\) に低下し、角柱頂部の高さ誤差は \(-0.046\ \text{mm}\) となる。図 33.3 はこの逆転を明確に示している:飽和帯(黄)内で、CoG(赤)は全体的に負の誤差領域に落ち込むのに対し、フィッティング(青)は常にゼロ誤差線に張り付いている。

図 33.3: 列ごとの抽出誤差(赤:CoG、青:ガウスフィッティング;黄帯は飽和区間、灰帯はオクルージョンによる欠落)。通常区間では両者ともゼロ誤差線に近接し、CoG の方が雑音がやや小さい;飽和帯に入ると CoG は明確な一方向の負の偏倚(レーザー線が下方に引っ張られる)を生じるのに対し、フィッティングはほとんど影響を受けない。

ここに、正直に報告しなければならない逆転現象がある。前節の通常区間では CoG(0.072)がフィッティング(0.111)よりわずかに優れていた;フィッティングが勝つのは、クリッピングが CoG を壊す場合に限られる。言い換えれば、フィッティングは「より高精度なアルゴリズム」ではなく、「飽和に対してより頑健なアルゴリズム」である。教訓は 2 層にわたる:第一に、露光の最優先の赤線はレーザーピークを決して飽和させないことである——過露光は高い信号対雑音比をもたらすのではなく、事後的に修復不可能な系統的偏倚をもたらす;第二に、プロファイルが飽和する可能性がある場合、CoG は沈黙のうちに高さを過大推定するため、鏡面、光沢塗装など反射しやすい表面に対しては、切断サンプルを除外できるフィッティングに切り替えるか、飽和列を個別に標識化する必要がある。

33.4 スキャンと距離画像

抽出したレーザー線の行位置を列ごとに \(h=(\text{BASEROW}-r)/k\) に代入することで、1 フレームの画像を 1 本の高さプロファイルに還元できる。図 33.4 はこの再構成プロファイル(黒点)を真値(灰線)に重ねたものである:三角柱は尖った頂点を持つ三角形、円弧状の凸部は弓形であり、両者とも真値に精密に張り付いている;一方、頂稜に遮蔽された区間では、再構成プロファイルはそのまま空白となっている——レーザーがなければデータは存在せず、架空の曲線で欠落部をつなぐことは決してしない。

図 33.4: 単一フレームで再構成した高さプロファイル(黒点は抽出結果、灰線は真値;灰帯はオクルージョンによる欠落)。三角柱(真値 50 mm)と円弧状の凸部(真値 30 mm)の再構成プロファイルは真値に密接している;遮蔽区間は空白のままとし、補間で埋めていない。

1 本のプロファイルは 1 つのスライスに過ぎない。物体をベルトコンベアでレーザー平面を通して等速で移動させ、カメラを固定フレームレートで連続撮影し、各フレームから 1 本のプロファイルを抽出してスキャン方向(行)に順に積み重ねることで、距離画像(range image)が得られる——各画素の「階調値」は輝度ではなく、その位置の高さとなる。これは 2 次元画像と完全な 3 次元点群の中間に位置する 2.5D 表現である:規則的な画素格子を持つが、各格子に \(z\) 値が格納されている。図 33.5 は本章の 200 本のスキャンライン \(\times\) 640 列をつなぎ合わせた距離画像で、高さが高いほど明るくなる:角柱は傾斜を持つ明るい尾根として、円弧状の凸部は柔らかい明るい斑として表現されている。

図 33.5: スキャンでつなぎ合わせた距離画像(\(200\times640\)、階調値で高さを符号化)。三角柱は傾斜を持つ明るい領域で、その右側の純黒の縦帯は頂稜に遮蔽された影の欠落部(無効画素、補間で埋めていない);円弧状の凸部は右側の円形の明るい斑である。

角柱の右側にある純黒の縦帯に注目されたい:角柱の下り斜面は自身の頂稜に遮られ、レーザーが全く到達しないため、カメラには明るい線が見えない。このフレームでは 37 列でレーザーピークが検出されず、抽出アルゴリズムはこの 37 列すべてを忠実に無効と標識化し(\(37/37\))、距離画像には正直な空洞が残されており、補間で埋めることは決してしない。これは チャプター 26 の「沈黙の失敗」とは正反対である:真偽が判別できない高さをでっち上げるよりも、目に見える空洞を残す方が良い。遮蔽は物理的事実であり、でっち上げられた滑らかな曲面は、下流の処理で存在しない表面を誤判定する原因となる。距離画像全体で \(3700\) 個の無効画素が存在し、ピーク高さは \(50.268\ \text{mm}\) であり、すべて影の領域に集中している。2 本のプロファイルの測定結果も検証に耐える:角柱は \(49.954\ \text{mm}\)(真値 50)、円弧状の凸部は \(29.918\ \text{mm}\)(真値 30)と測定され、サブミリメートルレベルで一致している。

SciVision では距離画像を SciRangeImage で扱う:内部は ushort の生カウント値で、3 軸の解像度 resolutionX/Y/Z とオフセット offsetZ が付属する;GetValue生カウント値\(z\) スケーリング後の値ではない)を返すため、物理的な高さは自身で resolutionZ を乗じて offsetZ を加える必要がある;Save は高さの精度を維持するために 16 ビット PNG を出力する。本例では GetValue は角柱頂部で \(49.940\ \text{mm}\) を読み取る。これは SciPointCloudSciTriangleMesh と並び、Sci3DData のコア 3D データ型に属する。

距離画像は本書第 IX 部の点群処理への橋渡しとなる:各有効画素に物理座標 \((x,y)\) と高さ \(z\) を付与することで、距離画像は直接組織化された点群に展開され、以降の位置合わせ、セグメンテーション、計測は チャプター 37 で展開される。

33.5 再現性と露光

高さ計測システムの良否は、1 回の測定がどれだけ正確かだけでなく、より重要なのは同一箇所を繰り返し測定した際のばらつきである——これはまさに チャプター 20 で強調された再現性(repeatability)の方法論である。完全に平坦な領域から 100 列を選び、幾何形状を固定してランダムノイズのシードのみを変更し、50 回のレンダリングと抽出を繰り返し、各列の抽出位置の標準偏差を計算した後、全列で平均する。

レーザーの明るさ(露光)はここで両刃の剣となる。ピーク値 220(通常露光)の場合、CoG の標準偏差は \(0.091\ \text{px}\)\(0.114\ \text{mm}\) に相当)、フィッティングは \(0.139\ \text{px}\) である;レーザーをピーク値 100 まで暗くすると、CoG は \(0.112\ \text{px}\)\(0.140\ \text{mm}\))、フィッティングは \(0.163\ \text{px}\) に上昇する。傾向は明確である:レーザーが暗いほど信号対雑音比は低くなり、再現性は悪化する——露光不足はランダム誤差の原因である。しかし前節で述べたように、過露光(飽和)ははるかに恐ろしい系統的偏倚をもたらす。両側から挟まれるため、露光は妥協点を選ぶしかない:信号対雑音比が十分に確保できる明るさで、かついずれの列も飽和させないことである。実際には「最も明るい実在の表面がギリギリクリッピングしない」状態を目標に調整し、異常に反射する列には飽和フラグを残して兜底策とすることが多い。

33.6 SciVision 実装

SDK の不具合は忠実に記録しなければならない。本書の 3D レーザー三角測量モジュール SciSv3DLaserTriangle(v26.1)は、本機上ですべてのエントリポイントでアクセス違反(0xC0000005)によりクラッシュする。FindLaserLine(2 つのオーバーロード、すべてのパラメータの組み合わせ)、AnalysisLaserlineReconstructeImage の計 20/20 回がクラッシュし、ノイズのないクリーンな画像、8U か 16U か、いかなる ROI(デフォルトの UNDEF を含む)を入力しても結果は変わらない。1 回のクラッシュでサンプル全体が停止する事態を防ぐため、プロジェクトでは SDK 呼び出しをサブプロセスプローブに隔離している。メインプロセスが system("demo.exe sdkprobe") を呼び出してサブプロセスを起動し、SDK を操作させる。クラッシュが発生してもサブプロセスのみが異常終了し、メインプロセスによって捕捉・記録される。いずれかの SDK バージョンで不具合が修正されれば、比較結果は自動的に再現される。レーザーラインの抽出はすべて独自に実装した CoG とガウスフィットで行っている(これまでの数値はすべてこれによるものである)。

// サブプロセスプローブ:SDK エントリポイントを試行(本機では 20/20 回クラッシュ。SDK 修正後のベースラインとして保存)
SCIMV::SciSv3DLaserTriangle lt;
SciPointArray pts;  SciVarArray grays;
long rc = lt.FindLaserLine(img, roi, /*thresh*/60, /*width*/20, /*sigma*/3, &pts, &grays);
// rc!=0 の場合は失敗として記録;サブプロセスのクラッシュはメインプロセスの system() の戻り値で捕捉される

距離画像側の SciRangeImage の構築と保存は正常に動作するため、安心して使用できる:

// u16:各画素の高さの生カウント値(mm×100);解像度・オフセットは構築時に渡す
SciRangeImage ri(u16.data(), W, NSCAN, W * (int)sizeof(unsigned short), SCI_DATA_USHORT,
                 1.0, 5002.0, /*resZ*/0.01, /*offZ*/-0.01, /*resX*/XRES, 0.0, /*resY*/YSTEP, 0.0);
double v = ri.GetValue(100, 220);                 // 生カウント値。物理的な高さではない
double z = v * ri.ResolutionZ() + ri.OffsetZ();   // → 物理的な高さ(mm)
ri.Save("out\\range_image_sci.png");              // 16 ビット PNG。高さの精度が保持される

FindLaserLine の期待されるインターフェースをここに併記し、SDK 修正後の参考とする。入力としてレーザー画像と探索 ROI を与え、ピーク強度の閾値、レーザーラインの幅、平滑化 \(\sigma\) を指定すると、出力としてサブピクセル精度のレーザー点列 pts と対応する階調値 grays が得られる。本例の独自抽出処理は、まさにこのセマンティクスに従って列ごとの CoG/ガウスフィットを実装したものである。本章のすべての画像と数値を生成する完全なプロジェクトは code/laser_triangulation/ に格納されている。

産業事例:電池極片のバリ高さ判定

リチウム電池の極片をスリット加工した後、エッジに高さ数十 µm のバリが残ることが多い。バリが過度に高いとセパレータを突き破って内部短絡を引き起こす可能性があるため、オンラインでバリの高さを測定して不良品を除外する必要がある。ラインレーザープロファイロメータはキロヘルツ単位のプロファイルレートで極片のエッジを高速に走査し、µm レベルの高さ測定に十分対応できるはずである。しかし、極片の表面は鏡面状の金属箔とコーティングであるため、レーザーが照射されると強い反射が発生し、ピークが容易に飽和してしまう。ピークが頭切れになると、本章で明らかにした機構により CoG は高さを系統的に過大評価する。規格外でないエッジが誤って高い「バリ」として測定され、大量の誤排除(過剰廃棄)が発生する。対策は 3 つある。1 つ目はハードウェアで反射を抑制すること。レーザーパワーを下げ、偏光板を追加して正反射成分を抑え、レーザーピークを非飽和範囲に戻す。2 つ目は抽出アルゴリズムを CoG から、頭切れサンプルを除外するガウスフィットに変更すること。3 つ目は依然として飽和している列を個別にフラグ付けし、即時廃棄せずに再検査に回すこと。教訓は厳しいものである。µm レベルのレーザー高さ測定では、抽出アルゴリズムは露光制御やレンズと同様に重要である。どれほど高価なプロファイロメータでも、飽和によってバイアスが生じる抽出アルゴリズムと組み合わせれば、偽りの高さを測定することになる。

33.7 まとめ

  • レーザー三角測量は 1 本のラインと引き換えに極めて高い単プロファイル精度を実現し、走査によって全面をつなぎ合わせる:レーザー平面とカメラの三角形状により、高さがレーザーラインの行変位として符号化される(\(h=(\text{BASEROW}-r)/k\))。構造化光との比較では「単一ライン vs 全面、速度 vs 情報量」のトレードオフとなる。
  • 抽出精度がすべてを決定するが、万能なアルゴリズムは存在しない:乗算性スペックル下の正常区間では、重心法(CoG、0.072 px)がガウスフィット(0.111 px)をわずかに上回る。最適な抽出手法はノイズの統計的構造に依存するため、想定ではなく実測によって決定しなければならない。
  • 飽和は CoG の最大の弱点である:頭切れプロファイルは CoG に系統的なバイアスを生じさせる(飽和区間で \(-0.387\) px、高さは \(+0.585\) mm 過大評価され、正常区間の 5.4 倍となる)。一方、ガウスフィットでは頭切れサンプルを除外することで 0.078 px に低減される。露光における最優先の禁止事項は、レーザーピークを決して飽和させないことである。
  • オクルージョンには誠実な穴を残し、決して補間してはならない:距離画像内の 37 列のオクルージョン列はすべて無効としてフラグ付けされる。偽りの平滑面は可視の穴よりもはるかに危険であるため、偽りのデータを作るよりは空白のままにするほうがよい。
  • 露光は、低露出によるランダム誤差と過露出による系統的バイアスの間の妥協点である:ピーク値 220 の場合、CoG の再現性は 0.091 px であるが、100 に調光すると 0.112 px に上昇する。調整の目標は「最も高い実表面がかろうじて頭切れしない」状態にすることである。

サブピクセルレーザーライン抽出の理論的基礎は、Steger が提案した偏りのない曲線構造検出器である (Steger 1998)。これは幅の推定とともにサブピクセル精度の中心線位置を出力する。産業現場の反射とノイズに対応する高速かつロバストなレーザーストライプ抽出法は、Usamentiaga らの研究に記載されている (Usamentiaga, Molleda, と García 2012)。レーザー三角測量と 3 次元再構成に関するより体系的な解説は、Steger らの著書も参照されたい (Steger, Ulrich, と Wiedemann 2018)