22  輝度、色、間隔の測定

すべての測定が幾何学に関連するわけではない。LED バックライト(透過照明)パネルがラインから出るとき、問われるのは「LED が所定の位置にあるか」ではなく「輝度が十分か、輝度は均一か」である。射出成形された筐体のロットでは、標準色板との色差が許容値を超えていないかを確認する必要がある。コネクタピンの列では、隣接する間隔が均一かどうかが関心事であり、いずれかの箇所が広すぎたり狭すぎたりすると、嵌合不良のリスクを意味する。これら3種類の問題はそれぞれ輝度測定(intensity measurement)色測定(color measurement)間隔測定(pitch measurement)の範疇に属する。対象は異なるが、骨格は完全に同一である:ROI 内で統計量を算出する → 公称値と比較する → 公差に基づいて良否判定する。本章では、実際に実施された3つの実験を通してこのパイプラインを順に説明する。図 22.1 は最初の実験の場面である:4つの LED スポットのうち1つが異常に暗いが、肉眼だけでどれがどの程度暗いかを確実に判断できるだろうか。

図 22.1: 輝度測定の場面:公称輝度が順に 220、180、220、100 の4つの LED スポットに、\(\sigma=4\) のガウシアンノイズを重畳した。2号の LED(左から3番目)は公称で 220 であるべきだが、実際にはわずか 140 しかない。1号の LED の正常値 180 との差はわずか 40 グレースケール値であり、目視では判断が難しい。

22.1 輝度測定

輝度測定の本質はROI 内のグレースケール値に対して統計量を算出することである。最も一般的に用いられる統計量はそれぞれ役割を持つ:平均値(mean)は「全体的に明るいか」を示し、輝度の良否判定の第一選択肢となる。標準偏差(standard deviation)は「内部が均一か」を示し、局所的な欠陥画素や汚れの検出に有用である。最小値・最大値・中央値(median)は分布の両端と中心を特徴づける。中央値は少数の外れ値画素に対して非感受性であり、表面に時折反射やほこりがある場合には平均値よりもロバストである。1回の測定呼び出しでこれらの統計量の組が同時に返されるので、必要に応じて使用すればよい。

実験場面は 図 22.1 の通りである:半径 30 px の4つの LED スポットの公称輝度は {220, 180, 220, 100} であり、そのうち2号の LED は暗灯欠陥を模擬するため実際には 140 でレンダリングされている。画像全体に \(\sigma=4\) のガウシアンノイズが付加されている。各 LED の中心に半径 24 px の円形 ROI を配置する。これは LED スポットよりも意図的に一回り小さくして、遷移エッジと背景を統計に含めないようにするためである。SDK による実測平均値は 220.11、180.09、139.97、100.06 であり、真値との最大偏差はわずか 0.11 グレースケール値である。実測標準偏差は 3.95~4.10 であり、注入されたノイズの \(\sigma=4\) と高度に一致している。これは、ROI が明瞭であれば、グレースケール値統計の精度はほぼノイズ自体によってのみ制限されることを示している。1000 画素以上の平均をとることで、1画素あたりの \(\sigma=4\) のランダム誤差が 0.1 レベルまで圧縮される。

平均値の標準誤差は \(\sigma/\sqrt{N}\) に従って縮小する。ROI 内には約 1800 画素あるので、\(4/\sqrt{1800}\approx 0.09\) となり、実測最大偏差の 0.11 と一致する。測定精度は 1 画素のノイズよりもはるかに高くできる。これがまさに統計的測定の価値である。

判定段階では、「実測平均値が公称値を 40 グレースケール値以上下回った場合、暗灯と判定する」というルールを採用する。4つの LED の公称値はそれぞれ異なるため、比較はグローバルな単一閾値に対して行うのではなく、各 LED ごとに自身の公称値と照合して行わなければならない。2号の LED の 140 を3号の LED の公称値 100 と比較すると、むしろ「明るい」と見なされてしまうためである。実行結果は、ちょうど2号の LED のみが DIM DEFECT としてマークされた(図 22.2)。公差 40 は根拠のない数値ではない。これはプロセスで許容される輝度変動(例えば、LED のビニング後の同ビン内の輝度ばらつきに駆動電流の公差を加えたもの)に基づいて設定され、さらに測定自体の不確かさの余裕が確保されている。公差を狭く設定しすぎると、正常なロット間の変動が誤って不合格と判定され、広く設定しすぎると真の欠陥が見逃される。

