이번 글에서는 미디언 필터(median filter)에 대해 알아보겠습니다.
영상의 잡음 중에는 소금과 후추를 뿌린 것같은 소금, 후추 잡음이 있습니다. 잡음의 픽셀값이 0 또는 255이여서 흰색과 검은 소금 후추를 뿌린것 같다하여 생긴 이름입니다.
소금, 후추 잡음을 생성하는 예제 코드는 아래와 같습니다.
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
cerr << "image open error" << endl;
return;
}
Mat noise;
src.copyTo(noise);
int noise_count = src.total() / 100;
for (int i = 0 ; i < noise_count ; i++)
{
int x = rand() % noise.cols;
int y = rand() % noise.rows;
// 소금, 후추 잡음 생성
noise.at<uchar>(y, x) = (i % 2) * 255;
}
imshow("src", src);
imshow("noise", noise);
waitKey();
destroyAllWindows();
미디언 필터는 소금 후추 잡음과 같이 잡음의 픽셀 값이 주변 값과 차이가 클 때 사용하면 효과적인 필터입니다.
미디언 필터는 주변 픽셀에 대한 값을 정렬한 뒤 중간 값을 새로운 값으로 사용합니다.
해당 방식을 이미지로 표현하면 아래와 같습니다.
OpenCV에서 미디언 필터에 대한 함수를 제공합니다.
/**
@param src 입력 영상
@param dst 출력 영상
@param ksize 필터 크기. 3보단 큰 홀수(for example: 3, 5, 7 ...)
*/
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
미디언 필터 예제 코드는 아래와 같습니다.
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
cerr << "image open error" << endl;
return;
}
Mat noise;
src.copyTo(noise);
int noise_count = src.total() / 100;
for (int i = 0 ; i < noise_count ; i++)
{
int x = rand() % noise.cols;
int y = rand() % noise.rows;
// 소금, 후추 잡음 생성
noise.at<uchar>(y, x) = (i % 2) * 255;
}
Mat median;
medianBlur(src, median, 3);
imshow("src", src);
imshow("noise", noise);
imshow("median", median);
waitKey();
destroyAllWindows();
실행 결과는 아래와 같습니다.