[OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝] 7장_정리(2)

SUN·2022년 12월 19일
0

7.3 샤프닝 : 영상 날카롭게 하기

  • 샤프닝

    초점이 잘 맞은 사진처럼 사물의 윤곽이 뚜렷하고 선명한 느낌이 나도록 영상을 변경하는 필터링 기법

7.3.1 언샤프 마스크 필터

  • 샤프닝(sharpening)

    영상을 날카로운 느낌이 나도록 변경하는것

    날카로운 느낌의 영상이란?
    -> 초점이 잘 맞은 사진처럼 객체의 윤곽이 뚜렷하게 구분되는 영상
    이미 촬영된 사진을 초점이 잘 맞은 사진처럼 보이게끔 변경하려면 영상 에지 근방에서 픽셀 값의 명암비가 커지도록 수정해야한다

    블러링된 영상을 사용한다

    블러링이 적용되어 부드러워진 영상을 활용하여 반대로 날카로운 영상을 생성한다는 것

    여기서 블러링이 적용된 영상, 즉 날카롭지 않은 영상을 언샤프(unsharp)하다고 하기도한다

    언샤프한 영상을 이용하여 역으로 날카로운 영상을 생성하는 필터를 언샤프 마스크 필터(unsharp mask filter)라고 한다

  • 예제코드

    샤프닝
    import sys
    import numpy as np
    import cv2
    
    src = cv2.imread('rose.bmp', cv2.IMREAD_GRAYSCALE)
    
    if src is None:
        print('Image load failed!')
        sys.exit()
    
    cv2.imshow('src', src)
    
    for sigma in range(1, 6):
        blurred = cv2.GaussianBlur(src, (0, 0), sigma)
    
        alpha = 1.0
        dst = cv2.addWeighted(src, 1 + alpha, blurred, -alpha, 0.0)
    
        desc = "sigma: %d" % 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()```
    



7.4 잡음 제거 필터링

7.4.1 영상과 잡음 모델

  • 신호 처리 관점에서의 잡음(noise)
    원본 신호에 추가된 원치 않은 신호

  • 영상에서의 잡음
    영상을 획득하는 과정에서 발생하며, 디지털 카메라에서 사진을 촬영하는 경우에는 광학적 신호를 전기적 신호로 변환하는 센서(sensor)에서 주로 잡음이 추가된다

영상신호 = 원본 + 잡음으로 되어있다

잡음이 생성되는 방식을 잡음 모델(noise model)
가장 대표적인 잡음 모델은 가우시안 잡음 모델(Gaussian noise model)
가우시안 잡음 모델
평균이 0인 가우시안 분포를 따르는 잡음

표준 편차가 작은 가우시안 잡음 모델일 수록 잡음에 의한 픽셀 값 변화가 적다고 생각할 수 있다

표준편차 stddev 값이 증가함에 따라 잡음의 영향이 커지므로 결과 영상이 더욱 지저분해진다

7.4.2 양방향 필터

가우시안 잡음을 제거하기 위해 가우시안 필터를 사용한다

입력 영상에서 픽셀값이 크게 변하지 않는 평탄한 영역에 가우시안 필터가 적용될 경우, 주변 픽셀 값이 부드럽게 블러링되면서 잡음의 영향도 줄어든다

그러나 픽셀값이 급격하게 변경되는 에지 근방에 동일한 가우시안 필터가 적용되면서 잡음뿐만 아니라 에지 성분까지 함께 감소하게 된다

즉, 잡음이 줄어들면서 함께 에지도 무뎌지기 때문에 객체의 윤곽이 흐릿하게 바뀐다

이러한 단점을 보완하기위해
에지 정보는 그대로 유지하면서 잡음만 제거하는 에지 보전 잡음 제거 필터(edge-preserving noise removal filter)에 대해 연구했다
양뱡향 필터(bilateral filter)는 에지 성분은 그대로 유지하면서 가우시안 잡음을 효과적으로 제거하는 알고리즘이다


7.4.3 미디언 필터

  • 미디언 필터(median filter)

    입력 영상에서 자기 자신 픽셀과 주변 픽셀 값 중에서 중간값(median)을 선택하여 결과 영상 픽셀 값으로 설정하는 필터링 기법

    마스크 행렬과 입력 영상 픽셀 값을 서로 곱한 후 모두 더하는 형태의 연산을 사용하지 않는다

    주변 픽섹 값들의 중간값을 선택하기 위해 내부에서 픽셀 값 정렬 과정이 사용된다

    잡음 픽셀 값이 주변 픽셀 값과 큰 차이가 있는 경우에 효과적으로 동작한다

  • 소금&후추(salt & pepper noise)

    픽셀 값이 일정 확률로 0 또는 255로 변경되는 형태의 잡음

    잡음이 마치 소금과 후추처럼 흰색 또는 검은색으로 구성되기때문

    소금&후추 잡음이 추가된 영상에 미디언 필터를 적용하면 대부분 소금&후추 잡음이 아닌 원본 영상에 존재하는 픽셀 값이 중간값으로 선택되기 때문에 잡음은 효과적으로 제거된다

특정 위치에서 특정 크기의 픽셀 값 배열 중 주변 픽셀 값 배열을 가지고,
그 영역의 픽셀 값을 일렬로 늘여 세운 후, 픽셀 값 크기 순으로 정렬한다
그 정렬된 데이터에서 중앙에 있는 픽셀 값을 선택하여 결과 영상의 픽셀 값으로 설정한다

이러한 과정을 영상 전체 픽셀에 대하여 수행하면 미디언 필터 결과 영상이 만들어진다

  • 예제코드
노이즈(잡음)
import numpy as np
import cv2
import random


def noise_gaussian():   # 가우시안 잡음 모델
    src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)

    if src is None:
        print('Image load failed!')
        return

    cv2.imshow('src', src)

    for stddev in [10, 20, 30]:
        noise = np.zeros(src.shape, np.int32)
        cv2.randn(noise, 0, stddev)

        dst = cv2.add(src, noise, dtype=cv2.CV_8UC1)

        desc = 'stddev = %d' % stddev
        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()


def filter_bilateral():  # 양방향 필터
    src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)

    if src is None:
        print('Image load failed!')
        return

    noise = np.zeros(src.shape, np.int32)
    cv2.randn(noise, 0, 5)
    cv2.add(src, noise, src, dtype=cv2.CV_8UC1)

    dst1 = cv2.GaussianBlur(src, (0, 0), 5)
    dst2 = cv2.bilateralFilter(src, -1, 10, 5)
    
    cv2.imshow('src', src)
    cv2.imshow('dst1', dst1)
    cv2.imshow('dst2', dst2)
    cv2.waitKey()
    cv2.destroyAllWindows()


def filter_median():  # 미디언 필터
    src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)

    if src is None:
        print('Image load failed!')
        return

    for i in range(0, int(src.size / 10)):
        x = random.randint(0, src.shape[1] - 1)
        y = random.randint(0, src.shape[0] - 1)
        src[x, y] = (i % 2) * 255

    dst1 = cv2.GaussianBlur(src, (0, 0), 1)
    dst2 = cv2.medianBlur(src, 3)

    cv2.imshow('src', src)
    cv2.imshow('dst1', dst1)
    cv2.imshow('dst2', dst2)
    cv2.waitKey()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    noise_gaussian()
    filter_bilateral()
    filter_median()

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

src : 입력 영상
ksize : 커널 크기, 1보다 큰 홀수
dst : 출력 영상

cv2.bilaterFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)

src : 입력 영상
d : 필터링에 사용될 이웃 픽셀의 거리(지금), 음수(-1)을 입력하면 sigmaSpace 값에 의해 자동 결정(권장)
sigmaColor : 색 공간에서 필터의 표준 편차
sigmaSpace : 좌표 공간에서 필터의 표준 편차
dst : 출력 영상
borderType : 가장자리 픽셀 처리 방식

0개의 댓글