3. [Python] Spatial Domain
from configs.config import DATA_PATH
from matplotlib import pyplot as plt
import imageio
import numpy as np
import cv2
import os
path = os.path.join(DATA_PATH,"images",'image2.jpg')
img_gray = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
img = cv2.imread(path,cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
1. Blurring
1. Mean Blurring
- 각 픽셀의 중심 좌표를 잡고 kernel size에 맞게 convolution을 진행한다.
- kernel 영역 내에 있는 픽셀의 평균값을 구하고 그 값을 새로운 밝기값으로 할당한다.
- 각 픽셀들이 주변 영역과 값을 공유하기 때문에 경계값이 모호해진다.
def get_kernel(k=int):
return (k,k)
k = 7
kernel_size = get_kernel(k)
img_mean_blur = cv2.blur(img, kernel_size)
fig,ax = plt.subplots(1,2, figsize=(6,4))
ax[0].imshow(img)
ax[0].set_title('Origin')
ax[0].axis('off')
ax[1].imshow(img_mean_blur, cmap='gray')
ax[1].set_title(f'Mean Blur (kernel size : {k}x{k})')
ax[1].axis('off')
plt.tight_layout()
plt.show()
2. Median Blurring
- 각 픽셀의 중심 좌표를 잡고 kernel size에 맞게 convolution을 진행한다.
- kernel 영역 내에 있는 픽셀의 중앙값을 구하고 새로운 값으로 할당한다.
- 중앙값을 사용하기 때문에 이상치 탐지에 용이하다.
- salt and pepper noise같은 경우에 용이하다.
def get_kernel(k=int):
return k
k = 7
kernel_size = get_kernel(k)
img_median_blur = cv2.medianBlur(img, kernel_size)
fig,ax = plt.subplots(1,2,figsize=(12,6))
ax[0].imshow(img)
ax[0].set_title('Origin')
ax[0].axis('off')
ax[1].imshow(img_median_blur)
ax[1].set_title(f'Median Blur (kernel size : {k}x{k})')
ax[1].axis('off')
plt.tight_layout()
plt.show()
3. Gaussian Blurring
- 픽셀 중심으로부터 거리에 따라 가중치가 매겨진다.
- 중심에서 멀어질수록 가중치가 작아지는 3D 정규분포의 형태이다.
- sigmaX가 커지면 편차가 커지므로 평균값 필터처럼 작용한다.
- 중심에 몰려있던 부분이 사이드로 빠진다고 생각하면 된다.
- 다음 포스팅에 쓰겠지만, Frequency Domain에서는 LPF를 담당한다.
- 편차가 커질수록 LPF의 영역이 작아진다.
- High Frequency 통과 대역이 줄어든다.
def get_kernel(k):
return (k,k)
k = 25
kernel_size = get_kernel(k)
img_gaussian_blur = cv2.GaussianBlur(img, kernel_size, sigmaX=0)
fig, ax = plt.subplots(1,2,figsize=(12,6))
ax[0].imshow(img)
ax[0].set_title('Origin')
ax[0].axis('off')
ax[1].imshow(img_gaussian_blur)
ax[1].set_title(f'Gaussian Blur (kernel size : {k}x{k})')
ax[1].axis('off')
plt.tight_layout()
plt.show()
2. Sharpening
- 중심 픽셀과 주변 픽셀의 차이를 키운다.
- 커널에 있는 필터의 합이 1이 되도록 유지한다.
img_blur = cv2.GaussianBlur(img, (15,15), 0)
kernels = {
'Sharpen1': np.array([
[-2,-2,-2],
[-2,17,-2],
[-2,-2,-2]
]),
'Sharpen2': np.array([
[0,-5,0],
[0,11,0],
[0,-5,0]
]),
'Sharpen3': np.array([
[0,0,0],
[-5,11,-5],
[0,0,0]
])
}
fig, ax = plt.subplots(2,2, figsize=(12,12))
ax[0,0].imshow(img_blur)
ax[0,0].set_title('Blurred Image')
ax[0,0].axis('off')
for i, (name, kernel) in enumerate(kernels.items(), start=1):
sharpened_img = cv2.filter2D(img_blur, -1, kernel)
r,c = (i//2,i%2)
ax[r,c].imshow(sharpened_img)
ax[r,c].set_title(name)
ax[r,c].axis('off')
plt.tight_layout()
plt.show()
- shapen2의 경우에는 세로방향의 밝기 차를 키워서 건물의 층수가 부각된다.
- shapen3의 경우에는 가로방향의 밝기 차를 키워서 빌딩 사이 세로 선이 부각된다.
3. Edge Detection
- 이미지의 경계선을 검출하는 커널과 Convolution을 진행해 경계선을 찾는다.
- 커널에 있는 필터의 합이 0이 되도록 조절한다.
path = os.path.join(DATA_PATH,"images",'image3.jpg')
img_gray = cv2.imread(path,cv2.IMREAD_GRAYSCALE)
img = cv2.imread(path,cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
kernels = {
'Sobel X': np.array([
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
]),
'Sobel Y': np.array([
[ 1, 2, 1],
[ 0, 0, 0],
[-1, -2, -1]
]),
'Laplacian': np.array([
[ 0, -1, 0],
[-1, 4, -1],
[ 0, -1, 0]
]),
'Prewitt X': np.array([
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]
]),
'Prewitt Y': np.array([
[ 1, 1, 1],
[ 0, 0, 0],
[-1, -1, -1]
])
}
fig, ax = plt.subplots(2, 3, figsize=(18, 12))
ax[0, 0].imshow(img)
ax[0, 0].set_title('Blurred Image')
ax[0, 0].axis('off')
for i, (name, kernel) in enumerate(kernels.items(), start=1):
edge_img = cv2.filter2D(img, -1, kernel)
r,c = divmod(i,3)
ax[r,c].imshow(edge_img)
ax[r,c].set_title(name)
ax[r,c].axis('off')
plt.tight_layout()
plt.show()
- Sobel X와 Prewiit X를 비교하거나, Sobel Y와 Prewiit Y를 비교하면 Sobel의 퀄리티가 더 좋은 것을 확인할 수 있다.
- 필터를 비교해보면 Prewiit의 경우에는 x 방향 또는 y방향의 DC=0 인 경우가 존재한다.
- Sobel의 경우에는 양방향 DC가 조금은 존재해서 퀄리티가 더 좋다.
- 물론 노이즈적인 측면에서는 나쁠 수 있는데, 디테일한 요소들이 더 잘 포착된다.
- 라플라시안 필터에서 커널의 밝기 차이를 늘렸을 때 변화다.
- 밝기 차이가 늘어날수록 노이즈가 끼는 것을 확인할 수 있다.
댓글