ラベリング

二値化画像処理された画像において、白の部分(または黒の部分)が連続した画素に同じ番号を割り振る処理を
ラベリングと言います。

 

通常、同じ番号ごとの面積(画素数)や幅、高さなどの特徴量を求めて欠陥検査や分類処理などに用いられます。

 

ラベリングには、二値化された画像の縦、横方向に連続している部分を同じラベルにする4連結と、
縦、横、斜め方向に連続している部分を同じラベルにする8連結との2種類の処理があります。
(4近傍、8近傍という場合もあります。)

【二値化画像】
【4連結】 【8連結】

以下、8連結の場合において、ラベリング処理アルゴリズムを紹介します。

 

まず、画像全ての画素のラベル番号を0(ゼロ)で初期化しておき、ラベリングで番号を割り付けるための
ラベリング番号のルックアップテーブルを用意しておきます。(テーブルの使い方の詳細は後ほど)

 

そして、画像の左上からラスタスキャンを行い、画素の色がの位置を検索します。

 

白の画素の左上、上、右上、左の画素のラベル番号を参照し、全て0(ゼロ)の場合は、最後に割り振った番号+1のラベル番号を割り振ります。
もし、参照した画素のラベル番号が複数存在した場合は、最小の番号を割り振ります。

 

最初に番号を割り振った様子↓

 

この処理を左上からラスタスキャンして続けていきます。

 

新しい番号が割り振られるとき↓

 

新しい番号が割り振られるとき↓ その2

 

参照した画素のラベル番号が複数存在した場合、最小の番号を割り振ります。
このとき、用いなかったラベル番号(下図の例では3)のルックアップテーブルの番号を最小の番号に書き換えます。

 

同様に、処理を続けていきます↓

 

全ての白の画素に番号が割り振れれた様子↓

 

ただし、よ~く見ると、ラベル番号の2や3など、連続していない部分が存在している事に気がつきます。
そこで、ルックアップテーブルの出番です。

 

処理の途中でルックアップテーブルの番号を変更した番号を
2→1、3→1、6→5
に変更すると、連続した領域は同じ番号になります。

 

このまま番号を変更しても良いのですが、ラベル番号が虫食いになるのも気持ちが悪いので、以下のようにルックアップテーブルの番号を詰め直してから、ルックアップテーブルを参照し、全画素のラベル番号を修正すると、以下のようになります。

 

基本的なアルゴリズムは上記、紹介したアルゴリズムで良いのですが、ラベリング処理を行う画像のパターンによってはうまくラベル番号が割り振られない場合があります。
そこは、何とかして(ちょっと説明が難しい部分)うまく割り振られるようにチャレンジしてみて下さい。

 

参考までに、ラベリング処理をすると失敗しやすい特徴的な画像を添付しておきます。↓

◆Level.1

 

◆Level.2

 

◆Level.Max!?

 

ラベリング処理のアルゴリズムには、この手法の他にも輪郭線を追跡し、閉じた領域を1つのラベルとする手法や、ランレングス的に求める方法もあります。

 

画像処理アルゴリズムへ戻る

 

判別分析法(大津の二値化)

判別分析法【discriminant analysis method】は大津の二値化とも言われ、分離度(separation metrics)

という値が最大となるしきい値を求め、自動的に二値化を行う手法です。

 

分離度はクラス間分散(between-class variance)とクラス内分散(within-class variance)
との比で求める事ができ、以下の様に求めます。

しきい値  で二値化したとき、しきい値よりも輝度値が小さい側(黒クラス)の画素数をω1
平均をm1、分散をσ1、輝度値が大きい側(白クラス)の画素数を画素数をω2、平均をm2
分散をσ2、画像全体の画素数をωt、平均をmt、分散をσtとしたときクラス内分散σw2

 

 

クラス間分散σb2

 

としてあらわす事ができる。

 

ここで、全分散(total variance)σt

 

としてあらわす事ができることから、求めるクラス間分散とクラス内分散との比である分離度

  

となり、この分離度が最大となるしきい値 t を求めればよい。
ここで、全分散σtはしきい値に関係なく一定なので、クラス間分散σb2が最大となるしきい値を
求めればよい事が分かる。
さらにクラス間分散の式の分母もしきい値に関係なく一定なので、クラス間分散の分子

 

  ω1 ω2 (m1 – m2)2

 

