본문 바로가기
Programming/Computer Vision

[OpenCV] 이미지 blurring (smoothing) 처리

by a voyager 2020. 10. 31.
728x90
반응형

[OpenCV] 이미지 blurring (smoothing) 처리

이미지 블러링은 이미지 처리나 컴퓨터 비전에 사용되는 기본적인 이미지 변형 방법이다. 이것은 이미지에 필터의 합성(2D convolution)을 통해 이뤄진다. 즉, 원본 이미지 보다 크기가 작은 필터를 이미지 전체에 걸쳐 이동하며 원본 이미지의 픽셀값을 바꾼다. 블러링은 노이즈를 제거하는데 유용한 방법이며, 이미지를 좀 더 매끈하게(smoothing) 하게 보이도록 만드는 효과를 낸다. 

 

이미지 상에서 픽셀의 값은 공간적으로 느리게 변한다. 따라서 픽셀간의 상관관계 (correlation)가 크다. 이를 slow spatial variation이라고 한다. 이것이 이미지에서 시그널(signal)에 해당한다. 반면, 노이즈는 픽셀간의 상관관계가 없다. 즉, 노이즈는 이미지에서 어떤 패턴도 나타내지 않는다.

 

이 노이즈를 제거하는 효과적인 방법은 바로 평균을 내는 것이다. 노이즈는 서로 상관관계가 아주 약하기 때문에 평균을 내면 0으로 수렴하게 된다. 이를 통해 이미지의 시그널을 상대적으로 부각시킬 수 있다. 

 

대부분의 이미지 블러링 알고리즘은 픽셀값의 평균을 낸다. 평균을 내는 방식이 단순한 산술 평균이냐 아니면 가중치를 고려한 평균이냐에 따라 방법이 다양하게 나뉜다. 

 

이 포스팅에서는 openCV에서 제공하는 4가지 방법의 블러링을 해보도록 하겠다. 

 

1. Averaging 

2. Gaussian Blurring 

3. Median Blurring

4. Bilateral Filtering 


방법을 소개하기에 앞에서 blurring 처리할 이미지 하나를 읽어 보겠다. 사용할 이미지는 유명한 lena이고 png포멧을 OpenCV의 imread를 사용해 읽는다. 4번째 줄에서 그림이 있는 폴더는 각자 환경에 맞게 바꿔주면 된다. 

import cv2
import matplotlib.pyplot as plt

image = cv2.imread('../images/lena.png')

def plotFigures(original_image, blurred_image):
    plt.figure(figsize=(10,10))
    plt.subplot(121)
    plt.imshow(cv2.cvtColor(original_image,cv2.COLOR_BGR2RGB))
    plt.title('Original')
    plt.xticks([]), plt.yticks([])

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(blurred_image,cv2.COLOR_BGR2RGB))
    plt.title('Blurred')
    plt.xticks([]), plt.yticks([])
    plt.show()

 

위 코드의 6줄~17줄까지는 이미지 처리 전후를 비교하기 위해 옆으로 나란히 결과를 보여주는 함수이다. matplotlib를 사용하면 jupyter notebook내에서 팝업없이 결과를 확인 할 수 있다.

 

plt.subplot를 사용했고, 121 즉, 1x2 격자의 1번째 (1,1)에는 원본 그림을 출력하고, 122 (1,2)에는 blurred 이미지를 출력한다. 두 이미지를 나란히 놓고 비교할 수 있다.  

 

 

1. Averaging (필터 박스내의 평균을 이용한 방법)

이 방법은 간단하게 필터 박스안의 픽셀들의 값을 평균을 내는 것이다. 이 평균값으로 현재 픽셀의 값을 대체한다. 아래 코드에서 (5,5)는 필터 박스의 사이즈이고 픽셀수의 단위를 갖는다. 

blur1 = cv2.blur(image,(5,5))
plotFigures(image,blur1)

 

2. Gaussian Blur (Gaussian smooth)

2차원 가우시안 분포를 이용해 블러링을 한다. 즉, 박스내에 픽셀값을 가우시안 분포의 가중치로 평균을 내어 현재 픽셀값을 업데이트 해주는 방법이다. 이 가중치는 중심 픽셀에서 멀어질수록 급격하게 줄어든다. 따라서 중심 픽셀의 값은 그 바로 주변의 픽셀들의 영향을 가장 크게 받게 된다. 

 

아래 코드에서 15,15는 커널사이즈이고, 표준편차는 0으로 주었다. 즉, 현재 픽셀에만 가중치가 곱해지게 된다. OpenCV의 메뉴얼에 의하면 두 가중치 sigmaX 와 sigmaY중 한 값을 0으로 주면, 두 값 모두 0으로 자동으로 설정된다고 한다. 따라서 아래와 같이 한 값만 0으로 설정하면 양 값 모두 0으로 세팅된다는 것이다. 

 

blur2 = cv2.GaussianBlur(image,(15,15),0)
plotFigures(image,blur2)

 

 

3. Median Blurring (중간값을 이용한 블러링) 

현재 픽셀값을 박스내의 픽셀 값들의 중간값으로 대체한다. 과정은 박스내 픽셀값들을 크기순으로 나열하여 중간값을 고르고 이것을 현재 픽셀값으로 주는 것이다. 아래 코드에서 박스 사이즈를 7로 주었다. 

 

median = cv2.medianBlur(image,7)
plotFigures(image,median)

 

 

4. Bilateral filter 

이 방법은 위 세 방법과 마찬가지로 노이즈를 제거하지만 이미지 내의 edge는 살리는 방식으로 진행된다. 이런 추가적인 기능으로 인해 이미지나 필터의 사이즈가 커지면 처리가 다소 느려진다는 단점이 있지만, 이미지의 윤곽은 샤프하게 살려두고 노이즈를 제거하는 데에는 아주 효과적이다. 실제 이미지 처리에서 가장 많이 사용되는 방법이기도 하다. 

 

이 bilateral filter이 다른 방법들과 차별점은 윤곽 (edge)는 살려둔다는 것이다. 이것을 위해서 similarity function (유사성 함수)를 도입한다. 이 함수는 현재 픽셀의 값이 주변 픽셀과 비슷한 값을 가지면 1 에 가까운 값을, 차이가 큰 값의 픽셀에 대해서는 0에 가까운 값을 주어 필터에 가중치를 부여한다. 

 

bilateral = cv2.bilateralFilter(image,10,75,75)
plotFigures(image,bilateral)

 

cv2.bilateralFilter(image, d, sigmaColor, sigmaSpace)

- d: 필터링을 하는데 사용될 픽셀의 범위를 정해주는 직경이다

- sigmaColorsigmaSpace는 이미지 내의 서로 영향을 받는 픽셀의 범위
  : 값이 클 수록 멀리있는 픽셀의 영향도 커져 이미지 블러링의 효과를 높이게 된다. 

 

 

728x90
반응형

댓글