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

  • 최초 작성일: 2022년 1월 14일(목)

목차

[TOC]


목표

영상처리를 위한 노이즈 제거의 중요성은 앞서 여러번 언급했던 바 있다.

이번에는 조금 더 전문적인 노이즈 제거 방법인 Low Pass Filters 에 대해 알아보자.



실습

Low Pass Filter (LPF) 는 말 그대로 낮은 값들만 통과시킨다 라고 이해하면 쉽다.

갑자기 높은 값의 노이즈가 툭 튀어나오는 경우, 해당 노이즈를 제거할 수 있다.

우선, 사용하게 될 함수에 대해 알아보고 가자.

Low Pass Filter (LPF) 중 대표적인 4가지 필터들을 알아보자.

이러한 필터들을 이용해 노이즈를 제거할 수 있다.


blur (src, dst, kernel_size, anchor, border_type) * 평균 필터 (Average Filter)

  • src: 입력 이미지
  • dst: 출력 이미지
  • kernel_size: 필터 사이즈. Size(x,y)의 형태
  • anchor: 픽셀 위치: 기본값 Point(-1, -1) 사용 권장
  • border_type: 이미지의 테두리 처리 방법
    • BORDER_CONSTANT 또는 0
    • BORDER_REPLICATE 또는 1
    • BORDER_REFLECT 또는 2
    • BORDER_DEFAULT 또는 4
    • BORDER_REFLECT101 또는 4 (기본 값)
    • BORDER_TRANSPARENT 또는 5
    • BORDER_ISOLATED 또는 16


GaussianBlur (src, dst, kernel_size, sigma_x, sigma_y, border_type) * 가우시안 필터 (Gaussian Filter)

  • src: 입력 이미지
  • ds: 출력 이미지
  • kernel_size: 필터 사이즈. Size(x,y)의 형태
  • sgma_x: x방향 표준편차, 기본값 0- > 자동 계산
  • sigma_y: y방향 표준편차, 기본값 0- > 자동 계산
  • border_type: 이미지의 테두리 처리 방법 (BORDER_TYPE은 blur 함수와 동일)


medianBlur (src, dst, kernel_size) * 미디안 필터 (Median Filter)

  • src: 입력 이미지
  • dst: 출력 이미지
  • kernel_size: 필터 사이즈. 한변의 길이 입력(정사각 행렬, 홀수)


bilateralFilter (src, dst, d, sigma_color, sigma_space, border_type) * 바이라더럴 필터 (Bilateral Filter)

  • src: 입력 이미지
  • dst: 출력 이미지
  • d: 필터 적용시 주변 픽셀 범위
  • sigma_color: 적용할 컬러 범위
  • sigma_space: 적용할 픽셀 범위
  • border_type: 이미지의 테두리 처리 방법 (BORDER_TYPE은 blur 함수와 동일)


앞서 평균 필터와 가우시안 필터는 알아봤으니, 이번엔 Median Filter와 Bilateral Filter에 대해 알아보자.

median filter는 소금 후추 노이즈 (salt & pepper noise)를 제거하는 데에 특화되어 있다.

점 노이즈라고 하는 소금 후추 노이즈는 아래의 이미지처럼 이미지에 소금이나 후추를 뿌려놓은 듯한 모습을 보인다.

image


그럼 중간값 필터가 왜 점 노이즈에 특화됐다고 말할 수 있는가? 그리고 평균 필터와 어떻게 비교 되는가?

image

위의 이미지와 같이 3x3 필터 크기만큼 필러팅이 진행된다고 할 때, median filter와 average filter를 각각 사용하여 필터링 하면 각각 아래의 결과를 나타낸다.

image


평균 필티의 경우에는, 주변값들의 영향을 많이 받는 필러팅 기법이다. 그러다보니 점 노이즈와 같은 Outlier(이상값)이 생길 경우, 해당 노이즈의 영향을 많이 받을 수밖에 없다.

극단적인 예를 들면, 3x3 매트릭스 내의 9개 값이 0, 0, 0, 0, 0, 255, 255, 255, 255 라면, 평균 필터로는 113, 중간값 필터로는 0을 적용하기 때문에 큰 차이를 보인다.

반면에, 중간값 필터는 점 노이즈와 같은 Outlier에 대한 영향을 덜 받기 때문에, 점 노이즈에 대한 필터링에 적합하다고 할 수 있다.


그러면 마지막으로, bilateral filter (양방향 필터) 를 알아보자.

양방향 필터는 이미지에 대한 비선형, 에지 보존 및 노이즈 감소 스무딩 필터이다. 각 픽셀의 강도를 근처 픽셀의 가중치 평균 강도 값으로 바꾼다.

이 가중치는 가우스 분포를 기반으로 할 수 있으며, 픽셀의 유클리드 거리뿐만 아니라 방사 측정 차이에도 의존한다.

그러면, 날카로운 모서리를 유지하는 결과를 보인다. 다시 말해, 모서리를 살리면서 노이즈만 효과적으로 제거하기 때문에 앞에서 다뤘던 노이즈 제거 방식보다 좋은 결과를 보인다.

하지만, 효과가 더 좋은 만큼 시간이 더 오래 걸린다는 것이 단점이다.


소스 코드

#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;

int main(int ac, char** av)
{
	Mat img = imread("lion_noise.png");
	Mat img_salt = imread("lion_salt_noise.png", 0);
	Mat img_blur, img_gaussian, img_median, img_bilateral;


	blur(img, img_blur, Size(5, 5), Point(-1, -1));
	GaussianBlur(img, img_gaussian, Size(5, 5), 0, 0, 4);
	medianBlur(img_salt, img_median, 5);
	bilateralFilter(img, img_bilateral, 9, 75, 75, 4);

	imshow("lion_noise.png", img);
	//imshow("img_salt_noise", img_salt);
	//imshow("img_blur", img_blur);
	//imshow("img_gaussian", img_gaussian);
	//imshow("img_median", img_median);
	imshow("img_bilateral", img_bilateral);
	waitKey(0);

	return 0;
}



결과

평균 필터 (average filter) - “lion_noise.png” 이미지에 적용

image


가우시안 필터 (gaussian filter) - “lion_noise.png” 이미지에 적용

image


중간값 필터 (median filter) - “lion_salt_noise.png” 이미지에 적용

image


양방향 필터 (bilateral filter) - “lion_noise.png” 이미지에 적용

image