前回Python/OpenCVによる単純な二値化を学びましたが、二値化処理はまだまだ奥が深いです。今回は単純な二値化だけでは上手くいかない画像に対する「適応的閾値処理による二値化」を習得します。
こんにちは。wat(@watlablog)です。
PythonとOpenCVによる画像処理の二値化を深堀をするために、ここでは適応的閾値処理による二値化を習得します!
適応的閾値処理なら綺麗な二値化処理ができる
通常の二値化処理
今回題材にするのはこの画像。碁盤です。
この碁盤には縦と横に線が入っており、碁盤の目を形成しています。さらに白と黒の石があり、二値化の題材としては非常に良い画像です。
前回の「Python/OpenCVで画像の二値化をする方法」で紹介したcv2.thresholdを使った二値化の方法を使ってみると以下の図のようになります。ここでは閾値を127にしています。
元画像の碁盤には「影」が落ちており、単純にある閾値で二値に分けようとするとこのように影があったり、同じ画像内に光源の偏りがあると二値化が上手くいきません。
そんな時に適応的閾値処理を使います!
適応的閾値処理とは?
適応的閾値処理を図解すると以下のようになります。
画像全体の中で任意の大きさの局所領域を設定し、その領域の中で閾値の計算を行い、1つ1つの画素を二値化して行きます。
この局所領域を画像全領域で走査することで、画像の画素全体の二値化を「各領域に合わせた閾値で」行うことができます。
これを適応的閾値処理と呼びます。適応的、とは英語ではAdaptiveを使います。
適応的閾値処理の効果を見てみる
百聞は一見にしかずです。以下の図に適応的閾値処理の効果を示します。
(a)が元の画像、(b)が通常の単一閾値で二値化した画像、(c)が適応的閾値処理によって二値化した画像です。
このように、適応的閾値処理の方は影が有ろうと無かろうと、碁盤の目や白と黒の石が綺麗に判別できる程度に二値化することができている様子がわかりますね。
適応的閾値処理のPythonコード
以下が適応的閾値処理を用いた二値化のPythonコードです。
ほとんどが「Python/OpenCVで画像の二値化をする方法」で書いたコードと同じですが、cv2.adaptiveThresholdを使っている部分だけが異なります。
以下が各引数の意味です。
第1引数:二値化する画像データ。
第2引数:輝度値の最大値。
第3引数:閾値計算のタイプ。
「ADAPTIVE_THRESHOLD_GAUSSIAN_C」は局所領域で閾値を計算する方法にガウス分布による重み付けを行った平均値を採用します。
「ADAPTIVE_THRESHOLD_MEAN_C」にすることで閾値に局所領域の中央値を採用します。
第4引数:閾値処理の種類。
第5引数:局所領域のサイズ(奇数である必要がある)。
第6引数:閾値から引く値。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import cv2 from matplotlib import pyplot as plt path = 'igo.jpg' # 画像のパス i = cv2.imread(path, 0) # 画像読み込み i_max = 255 # 最大輝度値 # 適応的閾値処理による二値化 i_binary = cv2.adaptiveThreshold(i, i_max, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \ cv2.THRESH_BINARY, 39, 2) #ここからグラフ設定 fig = plt.figure() ax1 = fig.add_subplot(111) # 画像をプロット ax1.imshow(i_binary, cmap = 'gray') # 軸を消す設定 ax1.tick_params(labelbottom = False, bottom = False) ax1.tick_params(labelleft = False, left = False) fig.tight_layout() plt.show() plt.close() |
第5引数の値を増減させることで、領域内の閾値の値が変わりますが、イメージとしては、この値を大きくすればざっくりとした閾値計算になるので、高周波に対して鈍化するということになります。
逆にこの値を小さくすれば急激な変化に対してピーキーになりますが、それが求めている効果を発揮するとは限りません。結局は丁度良い数値を探すしかありません。
第6引数は単純に第5引数で決定した閾値から引く値なので、値を大きくすればどんどん白くなっていきます。これも結局は丁度良い数値を探すしかありません。
まとめ
二値化の方法として今回は「適応的閾値処理」を学びました。適応的閾値処理を使えば、光源の偏りがあっても綺麗に二値化ができるとわかりました。
適応的なんちゃら、考えた人は賢い!このような画像処理はいずれAIに学習させる教師データとしても使えるかもしれないね!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!