つれづれなる備忘録

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

OpenCVの使い方16 ~ モルフォロジー変換4

 前回までのOpenCVによるモルフォロジー変換の応用としてOpening/Closing処理を用いた文書のノイズ処理について紹介する。

1. 中世の手紙

 豊臣秀吉の書状の文面で主に筆跡が薄いところを2値化して、かすれている(文字中に黒点)部分をClosing処理で見やすくする。

[豊臣秀吉書状] | 京都大学貴重資料デジタルアーカイブ

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)

読み込んだ画像をグレースケールにしたものが以下になる。

"豊臣秀吉の書状"
豊臣秀吉の書状

ビット反転することで、白と黒を入れ替えて文字が白になるようにする。

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

"反転画像"
反転画像

次に閾値threshold=130に設定して上の反転画像を2値化する。

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

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

最後に2値化画像をClosing処理する。

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

2値化画像よりもかすれている部分がわずかに明瞭になっている。

"Closing処理"
Closing処理

2. 奈良時代の経典

今度は奈良時代の不鮮明な文字を強めの2値化処理をして、余分なノイズをOPENING処理で除去する。

出典は無垢淨光陀羅尼. (出版年770年) 無垢淨光陀羅尼. [3] - 国立国会図書館デジタルコレクション

制作年代が明確な世界最古の印刷物。奈良時代の女帝、称徳天皇(718-770)の発願により作られた。

元の画像をグレー化、ビット反転した画像を以下に示す。

"奈良時代の古文書"
天平時代の古文書

閾値を低めのthreshold=78で2値化すると、

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

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

kernel= cv2.getStructuringElement(cv2.MORPH_RECT,(2,2))
closing = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
plt.figure(figsize=(20,20))
plt.imshow(closing,cmap='gray',vmin = 0, vmax = 255)

"Openinc処理画像"
Openinc処理画像

ノイズは減らせているが、特に複雑な漢字に関してはノイズと文字の区別がつきにくいのが欠点。

3. 死海文書

 最後に海外の古文書として有名な死海文書の一部を鮮明化してみる。

"死海文書"
死海文書

上の画像を閾値低めのthreshold=70で2値化して不鮮明箇所を明瞭にする。

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

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

2値化画像をOpening処理して、白点ノイズを除去するがカーネルとして3x3とCROSSの3x3で効果を比較する。

kernel1 = np.ones((3,3),np.uint8)
kernel2= cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
opening1 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel1)
opening2 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel2)
plt.figure(figsize=(20,30))
plt.subplot(1,2,1)
plt.imshow(opening1,cmap='gray',vmin = 0, vmax = 255)
plt.subplot(1,2,2)
plt.imshow(opening2,cmap='gray',vmin = 0, vmax = 255)

左が3x3, 右が十字のカーネルだが一様のカーネルよりも文字の部分が残っているようにみえる。

"Opening処理の比較"
Opening処理の比較

最後にかすれている文字を復元するためClosing処理を十字のカーネルで実行する。(白点ノイズの除去はできない)

kernel= cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
plt.figure(figsize=(10,15))
plt.imshow(closing,cmap='gray',vmin = 0, vmax = 255)

"Closing処理"
Closing処理

4. まとめ

 今回はOpening/Closing処理を用いて、古文書のノイズを除去する例を紹介した。