Koo's.Co

필터링 본문

Python/영상처리

필터링

kth321 2023. 1. 5. 19:20

1. 필터링(filtering)

영상에서 필요한 정보만 통과시키고 나머지는 걸러내는 작업

 

① 주파수 영역 필터링(Frequency domain filtering)

 - 저주파 성분과 고주파 성분을 convolution 연산을 통해 처리

 

② 공간적 필터링(Spatial domain filtering)

 - 영상의 픽셀 값을 직접 이용하는 필터링 방법

 - 마스크 연산, convolution 연산을 이용

 

마스크의 형태에 따라 필터의 역할이 결정됨

  • 영상 부드럽게 만들기
  • 영상 날카롭게 만들기
  • edge 검출
  • 잡음 제거
  • ...

2. 공간적 필터링: 마스크 연산

1) 픽셀들을 순환하면서 2) 그 주변값들과 mask값들의 값을 곱하여 3) 새로운 값을 연산

 

최외곽 픽셀의 경우, 마스크에 해당하는 부분을 대칭으로 넘겨 동일한 값이 있다 가정하고 계산함

cv2.BORDER_REFLECT101

3. 블러링: 평균값 필터

  • 특정 좌표값을 주변 픽셀 값들의 산술 평균으로 설정
  • 픽셀들간의 값의 변화가 줄어들어 에지가 무뎌지는 효과
  • 마스크의 크기를 키우면 좀 더 블러링 효과가 강해짐
  • 마스크가 커지면 그만큼 연산량이 늘어나게 됨
kernel = np.full((3, 3), 1/9, dtype=np.float64)
dst = cv2.filter2D(src, -1, kernel) # -1은 src와 동일한 형태와 크기를 반환한다는 뜻
cv2.blur(src, ksize, dst=None, anchor=None, borderType=None) -> dst

src: 입력 영상

ksize: 필터 크기 (width, height)

dst: 입력 영상과 같은 크기 & 타입

4. 블러링: 가우시안 필터

  • 평균값 필터의 경우 가까운 픽셀이나 멀리 있는 픽셀 모두 동일한 가중치를 사용해 계산한다
  • 평균값 필터를 사용하는 경우 멀리 있는 픽셀의 영향을 많이 받을 수 있다
  • 가우시안 필터는 가까운 픽셀에 대해서는 큰 가중치를, 멀리 있는 픽셀에 대해서는 작은 가중치를 부여한다
  • 2차원 정규분포를 사용하여 마스크를 설정
cv2.GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None) -> dst

- src: 입력 영상, 채널 별로 처리

- dst: 출력 영상

- ksize: 커널 크기, (0, 0)을 지정하면 sigma값에 따라 자동으로 결정

- sigmaX: x방향 sigma

- sigmaY: y방향 sgima, 값을 주지 않으면 sigmaX와 동일한 값이 입력됨 

- borderType: 가장자리 픽셀 확장 방식

 

ksize를 설정하기보다는 (0, 0)을 설정한 후 sigma에 의해 결정되도록 하는 것이 유용

-> 커널 크기를 한정하면 정규분포의 값도 한정되기 때문에

 

5. 샤프닝: 언샤프 마스크 필터

블러링 필터를 이용해 생성한 영상을 이용해 날카로운 영상을 생성하는 방법

입력 영상 f에 블러링된 영상 g에 일정 가중치를 더하여 샤프닝된 영상을 생성할 수 있다.

g에 가중치를 조절하면 샤프닝 정도를 조절할 수 있다.

기존 영상의 픽셀 분포
블러링을 이용해 만든 영상의 픽셀 분포
둘의 픽셀 차이를 나타낸 분포
언샤프 마스크 필터를 적용했을 떄의 픽셀 분포

import cv2
import sys
import numpy as np

src = cv2.imread('image.bmp', cv2.IMREAD_GRAYSCALE)
if src is None:
  print('Image load failed')
  sys.exit()

