728x90

스무딩을 왜 했었더라..

 

영상 잡음 노이즈 제거용으로 스무딩 처리를 한다고 하더라

 

가장 많이 사용되는게 가우시안 스무딩, 블러링이라고도 한다.

 

 

 

 

그런데 지금까지 내가 구현한 코드가 잘못된 부분이 있었다.

 

평균 스무딩, 평균 임계화를 다루면서

 

내가 패딩 처리를 제대로 하지 않은것도 있엇고

 

사실 커널, 마스크를 만들어 곱 연산 후 나누어주었어야 했는데, 그냥 평균으로 내버린 점이 그렇다.

 

일단 평균 임계/스무딩까지는 그렇게 해도 괜찬았는데

 

 

 

가우시안 스무딩을 구현하면서가 문제가 되더라..

 

ref : youngest-programming.tistory.com/235?category=877383

 

 

그러다 한 학생이 구현한 내용들을 봤는데

 

보기 좋고, 이해하기도 쉽고 정말 잘 만들었더라.

 

 

 

나는 대충 돌아가게만 만들어놓고 내버리거나 하는 경우가

 

아무튼 이분 내용 참고해서 간단하게 나마 구현할 수 있었다.

 

 

 

 

 

 

 

가우시안 커널, 마스크를 어떻게 구현하나 막막 했는데 많은 참고가 되었다.

 

 

def gaussian_kernel(k_size, sigma):
    """
    param
    k_size : Gaussian kernel size
    sigma : gaussian kernel standard variance
    
    return
    filter = k_size * k_size gaussian filter
    """
    size = k_size//2
    y, x = np.ogrid[-size:size+1, -size:size+1]
    #ref : https://en.wikipedia.org/wiki/Gaussian_filter
    filter = 1/(2*np.pi * (sigma**2)) * np.exp(-1 *(x**2 + y**2) /(2*(sigma**2)))
    sum = filter.sum()
    filter /= sum
    return filter

 

 

 

 

 

 

내가 이전에 만든 코드에는 인덱싱 최대, 최소 범위를 지정해서 하다보니

 

이런 마스크와 이미지 부분을 컨벌루션 시킬수가 없었다.

 

이 문제를 패딩 이미지를 만들어서 해결할수 있었다.

 

def padding(img, k_size):
    """
    param
    img : padding img
    k_size : kernel size
    
    return 
    res : padded img
    """
    pad_size = k_size//2
    rows, cols, ch = img.shape
    
    res = np.zeros((rows + (2*pad_size), cols+(2*pad_size), ch), dtype=np.float)
    
    if pad_size == 0:
        res = img.copy()
    else:
        res[pad_size:-pad_size, pad_size:-pad_size] = img.copy()
    return res
    

 

 

 

 

인덱싱은 기존 이미지 사이즈 대로 인덱싱대로 되지만

 

곱 연산은 패딩 이미지와 커널을 중심으로 수행된다.

 

커널을 기존 이미지에 적용하여 이미지 밖으로 넘어가는 문제는 제거됬다.

 

def gaussian_filtering(img, k_size=3,sigma=1):
    """
    param
    img : input img
    k_size : kernel size
    sigma : standard deviation
    
    return
    filtered_img : gaussian filtered image returned
    """
    rows, cols, channels = img.shape
    filter = gaussian_kernel(k_size, sigma)
    pad_img = padding(img,k_size)
    filtered_img = np.zeros((rows, cols, channels), dtype=np.float32)
    
    for ch in range(0, channels):
        for i in range(rows):
            for j in range(cols):
                filtered_img[i, j, ch] = np.sum(filter * pad_img[i:i+k_size, j:j+k_size, ch])

    return filtered_img.astype(np.uint8)

 

 

 

 

 

 

 

 

 

마지막으로 시각화

 

커널 사이즈가 작을때에는 sigma를 크게주어도 큰 차이가 없지만

 

사이즈가 클땐 sigma 값에 따라 블러링 정도가 강해지는걸 볼수 있다.

plt.figure(figsize=(12,12))
row = 3
col = 3

for i in range(0, 3):
    for j in range(0,3):
        plt.subplot(3, 3, 1+ i*3 + j)
        k_size = 3+2*i
        sigma = 3*j + 1
        res = gaussian_filtering(img, k_size = k_size, sigma = sigma)
        title = "k size : " + str(k_size) + ",  sigma = " + str(sigma)
        plt.title(title)
        plt.imshow(res)

 

 

 

 

 

 

300x250

+ Recent posts