본문 바로가기
OpenCV

OpenCV - Convolution & Blurring

by winston1214 2020. 10. 28.
반응형

Convolution이란 수학적 연산을 각 화소에 적용하고 그 값을 변화시키는 것이다.

여기서 말한 수학적 연산을 하기 위해 kernel 이라고 불리우는 또 다른 행렬을 사용한다.  kernel은 입력 영상에 비해 아주 작은 행렬이다. 이러한 커널을 영상의 각 화소에 대해 커널의 중심을 처리 대상의 화소 위에 올려놓는다. 그리고 커널 행렬의 각 값과 대응되는 화소의 값을 각각 곱하여 모두 더한다. 이 더한 값이 현재 화소의 위치에 대치될 출력 영상의 해당 값이 된다.

Blurring 이란 이웃화소들을 평균하는 것을 말한다. (= low pass filter) 이는 저주파를 허용하고 고주파를 차단하는 것이다.  여기서 저주파란 화소값의 변화가 작은 것을 말하고 고주파는 화소의 변화가 큰 것을 말한다. 이러한 논리로 저주파 통과 필터 즉 Blurring은 에지를 부드럽게 하려 하는 것이다. 이러한 Blurring의 간단한 예로 normalization이 있다.

이미지에 Normalization을 적용한 간단한 예제이다. 일단 코드를 보기 전에 모듈을 불러오고 간단한 기본 함수를 정의하고 시각화 한다.

import cv2
import numpy as np
import matplotlib.pyplot as plt
def show_img(img):    
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.show()

 

# low pass filter
img = cv2.imread('img/input.jpg')
rows,cols = img.shape[:2]
kernel_identity = np.array([[0,0,0],[0,1,0],[0,0,0]])
kernel_3x3 = np.ones((3,3),np.float32)/9.0 # divide by 9 to normalize the kernel
kernel_5x5 = np.ones((5,5),np.float32)/25.0 # divide by 25 to normalize the kernel
show_img(img) # original

output = cv2.filter2D(img,-1,kernel_identity)
plt.title('identity filter')
show_img(output) # identity filter

output = cv2.filter2D(img,-1,kernel_3x3)
plt.title('3x3 filter')
show_img(output) # 3x3 filter

output = cv2.filter2D(img,-1,kernel_5x5)
plt.title('5x5 filter')
show_img(output) # 5x5 filter

원본
kernel identity
3x3 filter
5x5 filter

그림을 연속적으로 자세히 보면 알 수 있다.(subplot 하기 귀찮아서 하나하나 했습니다 죄송합니다)

먼저 Identity filter를 보면 픽셀을 중심으로 3*3의 필터를 생성한 후 가운데의 숫자만 1인 kernel을 적용한 것이다. 아주 약간의 흐림을 볼 수 있을 것이다. 정확한 원리를 파악하기 위해선 cv2.filter2D에 대해 알아볼 필요성이 있다.

간단하게 파라미터에서 말하자면 cv2.filter2D(img,dst,kernel_matrix) 이다. dst = -1로 줬으므로 기존의 img와 동일한 사이즈를 반환하게 하는 것이다.

cv2 filter2d

docs.opencv.org/master/d4/d86/group__imgproc__filter.html

 

OpenCV: Image Filtering

void cv::bilateralFilter (InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)  Applies the bilateral filter to an image. More...   void cv::blur (InputArray src, OutputArray dst, Size ksize, Poin

docs.opencv.org

opencv 공식 홈페이지에 나온 적용 방법이다. 필터가 이미지의 각 픽셀을 순회하면서 해당 픽셀 주위의 픽셀들와 곱해져 더해지는 것이다. 

따라서 3*3 [[0,0,0],[0,1,0],[0,0,0]] kernel 연산을 각 픽세를 순회하면서 계산되는 것이다.. 아마 큰 차이가 없어서 의문이 들겠지만 다음 filter를 보면 큰 차이를 느낄 수 있을 것이다.

다음으로 3x3 filter를 보자. 확실히 흐려짐이 눈에 보인다. 이는 3x3 (모두 1) 행렬에 9로 나누어 정규화를 해준 것이다. 따라서 이미지의 화소 값이 1/9가 되어 흐려짐을 볼 수 있다.(이미지 색 행렬 · kernel)

5x5 filter도 마찬가지의 방법으로 정규화를 시켜주는데 3x3보다 더 넓은 영역을 해줘서 더욱 흐릿하게 보여지는 것이다.

Blurring으로 얻을 수 있는 효과는 직관적으로 보이는 것 처럼 흐릿하게 보여지게 할 수 있고 이를 이미지를 부드럽게 만든다고 표현한다.

이러한 Blurring의 방법을 빠르게 적용하는 함수를 opencv에선 구현을 해놨다.

output = cv2.blur(img,(3,3)) # same kerenl_3x3
show_img(output) 

cv2.blur를 사용하면 원하는 커널의 크기만큼의 블러링 효과를 줄 수 있다. 여러 blurring 기법은 다음 글에서 작성하겠다.

반응형

'OpenCV' 카테고리의 다른 글

OpenCV - Blurring(2) & Sharpening  (0) 2020.12.16
Ubuntu 18.04 OpenCV 3.2 설치  (0) 2020.10.24
OpenCV - Image Warpping  (0) 2020.10.11
OpenCV - 어파인 변환 및 투상 변환  (0) 2020.10.10
OpenCV - 이미지 사이즈 변환 및 보간법  (0) 2020.10.10

댓글