영상에서의 필터링이란 영상에서 필요한 정보만 통과시키고 원치 않는 정보를 걸러내는 작업을 의미합니다.
영상에서의 필터링은 2 종류로 나눌 수 있는데
1. 주파수 공간에서의 필터링
저주파 : 주변 영역과 색의 차이가 적은 부분(픽셀 값의 차이가 별로 없는 부분 : 대체로 면)
고주파 : 주변 영역과 색의 차이가 크게 나는 부분(픽셀 값의 차이가 큰 부분 : 대체로 모서리)
신호 및 시스템을 배우신 분이라면 저주파 필터, 고주파 필터에 대해 들어보셨을 텐데
저주파 필터의 경우 저주파 성분만을 통과시키는 것으로 이미지가 흐려지게 됩니다.
고주파 필터의 경우 고주파 성분만을 통과시키는 것으로 이미지의 선 같은 부분들이 강조됩니다.
2. 공간적 필터링
영상의 픽셀 값을 직접 이용하는 필터링
마스크(작은 크기의 행렬)를 통한 연산 = 커널을 통한 연산
마스크(커널)와 이미지 간의 컨벌루션 연산을 통하여 처리
컨벌루션 연산(합성곱 연산)에 대해선 https://wikidocs.net/64066
이곳이 간단히 컨벌루션이 무엇이다라고 간단히 이해하기는 쉬울 것 같네요
cv2.filter2D(src, ddepth, kernel [, dst [, anchor [, delta [, borderType]]]]) [] : 생략 가능
import cv2
import numpy as np
img = cv2.imread("imgs/Lenna.png")
img2 = cv2.resize(img, dsize=(0, 0), fx=2, fy=2) # 이미지 확대
kernel = np.ones((5, 5), dtype=np.float64) / 25. # 5*5 커널 생성
kernel2 = np.ones((10, 10), dtype=np.float64) / 100. # 5*5 커널 생성
filter_img = cv2.filter2D(img2, -1, kernel)
filter_img2 = cv2.filter2D(img2, -1, kernel2)
cv2.imshow("Lenna", img2)
cv2.imshow("filter_img", filter_img)
cv2.imshow("filter_img2", filter_img2)
cv2.waitKey()
cv2.destroyAllWindows()
src : 입력 영상
ddepth : 출력 영상 데이터 타입(-1 입력 시 입력 영상과 동일한 데이터 출력 영상 생성)
- 입력 : CV_8U -> -1/CV_16S/CV_32F/CV_64F
- 입력 : CV_16U, CV_16S -> -1/CV_32F/CV_64F
- 입력 : CV_32F -> -1/CV_32F/CV_64F
- 입력 : CV_64F -> -1/CV_64F
kernel : 필터 마스크 행렬(실수형) -> 커널의 총합: 1
커널 사이즈가 클수록 효과가 큽니다.
kernel = np.ones((5, 5), dtype=np.float64) / 25.
anchor : 고정점 위치, (-1, -1)이면 필터 중앙을 고정점으로 사용
delta : 추가적으로 더할 값
borderType : 가장자리 픽셀 확장 방식
cv2.blur(src, ksize [, dst [, anchor [, borderType]]]) []: 생략 가능
blur : 평균값 필터(영상의 특정 좌표값을 주변 픽셀 값들의 산술 평균으로 설정)
import cv2
img = cv2.imread("imgs/Lenna.png")
img2 = cv2.resize(img, dsize=(0, 0), fx=2, fy=2) # 이미지 확대
filter_img = cv2.blur(img2, (5, 5)) # 5*5 커널 생성
filter_img2 = cv2.blur(img2, (10, 10)) # 10*10 커널 생성
cv2.imshow("Lenna", img2)
cv2.imshow("filter_img", filter_img)
cv2.imshow("filter_img2", filter_img2)
cv2.waitKey()
cv2.destroyAllWindows()
src : 입력 영상
ksize : 커널 사이즈(width, height) 형태(위와 달리 커널 크기에 맞게 자동으로 나눠줍니다.)
dst : 결과 영상
anchor : 고정점 위치, (-1, -1)이면 필터 중앙을 고정점으로 사용
borderType : 가장자리 픽셀 확장 방식
※ filter2D보다는 blur 사용을 추천드립니다.
일반적인 필터를 사용할 경우(np.zeros 사용 후 같은 값으로 나눗셈) blur와 같고
다른 특별한 커널을 생성해서 하고 싶은 경우(커널을 만드는 것도 어렵기도 하고..) blur 외에도 커널의 가중치가 다양하게 반영되어있는 blur가 많기 때문에 필요한 것을 찾아 사용하시는 게 편리할 것 같습니다.
cv2.GaussianBlur(src, ksize, sigmaX [, dst [, sigmaY [, borderType]]]) []: 생략 가능
GaussianBlur : 가우시안 필터(가까이 있는 픽셀에 가중치를 매겨 가중치 평균값으로 대치)
가우시안 함수를 기반으로 한 필터입니다. 궁금하신 분은 찾아보시는 것도 좋겠네요
import cv2
img = cv2.imread("imgs/Lenna.png")
img2 = cv2.resize(img, dsize=(0, 0), fx=2, fy=2) # 이미지 확대
filter_img = cv2.GaussianBlur(img2, (0, 0), 1)
filter_img2 = cv2.GaussianBlur(img2, (0, 0), 3)
cv2.imshow("Lenna", img2)
cv2.imshow("filter_img", filter_img)
cv2.imshow("filter_img2", filter_img2)
cv2.waitKey()
cv2.destroyAllWindows()
src : 입력 영상
ksize : 가우시안 커널 크기, (0,0)으로 설정(추천) 시 sigma 값에 의해 자동 결정
(0,0)으로 주는 이유는 sigmaX를 설정했을 때 ksize가 sigma 값에 맞게 알아서 조정됩니다.
커널 사이즈를 따로 지정해줄 경우 온전한 가우시안 필터 효과를 받지 못할 수 있습니다.
만약에 설정해서 확인해 보고 싶으신 경우 값은 홀수로 주셔야 합니다.
2*2(짝수)로 만들 경우 중앙점도 애매하고 가깝고 먼 픽셀 구분도 안돼서 에러가 발생합니다.
sigmaX : x방향 sigma
값을 설정해주었을 때 마스크 크기가 6 * sigma + 1 또는 8 * sigma +1 정도로 설정된다고 하네요.
1~4 정도가 적당한 것 같습니다. 크게 하면 물체의 형태도 제대로 알아보기 힘들어요.
dst : 출력 영상
sigmaY : y방향 sigma, 0이면 sigmaX와 같게 설정
borderType : 가장자리 픽셀 확장 방식
'OpenCV-Python' 카테고리의 다른 글
OpenCV Python 이미지 영상 확대 축소 (0) | 2021.08.23 |
---|---|
OpenCV Python 필터링 - 날카로운 영상 만들기: 언샤프(unsharp) 필터 (0) | 2021.08.23 |
OpenCV Python 자르기, 붙이기 (2) | 2021.08.21 |
OpenCV Python 이미지 색상 변환 (0) | 2021.08.20 |
OpenCV Python 카메라, 동영상 출력 (0) | 2021.08.19 |