Pythonで画像処理〜モルフォロジー変換〜
こんにちは。Pythonで画像処理シリーズです。
今回はモルフォロジー変換という操作を行って、画像の中の星の数を数えるという事をしました。
前回の記事はこちら↓
kabos.hatenablog.jp
モルフォロジー変換とは
画像の特定の場所を膨張させたり収縮させたりすることでノイズを除去することのようです。膨張や収縮といった操作は、カーネルを作りたたみ込み演算を行うことでできます。
それでは、実際に画像を処理していきます。
準備
まずは画像を読み込んでグレースケールに変換し、正規化します。
img = plt.imread('stars.jpg') img = np.mean(img, 2) img /= np.max(img)
元画像はこんな感じです、月と星が写っています。
次に、閾値を決めて画像をバイナリ化します。
threshold = 0.2
img_thr = img > threshold
モルフォロジー変換
クロージング
それでは変換を行なっていきます。まずはクロージングと呼ばれる、膨張させてから収縮させる操作を行います。これは穴を埋めるようにノイズを除去する作業らしいです。
#カーネルを定める kernel_closing = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) #クロージング img_thr_cl = nd.binary_closing(img_thr, structure=kernel_closing)
オープニング
次に、オープニングというクロージングとは逆の作業を行います。オープニングは、孤立した(余分な)点を除去する作業に対応するようです。
#カーネルを定める kernel_opening = np.array([[0, 0, 0], [0, 1, 1], [0, 0, 0]]) #オープニング img_thr_cl_op = nd.binary_opening(img_thr_cl, structure=kernel_opening)
ファインチューニング
最後に、nd.binary_dilationという関数を使って画質をよくします。
kernel3 = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) img_final = nd.binary_dilation(img_thr_cl_op, structure=kernel3)
ここまでできたら、星がノイズと間違われて消されていないか、またノイズが星として誤認識されていないかを確認してみます。~はビット反転の演算子です。
opts = dict(cmap='gray', vmin=0.) f, [ax1, ax2, ax3] = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(10,5)) ax1.imshow(~img_thr_cl_op * img, vmax=1., **opts) ax2.imshow(img_thr_cl_op, vmax=.1, **opts) ax3.imshow(img, vmax=.1, **opts)
星の個数を数える
最後に星の個数を数えます。
slice_list = nd.find_objects(img_final)
ここで、scipy.ndimage.find_objectsは星がどこにあるかを返す関数です。例えば今回だと最初の返り値は
(slice(24, 30, None), slice(946, 951, None))
なのですが、これはつまり
img_final[24:30, 946:951]
のことを表しています。
そして各星の大きさをまとめて、ヒストグラムで表示します。
#星のリスト star_list = [img[slc] for slc in slice_list] #大きさのリスト mass_list = [np.sum(star) for star in star_list] #小さい順に並べる mass_list_sorted = sorted(mass_list) #一番大きい星(月)を削除 mass_list_sorted.pop(-1) mass_list_without_moon = mass_list_sorted #ヒストグラム plt.hist(mass_list_without_moon, bins=100)
参考記事
モルフォロジー変換 | オブジェクトに対して膨張・収縮を繰り返してノイズを除去する
膨張・収縮・オープニング・クロージング 画像処理ソリューション
scipy.ndimage.binary_dilation — SciPy v0.17.1 Reference Guide
scipy.ndimage.label — SciPy v1.4.1 Reference Guide
scipy.ndimage.find_objects — SciPy v1.4.1 Reference Guide
Built-in Functions — Python 3.8.1 documentation
[Python]Matplotlibでヒストグラムを描画する方法 - Qiita