はじめに
scipyのndimageのpercentile_filterを使って、画像を任意のパーセンタイル点で平滑化する方法について説明する。
コード&解説
モジュールのインポート
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")
バージョン
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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
画像の読み込み
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#load sample dataset
img = plt.imread("sumiremaru.jpg")
サボテン すみれ丸の画像を、plt.imread()で読み込む。
グレースケール変換
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
img_g = rgb2gray(img)
skimage.color の rgb2grayでRGB画像をグレースケール画像に変換する。
変換した画像をcmap=”bone”で表示すると以下のようになる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#show
fig,ax=plt.subplots()
ax.imshow(img_g,cmap="bone")
ax.axis("off")
plt.savefig("perc_1.jpg",dpi=200)
plt.show()

パーセンタイルフィルタ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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を変化させた場合
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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を変化させた場合
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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を変化させた場合
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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

参考
percentile_filter — SciPy v1.15.2 Manual
コメント