つれづれなる備忘録

日々の発見をあるがままに綴る

OpenCVの使い方6 ~ 2値化処理

 OpenCVの使用方法について、今回は画像の2値化処理について紹介したい。

1. 基本的な2値化処理

 単純な2値化処理はある閾値を設定して、グレースケール(モノクロ)画像に対して閾値より大きければ白(255)、小さければ黒(0)を割り当てる。 以下Google Colabで画像をアップロードして読み込ませて、グレースケール画像データgrayを生成するまでのpythonコードを示す。

import cv2
import numpy as np
from matplotlib import pyplot as plt
from google.colab import files
uploaded_file = files.upload()
uploaded_file_name = next(iter(uploaded_file))
orig = cv2.imread(uploaded_file_name)

Google Colabにアップロードした画像(BGR)をグレースケールに変換して表示する。

gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
plt.imshow(gray,cmap='gray')

"元画像(グレースケール)"
元画像(グレースケール)

次にグレースケールの元画像に閾値閾値を越えたピクセル値に白(255)を割り当てるにはcv2.threshold(src,threshold,maxval,method)を用いる。srcは元画像、thresholdは閾値、maxvalは閾値超えたピクセルに割り当てる値で白であれば255,methodは2値化の方法を指定することができる。以下のコードではthreshold=127, maxval=255(白), method=cv2.THRESH_BINRYと白黒を反転させる method=cv2.THRESH_BINRY_INVを指定した。 なおplt.imshow()vmin = 0, vmax = 255を入れないと自動的に表示スケールが最適化されてしまう。

ret,thresh1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
plt.figure(figsize=(10,20))
plt.subplot(1,2,1)
plt.imshow(thresh1,cmap='gray',vmin = 0, vmax = 255)
plt.subplot(1,2,2)
plt.imshow(thresh2,cmap='gray',vmin = 0, vmax = 255)

左が元画像を2値化処理したもの、右は反転させた画像になる。

"2値化処理画像"
2値化処理画像

2. その他の2値化処理

単純な2値化処理でmaxval=255の代わりに、maxval=100とすると白の代わりにグレースケールが閾値を越えるピクセルに割り当てられる。左がmaxval=255,右がmaxval=100の画像。

"2値化処理画像比較"
2値化処理画像比較

methodとして,cv2.THRESH_BINARYcv2.THRESH_BINARY_INV以外で2値化処理するコードと画像を以下に示す。

ret,thresh3 = cv2.threshold(gray,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(gray,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(gray,127,255,cv2.THRESH_TOZERO_INV)
plt.figure(figsize=(8,8))
plt.subplot(2,2,1)
plt.imshow(thresh3,cmap='gray',vmin = 0, vmax = 255)
plt.subplot(2,2,3)
plt.imshow(thresh4,cmap='gray',vmin = 0, vmax = 255)
plt.subplot(2,2,4)
plt.imshow(thresh5,cmap='gray',vmin = 0, vmax = 255)

上段がcv2.THRESH_TRUNCで下段がcv2.THRESH_TOZERO、下段左が反転させたcv2.THRESH_TOZERO_INVを適用した画像になる。

"いろいろな2値化処理"
いろいろな2値化処理

それぞれの詳細は以下のドキュメントを参照。

Miscellaneous Image Transformations — OpenCV 3.0.0-dev documentation

3. 適応的2値化処理

 上では閾値を設定して画像全体に適用していたが、全体の照明の当たり方など画像の明るさが一様でないときに画像中の小領域ごとに閾値を計算して適用する。 適用的2値化処理を実行するにはcv2.adaptiveThreshold(src,maxval,thresh_method,method,blocksize,constant)を用いる。src, maxval,methodはcv2.thresholdと同じ意味、thresh_methodは閾値を計算する方法、blocksizeは閾値を計算する小領域のサイズ(奇数), constantは計算された閾値から減算する定数。小領域のサイズを11, 2値化処理方法をcv2.THRESH_BINARY, thresh_methodをcv2.ADAPTIVE_THRESH_MEAN_Ccv2.ADAPTIVE_THRESH_GAUSSIAN_Cとする場合のpythonコードを以下に示す。

ath1 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
ath2 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
plt.figure(figsize=(10,20))
plt.subplot(1,2,1)
plt.imshow(ath1,cmap='gray',,vmin = 0, vmax = 255)
plt.subplot(1,2,2)
plt.imshow(ath2,cmap='gray',,vmin = 0, vmax = 255)

実行すると以下のような画像(左がADAPTIVE_THRESH_MEAN_C,右がADAPTIVE_THRESH_GAUSSIAN_C)になり、輪郭を抽出するのに特に向いている

"適用的2値化処理"
適用的2値化処理

4. まとめ

 今回はOpenCVを画像のいろいろな2値化処理方法について紹介した。2値化処理は画像マスクや輪郭を抽出する上で有用に使用することができる。