どうもこんにちは。
コンです。
私は普段から画像解析を行なっているのですが
やっぱり資料などにだす画像は、綺麗にしてから出したいと常々思っております。
(*データ改ざんみたいなものではありませんよ!)
今回はその手段の1つである画像の先鋭化、つまり画像のエッジを強調させる処理を行います。
これには画像の平滑化の知識が必要になってきますので、是非過去の記事も読んでいただけると幸いです。
まえおき
今回も神奈川工科大学さんのwebサイトから標準画像データベースSIDBAを使わせてもらいました。
今回は網目模様が多い BARBARA.bmpを使ってエッジ検出をしていきます。
以前の記事では、フィルターというものを使って、特定の画素とその周辺の領域内の画素をまとめて計算するという空間フィルタリングというもの紹介させていただいておりました。
こちらの知識があると、より今回の記事が面白く感じるかもしれません。
今回も空間フィルタリングを使って画像をはっきりさせる処理を行なっていきたいと思います。
処理の流れ
さっそく画像をくっきりさせるための処理を紹介したいと思います。
処理の流れは以下のようになります。
- 入力画像を平滑化する。
- 入力した画像と平滑した画像の画素の差分を計算する。
- 差分をk倍(任意の数字)して入力画像に足す
どんなことをしているかのイメージ図が下記の通りです。
これの流れを一回一回計算するのは大変ですが、実は先鋭化フィルターというものがあって、画像に空間フィルタリングするだけで、上記の一連の流れを処理することができます。
先鋭化フィルターは以下のようになります。
このフィルターを使って先ほど紹介した、BARBARA.bmpの画像を先鋭化していきたいと思います。
先鋭化フィルターの実装
実装例(最初は失敗しました)
実際に先鋭化フィルターをかけた例が以下になります。
これは左上が元の画像で右上、左下、右下の画像がそれぞれkの値を変えてフィルターをかけた結果です。
思っていた結果と違いますよね。
カラーバーの値を見てもらえれば分かると思うのですが、これは画素が0~255から外れてしまうからになります。
なので補正をかける必要があります。
鮮鋭化フィルタ適用後の0~255から外れた画素値の補正
上記の結果を踏まえて以下の補正をます。
・値が255を超えた画素→255
・負の値となった画素→0
これの補正をした結果が以下のようになります。
kの値が大きくなるにつれて先鋭度が高くなっております、
Pythonコード
以下が実装したコードになります。
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import math
from PIL import Image
import mpl_toolkits.axes_grid1
#横方向のフィルタ
def unsharp_masking(k):
filter = np.array([[(-1)*k/9, (-1)*k/9, (-1)*k/9], [(-1)*k/9, 1+(k*8/9), (-1)*k/9], [(-1)*k/9, (-1)*k/9, (-k)/9]])
return filter
#畳み込み
def convolve2d(image, filter):
shape = (image.shape[0] - filter.shape[0] + 1, image.shape[0] - filter.shape[0] + 1) + filter.shape
strides = image.strides * 2
strided_image = np.lib.stride_tricks.as_strided(image, shape, strides)
return np.einsum('kl,ijkl->ij', filter, strided_image)
im = np.array(Image.open('BARBARA.bmp'))
print('画像の大きさ', im.shape)
parameter_list = [3, 6, 18]
#描画
fig, axes = plt.subplots(2, 2)
count = -1
for i in range(2):
for j in range(2):
if i == 0 and j == 0:
output = im
title = 'original'
else:
output = convolve2d(im, unsharp_masking(parameter_list[count]))
title = 'k = '+str(parameter_list[count])
output = np.where(output>0, output, 0)
output = np.where(output<255, output, 255)
axes[i][j].axis("off")
axes[i][j].set_title(title)
divider = mpl_toolkits.axes_grid1.make_axes_locatable(axes[i][j])
cax = divider.append_axes('right', '5%', pad='3%')
data = axes[i][j].imshow(output, cmap = "gray")
fig.colorbar(data, cax=cax)
count = count + 1
#描画
plt.show()
plt.close()
ポイントとしてはnp.where(output>0, output, 0)を使って、画素値の補正をしているところでしょうか。
np.whereの使い方に関しては以下のサイト様を参考にさせていただきました。
おわりに
ここまで読んでいただき、ありがとうございました。
最初、画素の補正を知らずに
思ったような先鋭化にならずに苦労しておりました。。。
この記事が皆様の役に立てば幸いです。