図 22.2: 輝度測定結果:白い円は各 LED の円形 ROI(半径 24 px)である。2号の LED の実測平均値 139.97 は、公称値 220 を公差 40 以上下回っているため、暗灯欠陥としてマークされている(斜めの十字)。

本実験では 8 ビット画像を使用しており、4 つの LED ビン間のグレースケール値の間隔は十分に広い。もし測定対象の合格と不合格の差が数グレースケール値しかない場合(例えばコーティングガラスの透過率のグレーディングなど)、8 ビットの 256 段階の量子化が精度のボトルネックとなるため、10/12 ビットでの撮像を使用すべきである(チャプター 1 参照)。

最後の注意点として、輝度測定は「画素のグレースケール値」を測定するが、画素のグレースケール値 = 物体の反射・発光特性 × 照明 × カメラのゲインと露光である。アルゴリズムが関心を持つのは最初の項のみであり、後の2項のいかなるドリフトもそのまま測定結果に反映される。照明の経年劣化、電圧変動、環境光の漏れ込みにより、同じパネルでも時刻によって測定される輝度が異なることがある(チャプター 4 参照)。生産ラインでの堅牢な運用方法は、視野内に輝度参照用のパッチを固定配置することである。すべての画像について、まず参照パッチを測定し、その読み値を用いて対象の読み値を正規化することで、照明のドリフトを打ち消すことができる。

22.2 色測定

輝度測定をカラー画像に拡張する最も直接的な方法は、R、G、B の各チャネルに対して個別に統計量を算出することである。実験場面は 80×80 の4つの色パッチ(青、緑、赤、橙赤)で構成されており、各チャネルに \(\sigma=5\) のノイズが付加されている(図 22.3)。各パッチ内部に 64×64 の矩形 ROI を設定して測定すると、3チャネルの平均値と真値との最大偏差は 0.25、標準偏差と \(\sigma=5\) との最大偏差は 0.12 であり、チャネル単位の統計量はグレースケールの場合と同様に高精度である。

図 22.3: 色測定の場面:青、緑、赤、橙赤の4つの色パッチに、各チャネルノイズ \(\sigma=5\) が付加されている。3番目と4番目のパッチ(赤と橙赤)は目視では非常に近く、本節で色差を定量化する主な対象である。

しかし、「各チャネルの差がどれだけあるか」と「人間の目にどれだけ違って見えるか」は同じではない。RGB 空間は知覚的に不均一である。同じ 20 単位のユークリッド距離でも、緑色の領域ではほとんど知覚できないのに対し、肌色の領域では非常に目立つ。産業界における色差の標準的な指標は、CIELAB 空間における色差(color difference) \(\Delta E\) である。CIE76 は Lab 座標のユークリッド距離として定義される:

\[ \Delta E_{76} = \sqrt{(\Delta L^*)^2 + (\Delta a^*)^2 + (\Delta b^*)^2}, \]

Lab 空間は非線形変換を経て構成されているため、同じ \(\Delta E\) がほぼ同じ知覚的な差に対応する。経験的に \(\Delta E \approx 2.3\)最小可覚差(just-noticeable difference, JND)とされており、これより近い2つの色は、普通の観察者が並べて見ても区別できない。

実験における赤と橙赤のパッチの BGR 真値の差はわずか (5, 20, 5) である。実測平均値から算出すると、BGR のユークリッド距離は 21.02 であり、Lab に換算した後の CIE76 \(\Delta E = 5.85\) は約 2.5 倍の JND である。これはまさに「目視では近いが、装置では分離可能」という典型的な範囲である。これら2つの色板を目視で選別するのは困難であるのに対し、測定システムはそれらを安定して区別し、連続的な偏差量を出力できる。補足すると、SDK は Lab 出力を提供していないため、ここでの \(\Delta E\) はコード内で sRGB(D65 白点)→XYZ→Lab と独自に換算したものである。換算式は付属のプロジェクトを参照されたい。

