본문 바로가기
Data Science/OpenCV

OpenCV - Filtering

by 루크 Luke 2022. 1. 3.
반응형

1. Filtering Overview

- 영상에서 필요한 정보만 통과시키고 원치 않는 정보는 걸러내는 작업

- 주파수 공간에서의 필터링 (Frequency domain filtering

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

'커널'이라는 표현을 많이 쓰는 것 같다.

- Import Library

import cv2
import sys
import numpy as np

 

2. Mask = Kernel

- 다양한 모양과 크기의 마스크가 존재하며, 마스크의 형태와 값에 따라 필터의 역할이 결정됨

- Ex) 영상 부드럽게 만들기, 영상 날카롭게 만들기, 에지(edge) 검출, 잡음 제거

- OpenCV에서 지원하는 가장자리 테두리는 4가지

- Ex) BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101

- 2D Filtering : kernel을 직접 넣어줘서 필터링 적용

 

3. Mean Filter (Blur filter)

- 영상의 특정 좌표 값을 주변 픽셀 값들의 산술평균으로 설정하는 필터

- 픽셀들 간의 그레이스케일 값 변화가 줄어들어 날카로운 에지가 무뎌지고, 영상에 있는 잡음이 영향이 사라지는 효과

- 마스크의 크기가 커질수록 평균값 필터 결과가 더욱 부드러워짐. 대신 연산량이 많아짐

# 2d filtering - mean blur
import sys
import numpy as np
import cv2

src = cv2.imread('./data/apples.jpg', cv2.IMREAD_GRAYSCALE)
kernel = np.array([[1/9, 1/9, 1/9], [1/9, 1/9, 1/9], [1/9, 1/9, 1/9]])
dst = cv2.filter2D(src, -1, kernel)

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

cv2.destroyAllWindows()

- 일반적으로는 2D filter 보다는 Blur()를 더 많이 사용

# blur - 1
import sys
import numpy as np
import cv2

src = cv2.imread('./data/apples.jpg', cv2.IMREAD_GRAYSCALE)
# dst = cv2.blur(src, (3, 3))
dst = cv2.blur(src, (5, 5))  # 더 흐려짐

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

cv2.destroyAllWindows()
# blur - 2
import sys
import numpy as np
import cv2

src = cv2.imread('./data/apples.jpg', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()
cv2.imshow('src', src)

for ksize in (3, 5, 7):  # 숫자 높일 수록 Blur 효과 큼
    dst = cv2.blur(src, (ksize, ksize))
    desc = f'Mean: {ksize}x{ksize}'
    cv2.putText(dst, desc, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, 255, 1, cv2.LINE_AA)

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

cv2.destroyAllWindows()

- 평균값 필터의 단점 : 가까운 픽셀, 먼 픽셀 모두 같은 가중치 사용 -> 멀리 있는 픽셀의 영향을 많이 받게될 수 있음 

왼쪽이 mean filter, 오른쪽은 Gaussian filter

 

4. Gaussian Filter

- 가우시안 함수를 이용한 필터

- 가우시안 필터는 GaussianBlur() 등 별도로 제공되고 있다.

- sigma 값을 조정해서 흐릿한 정도를 변화시킬 수 있음 - sigma가 커지면 더 흐릿함

# Gaussian Blur - 1
import sys
import numpy as np
import cv2

src = cv2.imread('./data/apples.jpg', cv2.IMREAD_GRAYSCALE)
dst = cv2.GaussianBlur(src, (0, 0), 3)
dst2 = cv2.blur(src, (7, 7))

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

cv2.destroyAllWindows()
# Gaussian Blur - 2
import sys
import numpy as np
import cv2

src = cv2.imread('./data/apples.jpg', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()
cv2.imshow('src', src)

for sigma in range(1, 6):
    # sigma 값을 이용해서 가우시안 필터링 변화
    # sigma 커질수록 더 흐릿하게 보임
    dst = cv2.GaussianBlur(src, (0, 0), sigma)

    desc = f'sigma = {sigma}'
    cv2.putText(dst, desc, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, 255, 1, cv2.LINE_AA)
    cv2.imshow('dst', dst)
    cv2.waitKey()

cv2.destroyAllWindows()

 

5. Noise

- 영상의 픽셀 값에 추가되기를 원치 않는 형태의 신호

- 잡음의 종류는 가우시안 잡음(Gaussian noise), 소금&후추 잡음(Salt & Pepper)

- Noise 처리에는 대표적으로 미디언 필터(Median Filter)를 활용하며, 카툰 필터도 활용함

1) Median Filter

# Noise - Medianblur
import sys
import numpy as np
import cv2

src = cv2.imread('./data/noise.bmp', cv2.IMREAD_GRAYSCALE)
dst = cv2.medianBlur(src, 3)

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

cv2.destroyAllWindows()

2) Cartoon Filter

# Noise - Cartoon filter, Sketch filter
import sys
import numpy as np
import cv2

def cartoon_filter(img):
    h, w = img.shape[:2]
    img2 = cv2.resize(img, (w//2, h//2))

    blr = cv2.bilateralFilter(img2, -1, 20, 7)
    edge = 255 - cv2.Canny(img2, 80, 120)
    edge = cv2.cvtColor(edge, cv2.COLOR_GRAY2BGR)

    dst = cv2.bitwise_and(blr, edge)
    dst = cv2.resize(dst, (w, h), interpolation=cv2.INTER_NEAREST)

    return dst

def pencil_sketch(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blr = cv2.GaussianBlur(gray, (0, 0), 3)
    dst = cv2.divide(gray, blr, scale=255)

    return dst

cap = cv2.VideoCapture(0)

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

cam_mode = 0
while True:
    ret, frame = cap.read()

    if not ret:
        break

    if cam_mode == 1:
        frame = cartoon_filter(frame)
    elif cam_mode == 2:
        frame = pencil_sketch(frame)
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
    
    cv2.imshow('frame', frame)
    key = cv2.waitKey(1)

    if key == 27:
        break
    elif key == ord(' '):
        cam_mode += 1
        if cam_mode == 3:
            cam_mode = 0

src = cv2.imread('./data/noise.bmp', cv2.IMREAD_GRAYSCALE)
dst = cv2.medianBlur(src, 3)

cap.release()
cv2.destroyAllWindows()
반응형

'Data Science > OpenCV' 카테고리의 다른 글

OpenCV - VideoCapture, VideoWriter  (0) 2022.01.03
Start OpenCV and draw on the picture/video  (0) 2022.01.03

댓글