Skip to main content

공간 필터링

공간 주파수

  • 공간 주파수: 공간상에서 화소 밝기의 변화율
    • 고주파 영역: 화소 밝기가 급변하는 영역(주로 경계)
    • 저주파 영역: 화소 밝기의 변화가 거의 없거나 점진적으로 변화하는 영역(주로 배경)
src = cv.imread('temple.webp')

공간 필터링 spacial filtering

  • 인접화소들의 값을 참조하여 화소의 값을 변경하는 처리
  • 컨볼루션(convolution)을 이용하여 구현
    • 중심 화소의 값을 인접 화소값들의 가중 합으로 대체하는 연산
  • 가중치 2차원 배열: 커널(kernel), 필터(filter), 또는 마스크(mask)라고 함

평균값 필터링

  • 주변 3x3 픽셀의 평균으로 채워서 흐리게(blur) 만듦
    kernel = np.array([
    [1/9, 1/9, 1/9],
    [1/9, 1/9, 1/9],
    [1/9, 1/9, 1/9]], dtype=np.float32)
    dst = cv.filter2D(src, -1, kernel)
    show(dst)

가우시안 블러링 Gaussian Blurring

  • 이미지를 흐리게(blur) 만드는 방법
  • 가우시안 함수(=통계의 정규 분포)를 이용 → 가운데는 많이, 주변은 적게 반영
  • 커널 내 (예: 5x5 범위)에서만 적용
    blur = cv.GaussianBlur(src, (5, 5), 0)
    show(blur)
  • 커널을 직접 구하려면 아래 처럼
    kernel = cv.getGaussianKernel(5, 0)
    kernel = kernel * kernel.T
    kernel = kernel / np.sum(kernel)
    dst = cv.filter2D(src, -1, kernel)

수직 성분의 추출

  • 왼쪽의 픽셀들과 오른쪽의 픽셀들의 차이를 구함
  • 수평 방향으로 밝기가 변할 때 결과값이 커짐
  • 오른쪽이 밝고 왼쪽은 어두울 때 결과값이 가장 큼
    kernel = np.array([
    [-1, 0, 1],
    [-1, 0, 1],
    [-1, 0, 1]], dtype=np.float32)
    dst = cv.filter2D(src, -1, kernel)
    show(dst)

수평 성분의 추출

  • 위쪽의 픽셀들과 아래쪽의 픽셀들의 차이를 구함
  • 수직 방향으로 밝기가 변할 때 결과값이 커짐
  • 위는 밝고 아래는 어두울 때 결과값이 가장 큼
    kernel = np.array([
    [1, 1, 1],
    [0, 0, 0],
    [-1, -1, -1]], dtype=np.float32)
    dst = cv.filter2D(src, -1, kernel)
    show(dst)

Sharpening

  • 주변 픽셀들과의 밝기 차이를 과장해서 날카롭게 만듦(blur의 반대)
  • 초점이 맞지 않은 사진을 선명하게 만들 수 있지만, 노이즈도 증가
    kernel = np.array([
    [-1, -1, -1],
    [-1, 9, -1],
    [-1, -1, -1]], dtype=np.float32)
    dst = cv.filter2D(src, -1, kernel)

소벨 커널 Sobel kernel

  • 경계선(edge) 검출을 위한 커널
    sobelx = cv.Sobel(src, cv.CV_64F, 1, 0, ksize=3) # x 방향의 경계선 검출
    sobely = cv.Sobel(src, cv.CV_64F, 0, 1, ksize=3) # y 방향의 경계선 검출
    sobel_magnitude = cv.magnitude(sobelx, sobely) # 두 방향의 경계선을 하나로 결합
    sobel_result = cv.normalize(sobel_magnitude, None, 0, 255, cv.NORM_MINMAX, cv.CV_8U) # 정규화
    show(sobel_result) # 시각화

케니 에지 검출 Canny edge detection

  • 소벨 커널을 바탕으로 만든 경계선 검출 알고리즘
    gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY) # 그레이스케일로 변환
    # Otsu의 이진화로 상한값 계산
    upper, ret = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    lower = upper / 2 # 하한값은 보통 상한값의 1/2 또는 1/3 사용
    blur = cv.GaussianBlur(gray, (9, 9), 0) # 가우시안 블러 적용
    edges = cv.Canny(blur, upper, lower)
    show(edges) # Canny 엣지 검출 결과 출력

경계선 추출 전 흐리게 하기

  • 경계선은 밝기가 급격하게 변하므로 고주파 검출에 해당
  • 이미지의 잡음도 고주파이므로 경계선 검출을 방해할 수 있음
  • 이미지를 흐리게 하는 것은 낮은 주파수만 통과시키는 것과 같음(low-pass filter)
  • 경계선 검출 전에 이미지를 흐리게 하여 잡음을 뭉개면 경계선을 검출하는데 도움이 됨
  • 3x3 가우시안 블러를 했을 때
  • 15x15 가우시안 블러를 했을 때

퀴즈