[OpenCV] 잡음 제거 – 1. 양방향 필터

이번 글에서는 영상에서 잡음(noise)을 제거하는 방법을 알아보겠습니다.

잡음은 주로 영상 얻는 과정에서 발생하며, 영상에서 원치않는 값이 추가되는 것을 말합니다.
잡음이 추가된 영상은 아래와 같습니다.

실제로 얻어지는 영상에 대해 아래와 같은 식으로 표현합니다.

// 얻는 영상 = 원본 영상 + 잡음
f(x, y) = s(x, y) + n(x, y)

잡음이 생성되는 방식을 잡음 모델이라고 하며, 가장 대표적인 잡음 모델은 가우시안 잡음 모델입니다.
잡음을 생성하는 예제 코드는 아래와 같습니다.

Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE); // 원본 영상
if (src.empty())
{
	cerr << "image open error" << endl;
	return;
}

Mat noise(src.size(), CV_32SC1);
randn(noise, 0, 20); // 잡음

Mat dst;
add(src, noise, dst, Mat(), CV_8U); // 원본 + 잡음

imshow("src", src);
imshow("dst", dst);
waitKey();

destroyAllWindows();

잡을을 제거 하기 위해서는 잡음의 픽셀값이 주변 영상의 픽셀값과 크게 차이가 없게 해야하며, 기존에 존재하는 엣지도 보존해야 합니다.

양방향 필터는 이러한 잡음을 제거하는 필터입니다. OpenCV에서는 양방향 필터에 대한 함수를 제공합니다.

/**
@param src 입력 영상
@param dst 출력 영상
@param d 필터링에 사용되는 이웃 픽셀과의 거리. -1 자동 계산
@param sigmaColor 색 공간 가우시안 필터 표준편차
@param sigmaSpace 좌표 공간 가우시안 필터 표준편차
@param borderType 가장자리 픽셀 ㅏㅂㅇ식
 */
CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT );

양방향 필터에 대한 예제 코드는 아래와 같습니다.

// 원본 영상
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
	cerr << "image open error" << endl;
	return;
}

// 잡음 추가
Mat noise(src.size(), CV_32SC1);
randn(noise, 0, 5);
Mat src_noise;
add(src, noise, src_noise, Mat(), CV_8U);

// 양방향 필터
Mat bilateral;
bilateralFilter(src_noise, bilateral, -1, 10, 5);

imshow("noise", src_noise);
imshow("bilateral", bilateral);

waitKey();
destroyAllWindows();

출력 결과는 아래와 같습니다.