opencv c++ High Pass Filters를 이용하여 노이즈를 제거하자.

  • 최초 작성일: 2022년 10월 13일(목)

목차

[TOC]


목표

앞서 Low Pas Filter를 다루어보았고, 노이즈 제거를 알아보았다.

이번에는 비슷한 개념이면서 다른 개념의 High Pass Filter를 이해해보자.



실습

함수 종류 (고역주파수 통과 필터 (High Pass Filter))


Sobel (src, dst, ddepth, dx, dy, kernel_size, scale, delta, border_Type)

  • src: 입력 이미지
  • dst: 출력 이미지
  • ddepth: 이미지의 자료형 (CV_8U 또는 CV_16S 등)
  • dx: x방향으로 미분, 0(false) 또는 1(true)
  • dy: y방향으로 미분, 0(false) 또는 1(true)
  • kernel_Size: 적용시킬 평균 필터의 사이즈, Size(x, y)로 입력
  • scale: 미분 값에 대한 배율 조절, 보통 (1,0) 사용
  • delta: 결과 이미지에 더해줄 값, 보통 (0,0) 사용
  • border_Type: 이미지의 테두리에 대한 처리방법,
    • zero padding 또는 reflect(mirror) padding을 적용할 수 있음
      • BORDER_CONSTANT 또는 0
      • BORDER_REPLICATE 또는 1
      • BORDER_REFLECT 또는 2
      • BORDER_DEFAULT 또는 4
      • BORDER_REFLECT101 또는 4 (기본값)
      • BORDER_TRANSPARENT 또는 5
      • BORDER_ISOLATED 또는 16


Laplician (src, dst, ddepth, kernel_size, scale, delta, border_Type)

  • src: 입력 이미지
  • dst: 출력 이미지
  • ddepth: 이미지의 자료형 (CV_8U 또는 CV_16S 등)
  • kernel_Size: 적용시킬 평균 필터의 사이즈, Size(x, y)로 입력
  • scale: 미분 값에 대한 배율 조절, 보통 (1,0) 사용
  • delta: 결과 이미지에 더해줄 값, 보통 (0,0) 사용
  • border_Type: 이미지의 테두리에 대한 처리방법,
    • zero padding 또는 reflect(mirror) padding을 적용할 수 있음
      • BORDER_CONSTANT 또는 0
      • BORDER_REPLICATE 또는 1
      • BORDER_REFLECT 또는 2
      • BORDER_DEFAULT 또는 4
      • BORDER_REFLECT101 또는 4 (기본값)
      • BORDER_TRANSPARENT 또는 5
      • BORDER_ISOLATED 또는 16


Canny (src, dst, threshold1, threshold2, aperture_size)

  • src: 입력 이미지
  • dst: 출력 이미지
  • threshold1: 낮은 경계 값 (0~255)
  • threshold2: 높은 경계 값 (0~255)
  • aperture_size: sobel 연산 적용할 구멍 크기, 기본값 3



위의 함수들이 High Pass Filter에 속하는 연산들이다.

영상 처리에서 High Pass Filter는 가장자리(edge)를 두드러지게 하는 작업이다.

그러면 위의 함수들은 무슨 차이가 있느냐…

soble은 1차 미분.

laplacian은 2차 미분.

canny는 sobel 연산을 이용한 결과에 방향성을 추가로 고려한 연산이다.


High Pass Filter와 Low Pass Filter를 커널로 비교했을 때의 차이점이다.

image

커널을 알아야 이해하기 쉬울 것이다.

Low Pass Filter 는 평균 필터의 일종이며, High Pass Filter 는 필터 영역 중앙에 가중치를 더 많이 주는 것을 확인할 수 있다.

미분 연산을 해보면 High Pass Filter 처럼 행렬을 쓸 수 있는 것이고, 결과는 경계를 선명하게 해준다.


그러면 High Pass Filter의 역할을 알아봤으니, 1차 미분과 2차 미분에 대해 알아 보자.

일단 미분이 왜 적용되는지 알고 가자.

image

1차 미분을 하면 위의 이미지처럼 변한다.

밝기 정보가 갑작스럽게 변하는 구간이 경계일 확률이 높으므로, 1차 미분한 그래프에서 값이 높은 부분을 경계라고 보는 것이다.

