つれづれなる備忘録

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

OpenCVの使い方15 ~ モルフォロジー変換3

 前回に続いてOpening/Closing以外でcv2.morphologyEx()を用いて処理できるモルフォロジー変換について紹介する。

https://atatat.hatenablog.com//entry/opencv14_morphology2atatat.hatenablog.com

1. 画像の生成

Google Colabでのサンプル画像読み込み

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)
src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)
plt.imshow(src)

以下文字jをテスト画像srcとして用いる。

"文字j"
文字j

2. Gradient, Tophat, Blackhat処理

膨張した画像と収縮した画像の差分をとるGradient処理はcv2.MORPH_GRADIENTで指定する。輪郭を画像を生成するために用いられる。

kernel = np.ones((5,5),np.uint8)
gradient5 = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel)
kernel = np.ones((3,3),np.uint8)
gradient3 = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel)
plt.figure(figsize=(8,5))
plt.subplot(1,3,1)
plt.imshow(src)
plt.subplot(1,3,2)
plt.imshow(gradient5)
plt.subplot(1,3,3)
plt.imshow(gradient3)

左から元のj文字画像、カーネルサイズ5x5, 3x3の場合の処理結果を示す。カーネルサイズが小さいほど輪郭が細くなることがわかる。

"Gradient処理"
Gradient処理

次に元の画像とOpening処理の差を取るトップハット処理はcv2.MORPH_TOPHAT、逆に元の画像とClosing処理の差を取るブラックハット処理はcv2.MORPH_BLACKHATを指定する。

kernel = np.ones((9,9),np.uint8)
tophat = cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel)
plt.figure(figsize=(8,5))
plt.subplot(1,3,1)
plt.imshow(src)
plt.subplot(1,3,2)
plt.imshow(tophat)
plt.subplot(1,3,3)
plt.imshow(blackhat)

カーネルサイズを9x9として左から元のj文字画像、トップハット処理、ブラックハット処理した画像を示す。

"Tophat, Blackhat処理"
Tophat, Blackhat処理

3. カーネル生成

 カーネルを生成するためにNumpyのnp.ones()を利用したが、以下十字型、矩形型、楕円型についてはcv2.getStructuringElement()を用いて、それぞれcv2.MORPH_CROSS, cv2.MORPH_RECt, cv2.MORPH_ELLIPSEを指定することで生成することができる。

cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
>array([[0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0],
       [1, 1, 1, 1, 1],
       [0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0]], dtype=uint8
cv2.getStructuringElement(cv2.MORPH_RECT,(5,2))
>array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]], dtype=uint8)
cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
>array([[0, 0, 1, 0, 0],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [0, 0, 1, 0, 0]], dtype=uint8)

矩形のようなあるカーネルを用いることで処理に方向性をもたせることができる。例えば5x2の矩形カーネルを用いてGradient処理を行う。

kernel = np.ones((5,5),np.uint8)
gradient5 = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,2))
gradient_rec = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel)
plt.figure(figsize=(8,5))
plt.subplot(1,3,1)
plt.imshow(src)
plt.subplot(1,3,2)
plt.imshow(gradient5)
plt.subplot(1,3,3)
plt.imshow(gradient_rec)

左から元の画像、5x5のカーネル, 5x2の矩形カーネル処理だが、矩形カーネルは縦方向に対してより太い輪郭が描かれていることがわかる。

"矩形カーネルによるGradient処理"
矩形カーネルによるGradient処理

4. まとめ

 今回は、Gradient, Tophat, Blackhat, getStructuringElement()関数を用いたカーネル生成と効果について消化したい。今回でOpenCVを用いた基本的なモルフォロジー変換について一通り終わった。