blr = cv2.GaussianBlur(src, (0, 0), 2.0)
dst = cv2.addWeighted(src, 2, blr, -1, 0)
alph = 1.0 # 샤프닝 정도
# dst = np.clip(2.0 * src - alpha * blr, 0, 255).astype(np.uint8) # 0 ~ 255로 값을 한정

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()

cv2.destroyAllWindows()

좌) src, 우) 언샤프 마스크 필터 적용: contrast가 올라간 것을 볼 수 있다

 

import sys
import cv2

src = cv2.imread('image.jpg', cv2.IMREAD_COLOR)
if src is None:
  print('Image load failed')
  sys.exit()

src_ycrcb = cv2.cvtColor(src, cv2.BGR2YCrCb)

src_f = src_ycrcb[:, :, 0].astype(np.float32) # 밝기 정보
blr = cv2.GaussianBlur(src_f, (0, 0), 2.0)
src_ycrcb[:, :, 0] = np.clip(2.0 * src_f - alpha * blr, 0, 255).astype(np.uint8)

dst = cv2.cvtColor(src_ycrcb, cv2.COLOR_YCrCb2BGR)

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

색상이 있는 영상의 경우 YCrCb 형태의 데이터로 변환해준 후 색상 정보를 바꾸지 않고 밝기에만 필터를 적용해 엣지를 강조할 수 있다.

6. 잡음제거: 미디언 필터

  • 영상에는 gaussian noise 또는 salt&pepper noise가 포함된다.
  • 미디언 필터는 salt&pepper noise를 제거하기 위해 주로 사용되는 필터인데, 요즘에는 보통 gaussian noise만을 처리하기 때문에 자주 사용되는 필터는 아니다.
  • 마스크 연산을 사용하는 방법이 아닌 중앙값을 이용한 필터
  • 커널의 중심 픽셀을 그 주변 픽셀들의 중앙값으로 대치하는 방법

cv2.medianBlur(src, ksize, dst=None) -> dst

미디언 필터를 이용하면 blur되는 것처럼 나오기 때문에 medianBlur라는 함수 이름을 가짐

7. 잡음제거: 양방향 필터(Bilaateral Filter)

  • gaussian noise를 제거하기 위한 필터
  • 영상 내 객체는 뚜렷하게 만들면서(에지는 건들지 않고) 잡음만을 제거하기 위해 사용하는 필터

각 픽셀마다 마스크에 따른 정규분포를 적용하게 된다.

1) 엣지가 없는 첫번째 픽셀의 경우 전체적으로 가우시안 필터를 적용한다.

2) 엣지가 있는 경우에는 가우시안 필터의 일부분만을 사용해 가우시안 필터를 적용한다 -> 엣지 부분에는 블러링을 수행하지 않음

cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None) -> dst

 - src: 입력 영상

 - d: 이웃 픽셀의 거리. -1을 입력하면 sigmaSpace 값에 의해 자동으로 결정됨

 - sigmaColor: 색 공간에서 필터의 표준 편차. 엣지를 판단하기 위한 기준 -> ex) 10을 주는 경우 10주변의 값보다 큰 값을 엣지로 판단

 - sigmaSpace: 좌표 공간에서 필터의 표준 편차

 - dst: 출력 영상

 - borderType: 가장자리 픽셀 처리 방식

sigmaColor의 값은 10 ~ 20, sigmaSpace의 값은 5 이하로 사용하는 것이 좋다.

sigmaSpace의 값이 너무 커지게 되면 연산량이 너무 크게 늘어날 수 있다.

'Python > 영상처리' 카테고리의 다른 글

[OpenCV] 히스토그램 평활화(Histogram Equalization)  (0) 2023.01.05
[OpenCV] 히스토그램 분석  (0) 2023.01.05
[OpenCV] 명암비 조절  (0) 2023.01.05
[OpenCV] 컬러 영상 기본 함수  (0) 2023.01.04
[OpenCV] 산술 연산  (0) 2023.01.04
Comments