이처럼 경계를 찾고싶으면 밝기의 변화율을 볼 수 있는 미분을 사용하는 것이다.


1. sobel

  • x, y방향으로 각각 1차 편미분한 결과를 합친 것

image

x방향으로 편미분하여 밝기 증가율이 높은 부분이 표시되었다.


image

y방향으로 편미분하여 밝기 증가율이 높은 부분이 표시되었다.


위의 두 이미지를 합치면 아래와 같이 이미지의 경계를 표시해주는 이미지가 나타난다.

image

여기서 더 선명한 경계를 얻고자할 때, zero_crossing 을 해주면 되는데, 그냥 넘어가겠다.


2. Laplacian

  • 2차 미분하여 선명한 경계를 얻음.

1차 미분한 하면 약간 애매한 결과를 얻게 되는데, 2차 미분을 하면 확실한 밝기 변화를 볼 수 있다.

image

2차 미분을 하게 되면, 밝기 변화율에 대한 변화율을 얻을 수 있는데,

양에서 음으로 가는 순간 또는, 음에서 양으로 가는 순간을 경계로 인식하는 것이다.

결과는 아래와 같이 나온다.

image

opencv에서 라플라시안을 사용하면 기본적으로 sobel 연산이 적용된다.

라플라시안도 x, y 방향으로부터 미분값을 받아와 합쳐지게 된다.


3. Canny

  • sobel 연산을 적용하고 방향성을 고려한 경계 추출 방법

image

sobel 연산 결과에서 경계선이 연속적일 수 있게 방향성을 고려해 불필요한 부분을 지워준다.



Canny를 제외한 sobel과 laplacian을 비교해보면

sobel의 문제점은 검은색에서 흰색으로 진행되면 경계를 잘 찾아낸다. 하지만 밝은 부분에서 어두운 부분으로 바뀌는 부분은 경계로 인식하지 못한다.

laplacian은 어느 방향에서든 확실하게 경계를 잡아낸다.


그리고 canny 에는 자동으로 포함된 기능이 하나 있다.

바로 Gaussian Filter 이다.

경계를 찾음에 있어서 노이즈제거는 반드시 선행되어야 한다.

미분을 하는데 방해가 되기 때문이다.

그래서 항상 노이즈를 제거한 이미지를 입력해 주어야 한다.




소스 코드

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int ac, char** av)
{
	Mat img = imread("deer.jpg", 0);
	Mat img_gaussian, img_canny;
	Mat img_sobel_x, img_sobel_y, img_sobel;
	Mat img_lap;

	GaussianBlur(img, img_gaussian, Size(3, 3), 0, 0, 4);

	Sobel(img_gaussian, img_sobel_x, CV_8U, 1, 0, 3, (1.0), (0, 0), 4);
	Sobel(img_gaussian, img_sobel_y, CV_8U, 0, 1, 3, (1.0), (0, 0), 4);
	addWeighted(img_sobel_x, 1, img_sobel_y, 1, 0, img_sobel);

	Laplacian(img_gaussian, img_lap, CV_8U, 3, (1.0), (0, 0), 4);

	Canny(img, img_canny, 80, 120);

	imshow("original", img);
	imshow("img_sobel_x", img_sobel_x);
	imshow("img_sobel_y", img_sobel_y);
	imshow("img_sobel", img_sobel);
	imshow("img_lap", img_lap);
	imshow("img_canny", img_canny);
	waitKey(0);

	return 0;
}


결과

원본 (흑백으로 불러옴)

image


sobel (x, y 축에 대한 1차 미분, 커널 사이즈 3)

image


sobel 연산 최종 이미지

경계가 검출되었지만 밝은 곳에서 어두운 곳으로 이어지는 부분은 경계가 없거나 흐릿하다.

image


라플라시안 필터

sobel과 다르게 섬세하게 경계가 검출되었다.

image


canny

image



결론

High Pass Filter (HPF)는 이미지 경계를 뚜렷하게 해주는 역할을 한다.

HPF 를 적용하기 전에는 무조건 LPF 를 적용하여 노이즈를 제거하는 것이 필수적이다.

sobel과 laplacian의 차이는 1차 미분이냐, 2차 미분이냐는 차이이고, 각각의 사용법이 있다.

sobel 연산을 적용하면서 쉽게 사용할 수 있는 Canny 함수를 opencv에서 기본적으로 지원한다.