2

More than 1 year has passed since last update.

# 【画像処理】Numpyで平滑化フィルター

Last updated at Posted at 2021-12-30

Numpyで画像の平滑化フィルターを実装してみます。

まず、画像の読み込みを行います。

original_image = plt.imread(image_name)
if np.issubdtype(original_image.dtype, np.integer):
original_image = original_image / np.iinfo(original_image.dtype).max
plt.imshow(original_image)


【画像処理】Numpyで空間フィルタリング(畳み込み演算) - Qiita

def _convolve2d(image, kernel):
shape = (image.shape[0] - kernel.shape[0] + 1, image.shape[1] - kernel.shape[1] + 1) + kernel.shape
strides = image.strides * 2
strided_image = np.lib.stride_tricks.as_strided(image, shape, strides)
return np.einsum('kl,ijkl->ij', kernel, strided_image)

def _convolve2d_multichannel(image, kernel):
convolved_image = np.empty((image.shape[0] - kernel.shape[0] + 1, image.shape[1] - kernel.shape[1] + 1, image.shape[2]))
for i in range(image.shape[2]):
convolved_image[:,:,i] = _convolve2d(image[:,:,i], kernel)
return convolved_image

return np.pad(image, ((int(kernel_shape[0] / 2),), (int(kernel_shape[1] / 2),)), boundary)

return  np.pad(image, ((int(kernel_shape[0] / 2),), (int(kernel_shape[1] / 2),), (0,)), boundary)

def convolve2d(image, kernel, boundary='edge'):
if image.ndim == 2:
pad_image = _pad_singlechannel_image(image, kernel.shape, boundary) if boundary is not None else image
elif image.ndim == 3:
pad_image = _pad_multichannel_image(image, kernel.shape, boundary) if boundary is not None else image


## 平均化フィルター

\begin{bmatrix}
\frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\
\frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\
\frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\
\end{bmatrix}

\begin{bmatrix}
\frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} \\
\frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} \\
\frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} \\
\frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} \\
\frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} & \frac{1}{25} \\
\end{bmatrix}


def create_averaging_kernel(size = (5, 5)):
return np.full(size, 1 / (size[0] * size[1]))


パラメータを変えて平均化フィルター適用してみます。

averaging_kernel_3x3 = create_averaging_kernel(size=(3, 3))
averaging_image_3x3 = convolve2d(original_image, averaging_kernel_3x3)
plt.imshow(averaging_image_3x3)


averaging_kernel_5x5 = create_averaging_kernel()
averaging_image_5x5 = convolve2d(original_image, averaging_kernel_5x5)
plt.imshow(averaging_image_5x5)


averaging_kernel_11x11 = create_averaging_kernel(size=(11, 11))
averaging_image_11x11 = convolve2d(original_image, averaging_kernel_11x11)
plt.imshow(averaging_image_11x11)


averaging_kernel_17x1 = create_averaging_kernel(size=(17, 1))
averaging_image_17x1 = convolve2d(original_image, averaging_kernel_17x1)
plt.imshow(averaging_image_17x1)


## ガウシアンフィルター

f(x, y) = \frac{1}{2\pi\sigma^2}exp(-\frac{x^2+y^2}{2\sigma^2})


ガウシアンフィルターのカーネルを作成する関数は次のようになります。重みの合計が1になるように最後に正規化しています。

def create_gaussian_kernel(size=(5, 5), sigma=1):
center = ((size[0] - 1) / 2, (size[1] - 1) / 2)
sigma2 = 2 * sigma * sigma
kernel = np.fromfunction(lambda y, x: np.exp(-((x - center[1]) ** 2 + (y - center[0]) ** 2) / sigma2), size)
kernel = kernel / np.sum(kernel)
return kernel


パラメータを変えてガウシアンフィルターを適用してみます。

gaussian_kernel1 = create_gaussian_kernel()
gaussian_image1 = convolve2d(original_image, gaussian_kernel1)
plt.imshow(gaussian_image1)


gaussian_kernel2 = create_gaussian_kernel(size=(9, 9), sigma=3)
gaussian_image2 = convolve2d(original_image, gaussian_kernel2)
plt.imshow(gaussian_image2)


gaussian_kernel3 = create_gaussian_kernel(size=(15, 15), sigma=5)
gaussian_image3 = convolve2d(original_image, gaussian_kernel3)
plt.imshow(gaussian_image3)


Register as a new user and use Qiita more conveniently

1. You get articles that match your needs
2. You can efficiently read back useful information
3. You can use dark theme
What you can do with signing up
2