Pillow でOpenCV の膨張処理とを同じ処理がしたかったので、 その方法と処理結果が等しくなるか確認しました。
環境
コード全体
先に今回書いたコードを載せます。
# -*- coding: utf-8 -*- import cv2 import numpy as np from PIL import Image from PIL import ImageFilter def is_equal(cv_img, pil_img): return np.array_equal(cv_img, np.asarray(pil_img.convert('L'))) if __name__ == '__main__': img_file = 'test.png' cv_img = cv2.imread(img_file, cv2.IMREAD_GRAYSCALE) _, cv_img = cv2.threshold(cv_img, 127, 255, cv2.THRESH_BINARY) pil_img = Image.open(img_file).convert('1', dither=Image.NONE) print(is_equal(cv_img, pil_img)) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) cv_img_d = cv2.dilate(cv_img, kernel) pil_img_d = pil_img.filter(ImageFilter.MaxFilter(3)) print(is_equal(cv_img_d, pil_img_d)) pil_img_d = pil_img.filter(ImageFilter.MaxFilter(5)) print(is_equal(cv_img_d, pil_img_d))
このコードの結果は以下の通りです。
True True False
コードの説明
比較処理
def is_equal(cv_img, pil_img): return np.array_equal(cv_img, np.asarray(pil_img.convert('L')))
比較については以前、このような記事を書きました。
前回はカラー画像に対して比較しましたが、今回は二値画像です。 Pillow のimage をグレースケールにコンバートしてnumpy の配列に変換することで比較できます。 ただし、OpenCV の二値画像を0 or 255 で持つ必要があります。
二値化処理
_, cv_img = cv2.threshold(cv_img, 127, 255, cv2.THRESH_BINARY)
Python のOpenCV において、cv2.threshold
関数は処理結果の画像が2番目の戻り値だということに注意です。
ところで、2番目の引数に指定した閾値について、以下のようにすると膨張処理前の比較結果がFalse になってしまいます。
_, cv_img = cv2.threshold(cv_img, 128, 255, cv2.THRESH_BINARY)
OpenCV のTHRESH_BINARY の説明によると、 閾値以下の値が0、つまり閾値と同じ値を持つピクセルは0になります。 一方、Pillow のbilevel におけるconvert の説明によると、
If dither is NONE, all values larger than 128 are set to 255 (white), all other values to 0 (black).
とあるので、128の値を持つピクセルは0になるのではないかと判断しおります。
しかしこの結果を考えると、Pillow のconvert による二値化では128の値を持つピクセルは255になるのではないかと思います(未検証)。
*1
(2019/2/24追記)以下の記事で検証しました。
膨張処理
OpenCV
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) cv_img_d = cv2.dilate(cv_img, kernel)
OpenCV の膨張処理はcv2.dilate
を使います。
kernel の生成は、以下のような方法も可能です。
kernel = np.ones((3, 3), np.uint8)
Pillow
pil_img_d = pil_img.filter(ImageFilter.MaxFilter(3))
Pillow での膨張処理はImageFilter.MaxFilter
を使います。
ちなみにImageFilter.MaxFilter
の引数は奇数じゃないとダメっぽいです(4と6で失敗することを確認)。