つれづれなる備忘録

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

OpenCVの使い方17 ~ モルフォロジー変換5

 今回はOpenCVを用いてトップハット、ブラックハットを用いた画像処理の例にについて紹介する。

1. 名刺

名刺の画像から背景を消して文字を取り出すためにトップハット処理を適用する。

orig = cv2.imread(uploaded_file_name)
src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
plt.figure(figsize=(10,15))
plt.imshow(gray,cmap='gray',vmin=0,vmax=255)

"名刺画像"
名刺画像

トップハット処理を行うため、文字を白にするためcv2.bitwise()で白黒を反転させた上で閾値threshold=30で2値化画像を生成する。

gray2 = cv2.bitwise_not(gray)
plt.figure(figsize=(10,15))
plt.imshow(gray2,cmap='gray',vmin=0,vmax=255)

ret,thresh = cv2.threshold(gray2,30,255,cv2.THRESH_BINARY)
plt.figure(figsize=(10,15))
plt.imshow(thresh,cmap='gray',vmin = 0, vmax = 255)

"2値化画像"
2値化画像

カーネルサイズ5x5を用いて以下のようにトップハット処理を行うと、2値化で残っていた背景をすべて黒(厳密には左上に少し残っている)にすることができた。

kernel = np.ones((5,5),np.uint8)
tophat = cv2.morphologyEx(thresh, cv2.MORPH_TOPHAT, kernel)
plt.figure(figsize=(10,15))
plt.imshow(tophat,cmap='gray',vmin = 0, vmax = 255)

"トップハット処理画像"
トップハット処理画像

黒文字の状態で処理したい場合は、反転せずに2値化してブラックハット処理を適用する。

ret,thresh = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)
plt.figure(figsize=(10,15))
plt.imshow(thresh,cmap='gray',vmin = 0, vmax = 255)

"2値化画像(黒文字)"
2値化画像(黒文字)

カーネルサイズも上と同じ5x5を適用して、処理をブラックハットに指定する

kernel = np.ones((5,5),np.uint8)
blackhat = cv2.morphologyEx(thresh, cv2.MORPH_BLACKHAT, kernel)
plt.figure(figsize=(10,15))
plt.imshow(blackhat,cmap='gray',vmin = 0, vmax = 255)

最終的にはトップハット処理と同じ画像が得られる。

"ブラックハット処理画像"
ブラックハット処理画像

2. 標識

 次は道路案内板の文字に関してトップハット、ブラックハット処理の違いをみる。

orig = cv2.imread(uploaded_file_name)
src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
plt.figure(figsize=(10,15))
plt.imshow(gray,cmap='gray',vmin=0,vmax=255)

名刺画像よりも背景が複雑な点や、文字の輝度が異なるところが大きな違いになる。

"道路案内板画像"
道路案内板画像

案内板上の文字は白と黒が混在しているが、まず反転処理は行わずにthreshold=150で2値化する。

ret,thresh = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
plt.figure(figsize=(10,15))
plt.imshow(thresh,cmap='gray',vmin = 0, vmax = 255)

"2値化画像"
2値化画像

カーネルサイズを10x10として、トップハット処理とブラックハット処理を実行する。

kernel = np.ones((10,10),np.uint8)
tophat = cv2.morphologyEx(thresh, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(thresh, cv2.MORPH_BLACKHAT, kernel)
plt.figure(figsize=(20,30))

plt.subplot(1,2,1)
plt.imshow(tophat,cmap='gray',vmin = 0, vmax = 255)
plt.subplot(1,2,2)
plt.imshow(blackhat,cmap='gray',vmin = 0, vmax = 255)

左はトップハット処理、右はブラックハット処理をした画像を表示している。左のトップハット画像では電光掲示含めて白文字はしっかりと処理ができていて、黒文字は部分的には失敗している。 対称的に右側のブラックハット処理では、黒文字は処理できているが白文字は部分的に失敗している。なお、基本的には文字も含めて細い線を残す処理なので、背景の木々や案内板のフレーム、案内板上の線は残ってしまう。

"トップハット、ブラックハット処理画像"
トップハット、ブラックハット処理画像

中心の"名古屋市街"の文字を処理するために、閾値を220に設定して同様にトップハット処理とブラックハット処理をする。

ret,thresh = cv2.threshold(gray,220,255,cv2.THRESH_BINARY)
plt.figure(figsize=(10,15))
plt.imshow(thresh,cmap='gray',vmin = 0, vmax = 255)

閾値を大きくすることで、"名古屋市街"の文字が残り、また木々などの背景を黒にすることができたが、輝度の低い電光掲示の文字も黒になっている。

"2値化処理画像(閾値220)"
2値化処理画像(閾値220)

kernel = np.ones((10,10),np.uint8)
tophat = cv2.morphologyEx(thresh, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(thresh, cv2.MORPH_BLACKHAT, kernel)
plt.figure(figsize=(20,30))

plt.subplot(1,2,1)
plt.imshow(tophat,cmap='gray',vmin = 0, vmax = 255)
plt.subplot(1,2,2)
plt.imshow(blackhat,cmap='gray',vmin = 0, vmax = 255)

左はトップハット処理、右はブラックハット処理をした画像で、上と同様にトップハット処理は白文字、ブラックハット処理は黒文字に有効に処理ができている。

"トップハット、ブラックハット処理画像"
トップハット、ブラックハット処理画像

3. まとめ

OpenCVのトップハット、ブラックハットを用いた画像処理の例として名刺と道路案内板の文字について取り上げた。