OpenCV (Python3) を利用して画像を 2 値化

画像の閾値処理(2 値化)

OpenCV を利用して画像を 2 値化するには、画像を GRAY 空間に変換してから、ある閾値を超えるピクセルを黒にし、それ以外を白にする方法などが取られている。このような閾値処理は、画像全体に対して 1 つだけの閾値を決めて処理する方法(閾値処理)と、画像の各ピクセルに応じて異なる閾値を決めて処理する方法(適応閾値処理)とある。

閾値処理 threshold

次の例では、GRAY 空間に変換した画像に対して、閾値がそれぞれ 75、150 を超えたピクセルを 0 (黒)に変換し、それ以外を最大値(225)に変換する例である。

import cv2 as cv

img = cv.imread("sample.jpg")

img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
ret, thresh_150 = cv.threshold(img_gray, 150, 255, cv.THRESH_BINARY_INV)
ret, thresh_075 = cv.threshold(img_gray, 75, 255, cv.THRESH_BINARY_INV)

cv.imwrite("thresh_150.jpg", thresh_150)
cv.imwrite("thresh_075.jpg", thresh_075)
処理前GRAY 空間変換後
OpenCV 処理前の小麦の葉の画像
OpenCV 処理前の小麦の葉の画像(グレースケール)
処理後(閾値 75)処理後(閾値 150)
OpenCV 処理前の小麦の葉の画像(閾値75)
OpenCV 処理前の小麦の葉の画像(閾値150)

閾値の指定方法は、上の例で示した CV_THRESH_BINARY_INV のほかにもいくつか用意されている。

閾値の種類 処理後
THRESH_BINARY閾値を超えるピクセルは最高値になり、それ以外のピクセルは 0 になる。 THRESH_BINARY 処理
THRESH_BINARY_INV閾値を超えるピクセルは 0 になり、それ以外のピクセルは最高値になる。 THRESH_BINARY_INV 処理
THRESH_TRUNC閾値を超えるピクセルは閾値になり、それ以外のピクセルは変更されない。 THRESH_TRUNC 処理
THRESH_TOZERO閾値を超えるピクセルは変更されず、それ以外のピクセルは 0 になる。 THRESH_TOZERO 処理
THRESH_TOZERO_INV閾値を超えるピクセルは 0 になり、それ以外のピクセルは変更されない。 THRESH_TOZERO_INV 処理

適応閾値処理 adaptiveThreshold

threshold メソッドでは閾値を指定して、画像全体に対して 2 値化をしている。これに対して、adaptiveThreshold メソッドを用いれば、あるピクセルを 2 値化したい場合、そのピクセルを中心とする n×n ピクセルのデータを用いて、閾値計算を行い2 値化を行う。閾値は、指定範囲内の平均値 ADAPTIVE_THRESH_MEAN_C または標準化した平均値 ADAPTIVE_THRESH_GAUSSIAN_C を選ぶことができる。

import cv2 as cv
n = 99

img = cv.imread("opencv-wheat-leaf-sample.jpg")
img_gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)

thresh_m = cv.adaptiveThreshold(img_gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, n, 2)
thresh_g = cv.adaptiveThreshold(img_gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, n, 2)

cv.imwrite("thresh_m.jpg", thresh_m)
cv.imwrite("thresh_g.jpg", thresh_g)
処理後(ADAPTIVE_THRESH_MEAN)処理後(ADAPTIVE_THRESH_GAUSSIAN)
O処理前の小麦の葉の画像(平均)
処理前の小麦の葉の画像(正規)