9 グレースケール変換とヒストグラム
生産現場で最も多く聞かれる不満の1つが「画像が全体的に薄暗く、濃淡がはっきりしない」というものである。対象物と背景のグレースケール値は明らかに異なるのに、目視では両者が曖昧に混ざって見えてしまう。こうした画像に直面した際、最初に行われることが多いのはコントラスト調整である。そしてアルゴリズムのレベルで「コントラスト調整」に対応するのが、最も単純な画像演算の1つである点演算(point operation)である。点演算は「出力画素のグレースケール値が、同一位置の入力画素のグレースケール値のみに依存する」、つまり \(s = T(r)\) であり、周辺の画素には一切依存しないという性質を持つ。これは チャプター 6 で扱う空間フィルタリングとは明確に対照的である。フィルタが周辺画素を参照するのに対し、点演算は対象の画素自身の値のみを参照する。8ビット画像の場合、すべての点演算は同一の実装形態、すなわちルックアップテーブル(lookup table, LUT)に帰着する。あらかじめ \(T(0)\) から \(T(255)\) までの計256個の出力値を計算してテーブルに格納しておき、処理時には各画素ごとにこのテーブルを参照するだけでよい。本章で扱うコントラストストレッチ、ガンマ補正、ヒストグラム均等化は、本質的には「この256項目のテーブルをどのように埋めるか」という1つの問いに対する異なる答えに過ぎない。
LUTの工学的な価値は、「任意の複雑なグレースケール写像」を1画素あたり1回の \(O(1)\) のテーブル参照に統一できる点にある。まず256段階のグレースケール値それぞれについて \(T(r)\) を1回ずつ計算し、その後画像全体を1回走査するだけでよい。\(T\) が区分的線形関数であろうと、べき関数であろうと、累積分布関数(CDF)であろうと、実行コストは完全に同一である。
本章では、合成した低コントラストなシーン(480×360)をすべての実験で一貫して用いる。正弦波状のテクスチャを持つ背景上に、一定のグレースケール値を持つ平板、暗い矩形、明るい円、2 pxの細い線2本、解像度評価用の縞模様のセットが配置されている。さらに2つのアンカーブロックにより、グレースケール値の範囲が正確に90から150に固定されている。画像全体のグレースケール値は \([90,150]\) の区間に収まっており、8ビットのダイナミックレンジの4分の1未満しか使用されていない。図 9.1 にこのシーンとそのヒストグラムを示す。
9.1 ヒストグラム:画像のグレースケール帳簿
ヒストグラム(histogram)は画像のグレースケール分布を統計したものである。第 \(k\) 番目のビンの度数 \(h(k)\) は、グレースケール値が \(k\) の画素数に等しい。度数を総画素数 \(N\) で割ると正規化ヒストグラム \(p(k)=h(k)/N\) が得られる。これはまさに チャプター 2 で述べた「経験分布」の具体例である。「ランダムに抽出した1つの画素のグレースケール値」を確率変数と見なせば、\(p(k)\) はこの確率変数の分布に対する経験的な推定値となる。ヒストグラムはすべての空間情報を破棄する(画像の画素をランダムに並べ替えてもヒストグラムは変わらない)一方で、露出とコントラストに関するすべての情報を1本の曲線に凝縮する。
ヒストグラムを読み取ることは基本的な技能である。度数が左端の0に張り付いて積み上がっている場合は露出アンダー(暗部がクリップされている)、右端の255に張り付いている場合は露出オーバー(ハイライトが飽和しており、クリップされた情報はどのようなソフトウェアでも復元不可能である。これは チャプター 4 の照明設計に立ち返って解決する必要がある)である。一方、図 9.1 (b) のように中央の狭い帯に度数が集中しているのは、典型的な低コントラストの特徴である。露出自体は問題ないが、シーン自体のコントラストが小さいか、レンズフレアによって暗部が持ち上げられている状態である。本章のシーンをSDKで統計すると、平均値114.78、グレースケールの標準偏差12.55、範囲はちょうど \([90,150]\) であった。標準偏差がわずか12.55というのは、8ビット画像において「全体的に濃淡がなく曖昧」であることを定量的に示す値である。
9.2 線形ストレッチ
グレースケール値が \([r_{\min}, r_{\max}]=[90,150]\) にしか収まっていないのであれば、最も直接的な修正方法はこの区間を線形に伸長して \([0,255]\) 全体に満たすことである:
\[ s = (r - r_{\min}) \cdot \frac{255}{r_{\max} - r_{\min}}. \]
これは傾きが \(255/60 = 4.25\) の直線であり、各画素のグレースケール値(ノイズを含む)が4.25倍に増幅される。図 9.2 はストレッチ後の結果である。テクスチャ、細い線、縞模様のセットがすべて明瞭に判別できるようになっている。統計的には平均値105.30、標準偏差は12.55から53.34に急上昇し、範囲は \([0,255]\) 全体に広がっている。
ストレッチ後のヒストグラム(図 9.2 (b))は、教科書的な櫛状アーティファクトを呈している。入力には61個の離散的なグレースケール値しか存在せず、整数値のLUTはそれらを \([0,255]\) 内の高々61個の出力値に写像するため、残りの約200個のビンは必然的に空になる。ストレッチは新たな情報を一切創出しない。既存の61段階のグレースケール値を数直線上に広げているだけであり、識別可能なグレースケールの段数は1つも増えていない。このことは有用な診断基準でもある。櫛状のヒストグラムが見られた場合、その画像はデジタルストレッチ処理を施された可能性が極めて高いと判断できる。
実際には、画像全体の最小値・最大値を直接用いてストレッチを行うことはロバストではない。1つのキズ(不良)画素が存在するだけで \(r_{\min}\) または \(r_{\max}\) が極端な値に引っ張られ、ストレッチの効果が損なわれてしまう。工学的に標準的な対策はパーセンタイル切断ストレッチである。最も暗い側と最も明るい側からそれぞれ \(p\%\)(例えば1%)の画素を捨てた後に区間の端点を決定することで、ごく少数の画素を犠牲にする代わりに外れ値に対する耐性を得る。
9.3 ガンマ補正
線形ストレッチはすべてのグレースケール値を等しく扱うのに対し、暗部を選択的に明るくしたり明部を選択的に暗くしたりする場合には非線形写像が必要となる。最も一般的なものがべき関数の形式を持つガンマ補正(gamma correction)である:
\[ s = 255 \cdot \left(\frac{r}{255}\right)^{\gamma}. \]
この曲線の直感的な理解は単純である。\(\gamma<1\) のとき曲線は上に凸となり、暗部の傾きは1より大きく(値が引き伸ばされて明るくなり)、明部の傾きは1より小さくなる(値が圧縮される)。\(\gamma>1\) のときは逆に、暗部が圧縮され明部が拡大される。両端の \(0\mapsto 0\) と \(255\mapsto 255\) は常に不変であり、中間調の配分だけが変化する。0から255のグレースケールランプを用いてSDKの仕様を確認すると、\(\gamma=0.5\) のとき \(64\to 128\)、\(128\to 181\)、\(192\to 221\) となり、出力値は常に入力値より大きい。これは上記の式(入力を先に正規化してからべき乗する)と一致している。
ストレッチ後の画像で実測したところ(図 9.3)、暗い矩形内部(ストレッチ後の平均値21.4)は \(\gamma=0.5\) により71.8に引き上げられ、\(\gamma=2.0\) によりわずか2.3に圧縮された。明るい円内部(245.6)は \(\gamma=0.5\) で250.0にわずかに上昇し、\(\gamma=2.0\) で236.8にわずかに下降したに過ぎない。これらの数値は曲線の形状を裏付けている。ガンマ補正の「力」のほとんどは、両端から遠い側に費やされる。\(\gamma<1\) は暗部を大幅に変化させるがハイライトにはほとんど影響せず、\(\gamma>1\) はその逆である。
「ガンマ」という語は表示システムに由来する。従来のディスプレイの輝度応答は近似的に \(V^{2.2}\) であるため、民生用画像(sRGB)は保存時にあらかじめ \(\gamma\approx 1/2.2\) の逆符号化が施されている。一方、産業用カメラはデフォルトで線形のグレースケール値を出力する。画素値が光束に比例するこの性質は、測定アルゴリズムが求めるものそのものである。測定パイプラインにガンマ補正を導入することは線形の測光関係を破壊することを意味するため、極めて慎重に行う必要がある。ガンマ補正の正当な用途は表示と目視検査である。
9.4 ヒストグラム均等化
ストレッチとガンマ補正はいずれも人手によるパラメータ選択を必要とするのに対し、ヒストグラム均等化(histogram equalization)は画像自身に写像を決定させる手法であり、出力ヒストグラムを可能な限り平坦にすることを目標とする。導出はたった1段階で済む。分布を「平坦にする」ためには、度数の多いグレースケール区間は引き伸ばし、度数の少ない区間は圧縮する必要がある。そして累積分布関数(cumulative distribution function, CDF)はまさにこの性質を本来的に備えている。\(\mathrm{CDF}(r)=\sum_{k\le r} p(k)\) と定義し、写像を
\[ s = T(r) = 255 \cdot \mathrm{CDF}(r), \]
とすると、\(T\) は単調非減少であり(グレースケールの順序が逆転することはない)、その局所的な傾きはその点におけるヒストグラムの密度 \(p(r)\) に比例する。つまり画素が密集している箇所ほど傾きが最も急峻になり、値が最も大きく引き伸ばされる。本章のシーンに均等化を施した結果を 図 9.4 に示す。標準偏差はさらに74.28(平均値131.30)まで上昇し、コントラストは線形ストレッチをも超えている。
ただし 図 9.4 (a) の右上にある「平板」をよく見てほしい。元の画像ではグレースケール値122の一定値に \(\sigma=2\) のノイズが重畳されていただけだったのが、現在は粒状の模様で覆われている。この平板内部の標準偏差を定量的に測定すると、本章で最も重要な一連の数値が得られる。元の画像で2.02、線形ストレッチ後で8.46(4.19倍。ほぼLUTの一定ゲインである \(255/60\) に等しい)、均等化後ではなんと18.02——8.93倍の増幅であり、線形ストレッチの2倍を超えている。その理由はまさにCDFの傾きにある。平板の数千個の画素はすべて122付近の2、3個のビンに詰め込まれており、そこでは \(p(r)\) が極めて高いため、\(T\) の局所的な傾きが最も急峻になる。均等化は画素が最も密集している箇所で、グレースケールの差(ノイズを含む)を最も激しく増幅するのであり、平坦領域はまさに画素が最も密集する場所なのである。
このことから、均等化の工学的な位置づけが定まる。均等化は「人に画像を見せるための」ツールであり、目視検査、報告書の図、人手による再確認用のインターフェースなどには非常に適している。しかし、測定や欠陥検出のパイプラインでは慎重に使用する必要がある。チャプター 7 の自動閾値処理手法は「前景と背景がそれぞれ集中したグレースケール値を持つ」という統計的前提に基づいているが、均等化はまさにこの前提を体系的に破壊する。平坦領域のノイズが約9倍に増幅されると、元々クリーンだった背景に閾値を超える多数の偽応答が生じてしまう。
均等化の局所ゲイン \(T'(r) \propto p(r)\) は、一見矛盾した現象も説明する。均等化による真の構造のコントラスト向上と平坦領域のノイズ増幅は全く同一の機構に由来するものであり、前者だけを得て後者を排除することは不可能である。適応的な変形手法(CLAHEのクリップリミットなど)は、まさに密集したビンにおける傾きに上限を設けることでこの矛盾を緩和している。
9.5 SciVision 実装
本章の実験は3つのクラスに関連する。ヒストグラム統計を行う SciSvHistogram、ストレッチと均等化を行う SciSvHistEqualize、ガンマ補正を行う SciSvBrightness である。
SCIMV::SciSvHistogram histOp;
SciROI roi; // デフォルトコンストラクト = UNDEF ROI、SDKでは画像全体を意味する
SciVarArray histData, histRange;
double avg, stdValue; int mn, mx, med, norm, total;
// lower=0, upper=255 統計範囲;type=4 カスタムビン数;nBins=256 つまりグレースケール値ごとに1ビン
histOp.CaculateHist(img, roi, 0, 255, 4, 256, &histData, &histRange,
&avg, &stdValue, &mn, &mx, &med, &norm, &total);
SCIMV::SciSvHistEqualize eq;
SciImage stretched, equalized;
// method=1 切断式線形ストレッチ;lowPct/highPct=0 は [minGray,maxGray]=[90,150] を [0,255] 全体にストレッチ
eq.LineStretchHist(scene, roi, 1, 0.0, 0.0, 90, 150, &stretched);
// rangeValue=255 全範囲均等化;minStrength=0 / maxStrength=255 はデフォルトの強度区間
eq.EqualizeHist(scene, roi, 255, 0, 255, &equalized);
SCIMV::SciSvBrightness bright;
SciImage dst;
bright.AdjustGamma(img, roi, 0.5f, &dst); // s = 255*(r/255)^gammaCaculateHist を1回呼び出すとヒストグラム配列と一連の統計量が同時に返されるが、知っておくべき落とし穴が1つある。出力パラメータ stdValue は256個のビンの度数の標準偏差であり、画素のグレースケール値の標準偏差ではない。本章の元の画像に対してこの値は157.61を返すが、これは8ビットグレースケールの標準偏差の理論的上限である127.5を超えており、明らかにグレースケール値の統計ではない。本文中で引用した12.55/53.34/74.28の値は、いずれもヒストグラムから独自に計算したグレースケール値の標準偏差である。LineStretchHist の method=0(画像全体の最小・最大値による自動ストレッチ)は、本画像に対して一切の変換を行わないことが確認された(SDKの不具合と思われる)。そのため method=1 を用い、[minGray, maxGray] を明示的に指定している。また、画像全体のROIを GenRect1((0,0),(W-1,H-1)) で構築してはならない。この矩形は半開区間として扱われ、最終行と最終列の計839個の画素が統計から除外されてしまう。画像全体を指定するには、デフォルトコンストラクトしたUNDEF ROIを用いればよい。最後の詳細として、SDKによるストレッチ結果を、式に従って手書きしたLUTによる処理結果と1画素ごとに比較したところ、最大差はわずか1であった(整数変換時の切り捨てと四捨五入の違いによる)。このことから LineStretchHist の内部はまさにルックアップテーブルによる点演算であることが確認された。
完全な実行可能プロジェクトは code/gray_transforms_histograms/ に配置されており、再現性を確保するために乱数シードは固定されている。
産業事例:「画像が暗い」に対する2つの修正法
ある生産ラインから、検査用画像が暗くコントラストが低いという報告があった。ソフトウェアチームは最初にヒストグラム均等化で「修正」したところ、画像は瞬く間に鮮明で見栄えの良いものになった。しかし2週間後、欠陥の誤報率が2倍になった。均等化によって背景の平坦領域のセンサノイズが数倍に増幅され(本章の2.02→18.02が工場現場で再現された格好である)、多数のノイズ画素が欠陥判定の閾値を超えて偽欠陥として報告されたのである。事後検証で確立された正しい修正法は2段階からなる。第1段階:ハードウェアシステムに立ち返り、露光時間、絞り、レンズを確認し、アナログゲインを下げて、根源から十分なグレースケール範囲を持ちノイズが制御された画像を取得する(チャプター 4 と チャプター 1 を参照)。第2段階:ソフトウェア側ではパラメータが制御されたパーセンタイル切断線形ストレッチのみを適用し、ストレッチ後のノイズレベルを閾値の調整に反映させる。得られた教訓は一言でまとめられる。「見栄えが良いこと」と「測定に適していること」は別物である——人間の目が好む高コントラストな画像が、アルゴリズムが必要とする低ノイズな画像であるとは限らないのである。
9.6 まとめ
- 点演算 = ルックアップテーブル。出力が同一位置の入力グレースケール値のみに依存する演算は総称して点演算と呼ばれ、8ビット画像上ではすべて256項目のLUTとして実装できる。ストレッチ、ガンマ補正、均等化は、このテーブルを埋めるための3つの異なる戦略に過ぎない。
- ヒストグラムはグレースケール値の経験分布である。空間情報を捨てる一方で、露出とコントラストに関するすべての証拠を保持する。左端に張り付いていれば露出アンダー、右端に張り付いていれば露出オーバー(情報は復元不可能)、中央の狭い帯に集中していれば低コントラストである。
- 線形ストレッチは情報を創出しない。61段階のグレースケール値を256段階に広げても、識別可能な段数は変わらず、ヒストグラムには櫛状の隙間が残る。外れ値に耐性を持たせるため、端点には画像全体の最小・最大値ではなく切断パーセンタイルを用いるべきである。
- ガンマ補正は非線形に中間調を再配分する。\(\gamma<1\) は暗部を明るくし明部を圧縮し、\(\gamma>1\) はその逆で両端は不変である。産業用カメラの出力は本来線形であるため、測定パイプラインにガンマ補正を導入する際は慎重を要する。
- 均等化はCDFに基づいてテーブルを埋め、局所ゲインはヒストグラムの密度に比例する——平坦領域は画素が最も密集するため、ノイズの増幅も最も激しい(本章の実測値で8.93倍、線形ストレッチの4.19倍をはるかに超える)。均等化は人間が見るための強調ツールであり、測定・検出パイプラインに導入する前に、チャプター 7 の統計的前提に与える損傷を評価する必要がある。
グレースケール変換とヒストグラム処理(大域的ヒストグラム均等化を含む)の標準的な記述はGonzalezとWoodsの教科書にある(Gonzalez と Woods 2018)。大域的均等化が平坦領域のノイズを増幅する欠点に対処するため、Pizerらによって提案された適応的ヒストグラム均等化とその限界付き変形(CLAHEの原型)は古典的な改善手法である(Pizer ほか 1987)。産業用パイプラインにおけるグレースケール変換とヒストグラム処理の体系的な記述(ロバストストレッチや多項式グレースケール補正を含む)については、Stegerらの著書をさらに参照できる(Steger, Ulrich, と Wiedemann 2018)。