色測定と色マッチング(チャプター 18)の役割分担は以下の通りである:測定は「どれだけ偏っているか」を示し、連続量を出力するため品質のグレーディングやプロセス監視に適する。マッチングは「どのクラスに属するか」を示し、カテゴリラベルを出力するため仕分けに適する。同じ生産ラインで両方が必要となることが多い。

実用上、SDK には2つの知っておくべき約束事がある。1つ目は、colorSpace=0 の場合、MeasureColor が返す平均値・標準偏差の配列は R、G、B の順序で並んでいることである。これは画像メモリの BGR 格納順序とちょうど逆になっているため、添字 0 を B として扱うと赤と青が入れ替わってしまう。2つ目は、colorSpace=2 の HSV 出力において、色相は一般的な 0~360 度や 0~180(OpenCV の 8 ビットでの約束事)ではなく、度数 × 256/360 で表され、範囲は 0~256 であることである。純粋な赤の色相は 0 と 256 で回り込むため、実測された赤のパッチは 0 ではなく 256.0 を返す。色相による閾値判定を行う際には、この回り込みを処理しなければ赤の対象が全体的に見落とされてしまう。

22.3 間隙とピッチ測定

第3の代表的なシナリオはコネクタ、ピンヘッダ、ICリードである。等間隔に配列された多数の繰り返し構造で、欠陥は通常、そのうち1本が傾いている、位置ずれしている、または欠落しているという形で現れる。1本ごとにキャリパーを設定する(チャプター 20)方法は確かに機能するが、64ピンのコネクタには64個のキャリパーが必要となり、煩雑で非効率である。ピッチ測定器(pitch measurer)はこのようなシナリオ向けに設計された「バッチ式キャリパー」である。走査帯(band ROI)内で単一方向に沿って極性の規約に一致するすべてのエッジを抽出し、「立ち上がりエッジ—立ち下がりエッジ」のペアを形成する。各ペアから各ピンの幅と中心位置を求め、隣接する中心位置の差を計算してピッチ(pitch)系列を得る。これにより、1回の呼び出しで列全体の測定が完了する。

実験シーンは8本の垂直な明るいピン(幅14 px、公称中心間隔40 px)で構成され、5番目のピン全体を3 px右に移動させて位置欠陥を模擬し、\(\sigma=4\)のノイズを重畳している(図 22.4)。走査帯はすべてのピンを横切り、方向は左から右である。エッジ1は黒→白の極性(ピンの左縁)、エッジ2は白→黒の極性(右縁)としている。

図 22.4: ピッチ測定シーン:8本の垂直な明るいピン、幅14 px、公称ピッチ40 px。5番目のピン(左から6番目)が3 px右に移動しており、肉眼ではほとんど識別できない。

測定結果:8本のピンの幅は13.98~14.03(真値14)、中心位置決め誤差は≤0.01 pxであった。7区間のピッチは順に40.00、40.02、39.99、40.01、43.0037.00、40.00である。「公称40 ± 1.5 px」の判定基準に照らすと、4–5区間と5–6区間の2区間がちょうど許容範囲外となり、SDK自身が出力するmaxPitchIdx=4、minPitchIdx=5と一致する。結果は 図 22.5 の通りである。

図 22.5: ピッチ測定結果:上方の短い目盛り線は各ピンの実測中心、外枠は走査帯である。2つの異常なピッチ(4–5区間43.00 px、5–6区間37.00 px)は2本の縦線と底部の横棒で標示されており、それらの共通端点が位置ずれした5番目のピンである。

ここに記憶しておくべきパターンがある。1つの位置欠陥は2つのピッチ異常として現れるということである。5番目のピンが3 px右に移動したことで、左側のピッチは43、右側のピッチは37になった。大きすぎる区間の直後に小さすぎる区間が続き、偏差の大きさは等しく符号は逆である。したがって、ピッチ系列から欠陥位置を逆に追跡する際には、「4–5区間が許容範囲外」と「5–6区間が許容範囲外」を2つの別々の欠陥として報告するのではなく、異常ペアの共通端点を探すべきである。2つの異常区間に共有される5番目のピンこそが真の原因である。逆に、孤立した1区間のピッチだけが異常で隣接区間が正常である場合は、ピンの幅の異常かエッジ抽出の誤りである可能性が高く、別の判定基準で再確認する価値がある。

