본문 바로가기
Machine Learning/Image Processing

3. [Python] Spatial Domain

by 베짱이28호 2022. 7. 13.

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가 조금은 존재해서 퀄리티가 더 좋다.
  • 물론 노이즈적인 측면에서는 나쁠 수 있는데, 디테일한 요소들이 더 잘 포착된다.

  • 라플라시안 필터에서 커널의 밝기 차이를 늘렸을 때 변화다.
  • 밝기 차이가 늘어날수록 노이즈가 끼는 것을 확인할 수 있다.

'Machine Learning > Image Processing' 카테고리의 다른 글

8. [Python] Morpological Transfomation  (0) 2022.08.15
7. [Python] Thresholding  (0) 2022.08.08
6. [Python] Image Compression  (0) 2022.08.05
5. [Python] Histogram Modeling  (0) 2022.07.28
4. [Python] Frequency Domain  (0) 2022.07.22
2. [Python] Color Channel  (0) 2022.07.13
1. Color Space  (0) 2022.07.07

댓글