Loading [MathJax]/extensions/tex2jax.js

[SciPy] 28. パーセンタイルフィルタによる画像の平滑化(ndimage.percentile_filter)

matplotlib

はじめに

scipyのndimageのpercentile_filterを使って、画像を任意のパーセンタイル点で平滑化する方法について説明する。

コード&解説

モジュールのインポート

import matplotlib.pyplot as plt
import numpy as np
from skimage.color import rgb2gray
import scipy.ndimage as ndi
import seaborn_image as isns
from skimage.morphology import (square, rectangle, diamond, disk)
plt.rcParams['figure.dpi'] = 150
isns.set_context("paper")

バージョン

#version
import matplotlib,skimage,scipy
print(skimage.__version__)
print(matplotlib.__version__)
print(scipy.__version__)
print(np.__version__)
print(isns.__version__)
0.19.2
3.5.1
1.8.0
1.22.3
0.4.4

画像の読み込み

#load sample dataset
img = plt.imread("sumiremaru.jpg")

サボテン すみれ丸の画像を、plt.imread()で読み込む。

グレースケール変換

img_g = rgb2gray(img)

skimage.color の rgb2grayでRGB画像をグレースケール画像に変換する。

変換した画像をcmap=”bone”で表示すると以下のようになる。

#show
fig,ax=plt.subplots()
ax.imshow(img_g,cmap="bone")
ax.axis("off")
plt.savefig("perc_1.jpg",dpi=200)
plt.show()

パーセンタイルフィルタ

#percentile_filter
result = ndi.percentile_filter(img_g,10,size=10)
fig,ax=plt.subplots(1,2,figsize=(8,4))
ax=ax.ravel()
ax[0].imshow(img_g,cmap="bone",vmin=0,vmax=1)
im=ax[1].imshow(result,cmap="bone",vmin=0,vmax=1)
for a in ax:
a.axis("off")
ax[0].set_title("Original")
ax[1].set_title("percentile_filter")
plt.savefig("perc_2.jpg",dpi=150)
plt.show()

パーセンタイルフィルタのパーセンタイルを10、サイズを10として処理すると、以下のような画像が得られる。高輝度部分である棘が目立たなくなり、棘なしサボテンのようになっていることがわかる。

percentileを変化させた場合

#percentile_filter size
percs = []
percens=[10,20,30,40]
for i in percens:
result = ndi.percentile_filter(img_g,percentile=i, size=10)
percs.append(result)
fig,ax=plt.subplots(2,2,figsize=(6,6))
ax=ax.ravel()
[ax[i].imshow(percs[i],cmap="bone",vmin=0,vmax=1) for i in range(len(percens))]
[ax[i].set_title(str(percens[i])) for i in range(len(percens))]
for a in ax:
a.axis("off")
plt.suptitle('percentile_filter percentile=')
plt.savefig("perc_3.jpg",dpi=140)
plt.show()

パーセンタイルを大きくすることで、画像がより鮮明になっていく様子がみてとれる。

sizeを変化させた場合

#percentile_filter size
percs = []
sizes=[10,20,30,40]
for i in sizes:
result = ndi.percentile_filter(img_g,40, size=i)
percs.append(result)
fig,ax=plt.subplots(2,2,figsize=(6,6))
ax=ax.ravel()
[ax[i].imshow(percs[i],cmap="bone",vmin=0,vmax=1) for i in range(len(percs))]
[ax[i].set_title(str(sizes[i])) for i in range(len(percs))]
for a in ax:
a.axis("off")
plt.suptitle('percentile_filter size=')
plt.savefig("perc_4.jpg",dpi=140)
plt.show()

サイズを大きくすることで、画像がボケていく。

footprintを変化させた場合

#percentile_filter footprint
percs = []
fps=[square(20),rectangle(10, 50),diamond(15),disk(15)]
titles=["square(20)","rectangle(10, 50)","diamond(15)","disk(15)"]
for i in range(len(fps)):
result = ndi.percentile_filter(img_g,10, footprint=fps[i])
percs.append(result)
fig,ax=plt.subplots(2,2,figsize=(6,6))
ax=ax.ravel()
[ax[i].imshow(percs[i],cmap="bone",vmin=0,vmax=1) for i in range(len(percs))]
[ax[i].set_title(str(titles[i])) for i in range(len(percs))]
for a in ax:
a.axis("off")
plt.suptitle('percentile_filter footprint=')
plt.savefig("perc_5.jpg",dpi=140)
plt.show()

footprintでフィルタをかける範囲を変更できる。ここでは、skimageのmorphologyを使用して、フィルタのかかる範囲を設定した。結果は以下のようになる。

Generate footprints (structuring elements) — skimage 0.25.2 documentation
コードをダウンロード(.pyファイル)

コードをダウンロード(.ipynbファイル)

参考

percentile_filter — SciPy v1.15.2 Manual

コメント