2値化処理

目的

紙に書かれた文字や図形をディジタルカメラやスキャナでディジタル画像としてコンピュータに取り込み,処理することを考える.文字や図形では,そこにインクの染みがあるかないかが重要であるため,0か1(黒か白)の2値で各画素を表現すれば十分である.ここでは,多値(例えば8bit256階調グレースケール)画像を2値画像に変換する2値化処理について学ぶ.

説明

固定しきい値処理

書類に書かれた文字や図面は,白か黒か,あるいは背景か対象か,といった2つの値で表現できれば十分であり,多値で表現された画像を2値で表現することを2値化と呼ぶ.2値化処理は濃度変換の特殊なもので,ある濃度値をしきい値とし,背景と対象に分割する処理である.以下の8bitグレースケール画像をしきい値を指定して2値化してみよう.

22行目で画像を読み込み,23行目でヒストグラムを求めている.24行目で,引数で指定したしきい値(デフォルトで127)より大きい場合には255(白)とし,小さい場合には0(黒)としている.26行目から36行目でヒストグラムとしきい値を描画し,39行目で2値化した画像を描画している.実行すると以下のように表示され,デフォルトではしきい値127で2値化されていることがわかる.

OpenCVのthreshold関数

OpenCVには画像を2値化することができるthreshold関数が用意されている.threshold関数を使用して画像を2値化するには以下のようにすればよい.

24行目のように,第1引数に処理対象の画像を,第2引数にしきい値を,第3引数にしきい値以上の画素に対して割り当てる画素値を,第4引数にcv2.THRESH_BINARYを指定し,threshold関数を呼び出すと,しきい値retと2値化された画像binary_imageが返される.実行結果はthreshold関数を使用しない場合と同じである.

自動しきい値決定法

以上の例ではしきい値を指定していた.しきい値を自動あるいは半自動で決定する方法がいくつかある.ここでは,p-タイル法,モード法,大津の2値化の3種類の方法でしきい値を決定してみよう.

p-タイル法

p-タイル法は対象図形のおおよその面積が既知のときに有効な方法である.画像全体の面積を\(S\),対象図形の面積を\(S_0\)とすると,画像全体に対する対象図形の面積の比率\(p\)は$p=\frac{S_0}{S}$と表せる.対象図形が背景より暗いときには,濃度値の小さいほうから画素数を数え,全体の画素数に対する比率を求める.これが\(p\)と同じになるときの濃度値をしきい値とする.p-タイル法によりしきい値を決定するには以下のようにすればよい.

24行目でヒストグラムの累積分布を求め,25行目から28行目で,濃度値の小さい方から累積分布の値を確認し,引数で指定した比率(デフォルトで0.07)を超えた場合に,その濃度値をしきい値としている.実行すると以下のように表示され,しきい値137で2値化されていることがわかる.

モード法

モード法は,対象図形と背景の濃度値の差が大きく,濃度ヒストグラムに明確な谷がある場合に,濃度ヒストグラムが極小となる濃度値をしきい値とする方法である.一般に極小値を求めることは難しいため,ここでは極小値の存在する範囲を指定し,その範囲における最小値を極小値としよう.

25行目で,引数で指定した範囲(デフォルトでは50から200)において濃度ヒストグラムが最小となる濃度値を求め,しきい値としている.実行すると以下のように表示され,しきい値75で2値化されていることがわかる.

大津の2値化

大津の2値化では,ある濃度値でヒストグラムを2つのクラスに分割したときに,クラス内分散が最も小さくなる濃度値をしきい値として2値化を行う.したがって,濃度ヒストグラムに明確な谷がある場合に谷に相当する値をしきい値とすることができる.大津の2値化を行うには以下のようにすればよい.

OpenCVには大津の2値化が実装されており,23行目のように,第4引数にフラグとしてcv2.THRESH_OTSUを追加してthreshold関数を呼び出すと,しきい値retと2値化された画像binary_imageが返される.実行すると以下のように表示され,しきい値134で2値化されていることがわかる.

可変しきい値処理

以下のような右上が明るく,左下が暗く写っている画像を2値化してみよう.

大津の方法で2値化すると,以下のように表示され,うまく2値化されていないことがわかる.

このように右上が明るく,左下が暗い画像では,背景部分の濃度値や対象部分の濃度値が画像全体で一定でなく,背景部分の濃度値が別の対象部分の濃度値よりも小さい場合が生じる.したがって,画像全体で同じしきい値を使用する固定しきい値処理では,対象部分が背景部分に埋もれてしまうことがある.このような場合には,画素ごとにしきい値を変化させる可変しきい値処理が使用される.

可変しきい値処理では,注目している画素を中心として,ある大きさの局所領域の平均値を求め,それをしきい値とする.局所領域に対象と背景がある場合には,平均をとることによって対象と背景の中間の濃度値がしきい値となるため,うまく2値化することができる.白い(濃度値の大きい)背景に黒い(濃度値の小さい)対象が写っている場合,背景領域の面積が大きくなることが多いため,しきい値が大きな値となることがある.OpenCVの実装では,平均値から指定した値を引いたものをしきい値とすることができる.

平均値を使用した可変しきい値処理

局所領域の平均値をしきい値とする可変しきい値処理をしてみよう.

25行目のように,第1引数に処理対象の画像を,第2引数にしきい値以上の画素に対して割り当てる画素値を,第3引数にcv2.ADAPTIVE_THRESH_MEAN_Cを,第4引数にcv2.THRESH_BINARYを指定し,キーワード引数blockSizeに局所領域の大きさを,キーワード引数Cに平均値から引く値を指定し,adaptiveThreshold関数を呼び出すと,可変しきい値処理によって2値化された画像binary_imageが返される.局所領域の大きさを51,平均から引く値を16とすると,以下のような2値画像が得られ,うまく2値化されていることがわかる.

正規分布に従う重み付き平均値を使用した可変しきい値処理

OpenCVでは正規分布に従う重み付き平均値を使用する可変しきい値処理も実装されている.

25行目のように第3引数にcv2.ADAPTIVE_THRESH_GAUSSIAN_Cを指定してadaptiveThreshold関数を呼び出すと,正規分布に従う重み付き平均値をしきい値とする可変しきい値処理を行うことができる.実行すると以下のように表示され,うまく2値化されていることがわかる.

課題

課題0

8bitグレースケール画像を読み込み,しきい値を指定して2値化せよ.

課題1

8bitグレースケール画像を読み込み,p-タイル法により2値化せよ.

課題2

8bitグレースケール画像を読み込み,モード法により2値化せよ.

課題3

8bitグレースケール画像を読み込み,大津の方法により2値化せよ.

課題4

画像全体で明るさが変化している画像を読み込み,大津の方法により2値化せよ.

課題5

画像全体で明るさが変化している画像を読み込み,平均値を使用した可変しきい値処理により2値化せよ.

課題6

画像全体で明るさが変化している画像を読み込み,正規分布に従う重み付き平均値を使用した可変しきい値処理により2値化せよ.