が最大となるしきい値 t を求めればよい。
結局、分散とか関係なく、黒、白それぞれの領域のヒストグラムから、画素数ωと輝度値の
平均値mから上記の値が最大となるしきい値 t をしらみつぶしに求めればいいので、以外と簡単...

 

【処理例】

上記例のように、判別分析法はおおむね良好な結果を得る事ができます。

 

画像処理アルゴリズムへ戻る

 

Pタイル法

Pタイル法【Percentile Method】は、画像の二値化したい領域が全画像の領域に占める割合をパーセント(%)で指定し二値化する手法です。

【処理例】

Pタイル法処理前

Pタイル法処理後

(二値化する割合を23%で指定)

【処理アルゴリズム】

まず最初に画像のヒストグラムを取得します。

 

このヒストグラムを見ると、輝度値でおおよそ160前後で二値化すると、目的の画像が得られそうな 事が分かります。

次にヒストグラムの輝度値が高い方から頻度を足していき、その頻度の合計が指定した割合を超える 輝度値をしきい値とし、二値化処理を行います。

 

実際の処理では、例えば画像サイズが640×480画素だとすると、全画素数は307,200画素なので、 二値化する割合が23%のときは23%に相当する画素数は

307,200 × 0.23 = 70,656画素

なので、ヒストグラムの頻度を輝度値の高い方から(黒側の面積を指定する場合は低い方から)足していった時に70,656画素を初めて超える輝度値を二値化のしきい値とします。 Pタイル法では、二値化する領域の大きさが一定の場合、画像の明るさが変動しても、二値化された 画像は変わらない事がメリットです。

 

一般にカメラから得られる画像の輝度値はカメラ本体の温度変化により変動し、LEDなどの照明も 長時間使用していると暗くなる傾向があるので、固定しきい値による二値化処理よりも安定的に 二値化処理を行うことが可能となります。 もっとも、二値化する領域の大きさの変動が大きい場合は不向きです。

 

画像処理アルゴリズムへ戻る

 

二値化

二値化【Binarization】では画像の輝度値が指定した値(しきい値【Threshold】)以上の場合は、値未満の場合はにする処理を行います。

二値化処理前 二値化処理後

 

二値化処理では上図のように、しきい値付近に輝度値の変動がある場合、二値化処理を行うと点々とした画素が残ってしまうため、この場合は二値化処理を行う前に平滑化フィルタメディアンフィルタなどのノイズ除去を行ってから二値化処理を行う場合が多くあります。 また、二値化処理を行うと画像の輝度値は白と黒しかないため、の輝度値をの輝度値をとし、1画素を1ビットであらわす事ができ、画像データサイズを小さくすることができるのですが、1画素を1ビットであらわすと各画素の輝度値の参照がかえって面倒になってしまうので、画像処理のプログラムではの輝度値を255の輝度値をとして、1画素8ビット(1バイト)で扱う場合の方が一般的です。 (フォトレタッチ系のソフトでは1画素1ビットで扱う場合の方が多いと思います。)

 

【二値化処理の応用例】

  • 欠陥検出
  • 領域分割、抽出
  • 処理領域のマスク(領域指定)

など  

 

【二値化プログラム例】
●効率の悪いプログラム例

for (j = 0; j < Height ; j++){
    for ( i = 0; i < Width; i++){ 
        //入力画像の輝度値の取得
        Bright = pSrc[i + j * Width]; 
        //二値化処理 
        if (Bright >= Threshold)
            pDst[i + j * Width] = 255;
        else
            pDst[i + j * Width] =0;
    }
}

このプログラムでは画像の全画素をif文で処理しているので、非常に非効率です。 この部分はルックアップテーブルを用いて最適化します。 また、この例では二重ループを用いて画像の輝度値を二次元的に参照していますが、二値化処理では近傍画素を用いて処理を行わないので、画像データをただの一次元的な配列として捉えても構いません。 ということで、最適化したのが以下の例です。

●効率の良いプログラム例

unsigned char LUT[256] = {0};
//二値化ルックアップテーブルの作成
for ( i = Threshold; i < 256; i++)
    LUT[i] = 255;
//二値化処理
for ( i = 0; i < Width * Height; i++)
    pDst[i] =  LUT[ pSrc[i] ];

 

画像処理アルゴリズムへ戻る