バックナンバーはこちら。
https://www.simulationroom999.com/blog/compare-matlabpythonscilabjulia3-backnumber/
はじめに
Sobelフィルタの実験。
今回はPython(NumPy)で実施。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
Sobelフィルタ【再掲】
太郎くん
まずは、Sobelフィルタと実験手順を再掲。
Sobelフィルタ
\(
K_{sbl}=
\begin{bmatrix}
1 \\
2 \\
1 \\
\end{bmatrix}
\begin{bmatrix}
-1 & 0 & 1
\end{bmatrix}=
\begin{bmatrix}
-1 & 0 & 1 \\
-2 & 0 & 2 \\
-1 & 0 & 1 \\
\end{bmatrix}
\)
実験手順
- 画像の読み込み
- ガウシアンフィルタ用のカーネル用意
- Sobelフィルタ用のカーネル用意
- SDTVグレースケール化実施
- ガウシアンフィルタ実施
- Sobelフィルタ実施
- 各Sobelフィルタの結果の合成
- 画像の書き出し
フクさん
これをPython(NumPy)で実現する。
Pythonコード
フクさん
Pythonコードはこうなる。
import numpy as np
import cv2
# 畳み込み演算
def convolution2d(img, kernel):
m, n = kernel.shape # カーネルサイズ取得
# カーネル中心からみた幅
dy = int((m-1)/2) # カーネル上下幅
dx = int((n-1)/2) # カーネル左右幅
h, w = img.shape # イメージサイズ
out = np.zeros((h, w)) # 出力用イメージ
# 畳み込み
for y in range(dy, h - dy):
for x in range(dx, w - dx):
out[y][x] = np.sum(img[y-dy:y+dy+1, x-dx:x+dx+1]*kernel)
return out
def sobel_test():
# 入力画像の読み込み
img = cv2.imread("dog.jpg")
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]
# ガウシアンフィルタ用のkernel
kernel_gauss = np.array([[1/16, 2/16, 1/16],
[2/16, 4/16, 2/16],
[1/16, 2/16, 1/16]])
# Sobelフィルタ用のKernel
kernel_sx = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
kernel_sy = kernel_sx.T
# SDTVグレースケール
gray_sdtv = np.array(0.2990 * r + 0.5870 * g + 0.1140 * b, dtype='uint8')
# ガウシアンフィルタ
img_g = convolution2d(gray_sdtv, kernel_gauss)
# Sobelフィルタ
img_sx = convolution2d(img_g, kernel_sx)
img_sy = convolution2d(img_g, kernel_sy)
cv2.imwrite("dog_sx.jpg",np.abs(img_sx))
cv2.imwrite("dog_sy.jpg",np.abs(img_sy))
# 合成
img_s = np.sqrt( img_sx**2 + img_sy**2 )
cv2.imwrite("dog_s.jpg",img_s)
return
sobel_test()
処理結果
フクさん
処理結果は以下。
考察
太郎くん
結果はMATLABと一緒だね。
フクさん
特筆するほどの話もほぼ無いな。
油断するとnp.arrayがuint8じゃなくてdoubleになったりするから、
そこらへんが注意点だが、これはSobelフィルタに限った話ではない。
太郎くん
そうか。
imwriteする段階で、uint8になってないとまずいのか。
まとめ
フクさん
まとめだよ。
- Python(NumPy)でSobelフィルタを実施。
- MATLABと同じ結果が得られた。
- np.arrayがuint8になっている状態を維持する必要がある。
- imwrite時にuint8になっていないと期待した出力にならない。
バックナンバーはこちら。
コメント