ピッチ測定はキャリパーと同じサブピクセルエッジカーネルを共有している。本実験における≤0.01 pxの中心誤差の大きさは、チャプター 20 の片側位置決め精度と一致している。違いは実行方法のみである。キャリパーは1回に1組のエッジを測定するのに対し、ピッチ測定器は1回に列全体を測定する。

22.4 SciVision 実装

3種類の測定はそれぞれSciSvIntensityMeasurementSciSvColorMeasurementSciSvPitchMeasurerによって処理される。輝度測定は以下の通りである。

SCIMV::SciSvIntensityMeasurement im;
SciROI roi;
SciPoint ctr(LED_CX[k], LED_CY);
roi.GenCircle(ctr, 24.0);                       // 円形ROI、半径24
double avg, sd, mn, mx, med, pixelTotal;
long rc = im.MeasureIntensity(img, roi, /*lower*/0, /*upper*/255,
                              NULL, &avg, &sd, &mn, &mx, &med,
                              NULL, &pixelTotal, NULL, NULL);
// pixelTotal:SDK出力、実測値3324でROIの幾何的ピクセル数約1810とは異なる。意味が不明確なため、工業的用途で面積として使用してはならない

lower/upperは統計に含めるためのグレースケール閾値であり(0..255は全ピクセルを意味する)、露出オーバーの点を除外するために使用できる。出力は順に平均値、標準偏差、最小値、最大値、中央値、pixelTotal(SDK出力、実測値3324でROIの幾何的ピクセル数約1810とは異なる。意味が不明確なため、工業的用途で面積として使用してはならない)である。不要な出力にはNULLを渡せばよい。

色測定(2回の呼び出しでは異なるROI変数を使用する必要がある。パラメータは非const参照である):

SCIMV::SciSvColorMeasurement cmeas;
SciROI roi;  roi.GenRect1(tl, br);               // GenRect1の右下隅は排他的端点
SciVarArray avgRGB, stdRGB;
long rc = cmeas.MeasureColor(img, roi, /*colorSpace*/0,   // 0=RGB, 2=HSV
                             0, 255, 0, 255, 0, 255,      // 3チャンネルの統計閾値
                             /*model*/0, NULL, &avgRGB, &stdRGB, NULL, NULL);
double B = avgRGB[2].D(), G = avgRGB[1].D(), R = avgRGB[0].D();  // 戻り値の順序はR,G,B!

ピッチ測定:

SCIMV::SciSvPitchMeasurer pm;
SciROI band;  band.GenRect1(SciPoint(50,100), SciPoint(410,140));  // ピンを横切る走査帯
EdgeDirection dir;   // 左から右;エッジ1は黒->白(左縁)、エッジ2は白->黒(右縁)
dir.direction1 = 2; dir.direction2 = 2; dir.polarity1 = 0; dir.polarity2 = 1;
EdgeFilter filter;
filter.searchLineCount = 1; filter.edgeWidth = 2; filter.projectWidth = 2;
filter.sensitivity = 30; filter.strengthThresh = 5; filter.strengthLimit = 255;
double avgWidth, avgPitch;  SciVarArray widthArr, intervalArr, pitchArr, ang1, ang2;
SciPointArray edge1, edge2;  int maxW, minW, maxP, minP;
long rc = pm.PitchMeasurer(img, band, region, dir, /*pattern*/0, filter,
                           0, 0, /*widthThresh*/5.0, /*widthLimit*/30.0,
                           /*pairsCount*/8,
                           &avgWidth, &avgPitch, &widthArr, &intervalArr, &pitchArr,
                           &maxW, &minW, &maxP, &minP, &edge1, &ang1, &edge2, &ang2);

widthThresh/widthLimitは合法的なピンの幅の範囲(5~30 px)を制限し、ノイズによるエッジペアをフィルタリングする。pairsCountは期待されるエッジペアの数である。pitchArr\(N-1\)項のピッチを返し、maxP/minPは最大/最小ピッチのインデックスを直接与える。

