티스토리 뷰

영상처리/OpenCV

09. Median filter

빠리빵 2019. 4. 24. 22:46

이번 시간에는 Median filter에 대해서 알아보도록 한다. 효과 및 비교를 위해 03. Accessing pixel values 에서 다루었던 salt and pepper noise와 07. mean / gaussian filter 에서 다루었던 mean filter를 사용한다.


먼저 이전에 배웠던 Mean filter에 대해 간단하게 다시 다루면, center pixel을 중심으로 kernel에서 같은 weight를 적용하여 값을 변경한다. 이 경우 white pixel(혹은 black pixel)은 mean filter를 적용하는 과정에서 큰 영향을 끼칠 수 있다. (bad pixel과 같이 눈에 띄는 상황이라면 dot artifact가 생겨날 수 있다.)  


Median filter는 mean filter와 다르게 convolution operation을 적용하는 것이 아니다. 이것은 non linear filter이며, central 이웃 값들을 정렬한 상태에서 middle 값을 선택한다. 따라서 white(or black)과 같이 data들의 중심에서 멀리 벗어나는 outlier 값들은 제외시킬 수 있다. 하지만 단점으로 편차가 적은 영역에서는 대부분이 비슷한 값들로 치환되면서 detail이 떨어질 수 있겠다. 아래의 비교 영상에서 확인해보자.


얼핏 보기엔 mean filter와 median filter 모두 noise가 제거된 것처럼 보일 수 있다.


하지만 확대해보면 Mean filter의 경우 어두운 영역에서는 white pixel의 영향이 남아 얼룩이 보이는 것을 확인할 수 있다.  위에서 언급했던 outlier 값이 영향을 끼쳐 부효과가 나타나는 것이다. 이에 비해 Median filter의 경우 깨끗한 것을 확인할 수 있다.


Median filter의 경우 edge의 sharpness가 mean filter 대비 어느정도 보존되는 것을 볼 수 있다. 이것은 mean filter는 weight를 동일하게 섞어버리는 것에 비해, median filter의 경우 두 영역의 경계면 근처에서 반대 영역의 data들은 outlier로 처리하여 버리기 때문에 경계가 뚜렷해지는 것이다. 


대신 uniform 영역에서 detail은 outlier data들의 영향이 큰데(예로 얼굴의 점을 생각하면 되겠다.), 이러한 data들을 주위 값들로 치환해버리기 때문에 detail이 떨어지는 것을 확인할 수 있다.

#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include<random>

using namespace std;
using namespace cv;

void saltAndPepper(Mat image, int n) {
	default_random_engine generator;
	uniform_int_distribution<int> randomRow(0, image.rows - 1);
	uniform_int_distribution<int> randomCol(0, image.cols - 1);

	int i, j;
	for (int k = 0; k < n; k++) {
		// random image coordinate
		i = randomCol(generator);
		j = randomRow(generator);

		if (image.type() == CV_8UC1) { // gray-level image 
			// single-channel 8-bit image
			image.at<uchar>(j, i) = 255;
		}
		else if (image.type() == CV_8UC3) { // color image
			// 3-channel image
			image.at<Vec3b>(j, i)[0] = 255;
			image.at<Vec3b>(j, i)[1] = 255;
			image.at<Vec3b>(j, i)[2] = 255;
		}
	}
}

int main() {
	Mat image = imread("lena.tif", IMREAD_COLOR);
	Mat medianFilteredImage;
	Mat meanFilteredImage;

	saltAndPepper(image, 3000);
	
	medianBlur(image, medianFilteredImage, 5);
	blur(image, meanFilteredImage, Size(5,5));
	
	imwrite("saltAndPepper.bmp", image);
	imwrite("medianFilteredImage.bmp", medianFilteredImage);
	imwrite("meanFilteredImage.bmp", meanFilteredImage);

	waitKey(0);
}

'영상처리 > OpenCV' 카테고리의 다른 글

11. Laplacian  (0) 2019.05.02
10. Directional Filter(Sobel)  (0) 2019.04.27
08. Downsampling  (4) 2019.04.22
07. mean / gaussian filter  (1) 2019.04.18
06. Writing efficient scanning loops  (0) 2019.04.16
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함