webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

python画像処理入門5 アンシャープマスキング

f:id:s-uotani-zetakansu:20170822124329j:plain

こんにちは、エンジニアのさもです

今回はぼやけた画像の輪郭をくっきりさせる、アンシャープマスキングを実装したいと思います。

スポンサーリンク

目次

はじめに

前回まで頻繁にぼかし処理を使ってきました。

例えば、こちらの新幹線の写真

f:id:s-uotani-zetakansu:20170828165324j:plain

この写真へぼかし処理を行うと、以下のようになります。 f:id:s-uotani-zetakansu:20170828165334j:plain

このぼやけた画像へアンシャープマスキングをかけてみると、以下のようになります。

f:id:s-uotani-zetakansu:20170901135517j:plain

ほんの少し輪郭がはっきりしたでしょうか。

それでは、実装をしていきます。

スポンサーリンク

実装

アンシャープマスキングは、画像の各画素を、その画素と周辺画素にフィルターをかけた値で置き換えます。

  • フィルター
{\displaystyle
  \begin{pmatrix}
    Ar & Ar & Ar\\\
    Ar & Cr & Ar\\\
    Ar & Ar & Ar
  \end{pmatrix}\\\
  Ar=-\frac{k}{9}, Cr=1 + \frac{8 * k}{9}
}

kはアンシャープマスキングの効果の強さで、大きいほど効果が大きくなります。

from PIL import Image, ImageDraw
import numpy as np

# アンシャープフィルタをかけた画像を返す
def unsharp_filter(img, w, h, k):
  # STEP1
  pixcels = np.array([[img.getpixel((x,y)) for x in range(w)] for y in range(h)])
  filtered_img = Image.new('RGB', (w, h))
  cr = 1 + 8 * k / 9
  ar = - k / 9

  # STEP2
  for x in range(w):
    for y in range(h):
      if x == 0 or x == w - 1 or y == 0 or y == h - 1:
        # STEP2-1
        filtered_pixcel = pixcels[y][x]
      else:
        # STEP2-2
        filtered_pixcel =   ar * pixcels[y - 1][x - 1] + ar * pixcels[y - 1][x] + ar * pixcels[y - 1][x + 1]\
                          + ar * pixcels[y][x - 1]     + cr * pixcels[y][x]     + ar * pixcels[y][x - 1]\
                          + ar * pixcels[y + 1][x - 1] + ar * pixcels[y + 1][x] + ar * pixcels[y + 1][x + 1]
      # STEP2-3
      filtered_img.putpixel((x,y), (tuple(list(map(int, filtered_pixcel)))))
  return filtered_img

# 画像ファイルの読み込み
filename = "sin.jpg"
img = Image.open("../images/" + filename).convert("RGB")
w, h = img.size

# 画像へアンシャープマスキングをかける
unsharp_img = unsharp_filter(img, w, h, 1)
unsharp_img.save("./unsharp_" + filename)

今回はコードが短いので一気に書きました。

  • STEP1
    • 変数の定義です
    • cr, ar は上の説明で登場した Cr Arです
  • STEP2
    • STEP2-1
      • 端っこの画素は正方形のフィルタがかけられないので、そのままの値を表示します
    • STEP2-2
      • 上のフィルタを適応しています
    • STEP2-3
      • フィルタをかけたあとの値は整数ではないので、整数に変換して画素を画像へ置いていきます

実行

上記コードをunsharp.pyという名前で保存します。

適当な画像を用意しておき、以下を実行します。

python unsharp.py

ぼやけた画像を作って試したいという方は、以下の記事中の「平滑化フィルタを事前に通しておく」を参考にしてみてください

www.uosansatox.biz

よりシャープに

kとして10を選んだときの実行結果がこちらです。

f:id:s-uotani-zetakansu:20170901150025j:plain

くっきりしましたね。

最後に

今回でシリーズ?5回目になりました!

すこしpythonに慣れてきたかなという感じです。

これまでの画像処理では2重のfor文を使ってきましたが、これだと遅いので、高速化する方法の記事も書きたいと思います

読者登録いただければはげみになりますので、よろしくお願いします。