実測で遭遇した落とし穴を以下にまとめる。いずれも付属のプロジェクトcode/intensity_color_gap_measurement/で対処済みである。

  • MeasureColorの戻り値の順序はR, G, Bであり、画像の格納順序であるBGRとは逆であるため、値を取得する際には逆順でインデックス指定する必要がある。
  • HSVの色相は度数 × 256/360(0~256)であり、赤色は256.0に折り返す。色相の範囲判定を行う際には折り返し処理が必要である。
  • PitchMeasurerのエッジ点配列は各エッジにつき2つの端点を出力する(走査帯の上縁と下縁に1つずつ、交互に配列される)。8本のピンの場合、edge1の長さは8ではなく16となる。ピンごとの中心を求める際には、同じエッジの2つの端点をまず平均する必要がある。

工業事例:バックライト(透過照明)モジュールの輝度均一性

あるバックライト(透過照明)モジュールの生産ラインでは、9点法によって均一性(uniformity)の受け入れ検査を行っていた。画面に9つの測定点を設定し、最暗点の平均値と最亮点の平均値の比が80%以上であることが要求されていた。単点測定の再現性は常に良好であったが、量産開始後に顧客からの苦情が増加した。調査の結果、治具の金属製の押さえ縁が光を画面の四隅に反射し、4つの角の測定点の平均値を約5%系統的に高く見せていたことが判明した。角はバックライトが最も暗い部分であるため、読み値が嵩み上げられたことでmin/max比が人為的に高くなり、本来は不合格となるべき低均一性のモジュールが出荷されていた。

改善は2段階で行われた。まず治具に遮光カバーを取り付けて反射を除去し、同時に各測定点の統計量を平均値から中央値に変更し、残留する反射輝点が読み値を引き上げる影響を抑制した。改善後、判定結果と目視評価が再び一致するようになった。教訓として、統計量の選択は測定設計の一部であるということが挙げられる。平均値はすべてのピクセルを等しく扱うのに対し、中央値は少数の外れ値を自然に破棄する。測定点の環境を制御できない場合、後者の方が「人間が見る輝度」に近いことが多い。

22.5 まとめ

  • 3種類の非幾何測定は共通の骨格を持つ:ROI内で統計を算出 → 公称値と比較 → 許容差に基づき判定する。ROIはエッジと背景を避ける必要があり、許容差は勘に頼るのではなく工程のばらつきに基づいて設定する必要がある。
  • 統計により精度をノイズ以下にする:平均値の標準誤差は\(\sigma/\sqrt{N}\)で縮小する。本章における輝度平均の誤差0.11、チャンネル平均の誤差0.25、ピン中心の誤差0.01 pxは、いずれも単ピクセルノイズをはるかに下回っている。
  • 色差は知覚的に一様な空間で計算する:RGB空間での距離は視覚的な差を反映しない。工業的な判定基準にはCIELABの\(\Delta E\)を用い、JNDは約2.3である。赤色とオレンジがかった赤色の実測\(\Delta E = 5.85\)であり、肉眼では近いが装置では分離可能である。
  • 1つの位置欠陥 = 2つのピッチ異常:ピッチ系列における大きさが等しく符号が逆の隣接異常ペアは、それらの共通端点を指し示す。ピッチ測定器は本質的にはバッチ化されたキャリパーである。
  • SDKの3つの約束事を記憶する:色平均の戻り値の順序はR,G,B、HSVの色相は256スケールで赤色の位置で折り返す、ピッチ測定のエッジ点は各エッジにつき上下2つの端点を出力する。

輝度測定と色測定の背後にある放射測定と測色の基礎、およびエッジペア測定の体系的な議論については、Stegerらの著作(Steger, Ulrich, と Wiedemann 2018)を参照されたい。本章で使用したCIELAB、白点、\(\Delta E\)などの概念は、WyszeckiとStilesの測色学の古典的な著作に由来する。ほぼすべての色空間と色差公式の定義、データ、導出がここに集約されている(Wyszecki と Stiles 2000)。本章では簡潔さのためにCIE76の\(\Delta E\)を使用したが、工業現場では知覚的な一様性に優れたCIEDE2000がより一般的に使用される。Sharmaらはこの式の完全な実装詳細、補足試験データ、およびいくつかの数学的な注記を提供しており、本章の色差計算を現行の標準式にアップグレードするための実用的な参考資料となっている(Sharma, Wu, と Dalal 2005)