こんにちは、エンジニアのさもです
今回は画像の膨張、縮小化を実装してみたいと思います。
スポンサーリンク
目次
はじめに
今回対象とする画像は白黒画像です。
膨張化とは、白黒画像の白色(背景でない部分)部分を膨張させ、黒色(背景)部分の面積を小さくすることです。
逆に、縮小化とは、白色部分を縮小させ、黒色部分の面積を大きくすることです。
こんなことをして何がうれしいかというと、膨張と縮小を組み合わせて適応することで、ノイズやゴミの影を消すことが出来ます。
例えば以下のような画像を見てください
白色の部分にゴミのようなノイズがたくさん入っています。
この画像へ膨張・縮小を行ってみると以下のようになります
ふちが少し変になってしまいましたが、ノイズがかなり消えています。
今回はこんなことをしていきます。
膨張
といってもアルゴリズムはとても簡単です。
あるピクセルに注目して、そのピクセルと8近傍が、1ピクセルでも白を含んでいれば、注目ピクセルを白にします。
以下実装例です
from PIL import Image, ImageDraw import numpy as np def dilation(img): w, h = img.size image_pixcels = np.array(list(img.getdata())).reshape(h, w,) filtered_pixcels = np.zeros((h, w,)) for x in range(w): for y in range(h): x1 = max(0, x - 1) x2 = min(x + 1, w -1) y1 = max(0, y - 1) y2 = min(y + 1, h - 1) if (image_pixcels[y1:y2 + 1, x1:x2 + 1] == 255).any(): filtered_pixcels[y][x] = 255 else: filtered_pixcels[y][x] = 0 filtered_img = Image.new('L', (w, h)) filtered_img.putdata(filtered_pixcels.reshape(w * h, 1)) return filtered_img filename = "e.png" img = Image.open("../images/" + filename).convert("L") img = dilation(img) img.save("./dil_" + filename)
上で表示したノイズ入りの「絵」の画像へ適応すると以下のようになります
まだ少しノイズが残っていますね。
もう一度適応するとこんな感じです
ノイズは消えました!
絵の部分がかなり太くなったので戻すのと、今度は白色のノイズを消すために、縮小を行います
縮小
膨張の全く逆になります
コードは以下のようになります
from PIL import Image, ImageDraw import numpy as np def erosion(img): w, h = img.size image_pixcels = np.array(list(img.getdata())).reshape(h, w, 1) filtered_pixcels = np.zeros((h, w,)) for x in range(w): for y in range(h): x1 = max(0, x - 1) x2 = min(x + 1, w -1) y1 = max(0, y - 1) y2 = min(y + 1, h - 1) if (image_pixcels[y1:y2 + 1, x1:x2 + 1] == 0).any(): filtered_pixcels[y][x] = 0 else: filtered_pixcels[y][x] = 255 filtered_img = Image.new('L', (w, h)) filtered_img.putdata(filtered_pixcels.reshape(w * h, 1)) return filtered_img filename = "e.png" img = Image.open("../images/" + filename).convert("L") img = erosion(img) img.save("./dil_" + filename)
違う部分は、メソッド名と、以下のところです
if (image_pixcels[y1:y2 + 1, x1:x2 + 1] == 255).any(): filtered_pixcels[y][x] = 255 else: filtered_pixcels[y][x] = 0
ちょうど255と0が入れ替わっています。
dilation(img)の引数に0か255を渡すようにすればメソッドは1つにまとめることも出来ますね。
膨張2回のあとに縮小を2回行うと以下のようになります
適応回数を変えてみる
膨張4回、縮小4回
すっかりきれいになりました
縮小2回、膨張2回
・・・。順番が逆になるとだめなんですね
膨張、縮小を交互に4回繰り返す
変わってないですね。
最後に
最後までお読みいただきありがとうございました。
アルゴリズムは凄く簡単ですが、思っていた以上に綺麗になって面白かったです。
読者登録をしていただけると、ブログを続ける励みになりますので、よろしくお願いします。