본문 바로가기
런닝머신 (ML)

[컴퓨터 비전 & 머신러닝] 잡음 제거 필터링

728x90

영상과 잡음 모델

영상에서 잡음은 주로 영상을 획득하는 과정에서 발생하며, 디지털 카메라에서 사진을 촬영하는 경우에는 광학적 신호를 전기적 신호로 변환하는 센서에서 주로 잡음이 추가된다

디지털 카메라에서 카메라 렌즈가 바라보는 장면을 원본 신호 s(x,y)라고 하고, 여기에 추가되는 잡음을 n(x,y)라고 표현한다면 실제로 카메라에서 획득되는 영상 신호는 f(x,y)이다

 

잡음이 생성되는 방식을 잡음 모델이라고 하며, 가장 대표적인 잡음 모델은 가우시안 잡음 모델이다. 

평균이 0이고 표준 편차가 10인 가우시간 분포 그래프

표준 편차가 작은 가우시안 잡음 모델일수록 잡음에 의한 픽셀 값 변화가 적다

 

OpenCV 에서는 randn() 함수를 사용해 가우시안 잡음으로 구성된 행렬을 생성하여 반환한다

void noise_gaussian()
{
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return;
	}

	imshow("src", src);

	//표준 편차 stddev 값이 10,20,30이 되도록 for 반복문을 수행
	for (int stddev = 10; stddev <= 30; stddev += 10) {
		Mat noise(src.size(), CV_32SC1);
        //평균이 0이고 표준 편차가 stddev인 가우시안 잡음을 생성하여 noise 행렬에 저장
		//noise 행렬은 부호 있는 정수형을 사용하도록 미리 생성하여 randn() 함수에 전달
		randn(noise, 0, stddev);

		Mat dst;
		//입력 영상 src에 가우시안 잡음 noise를 더하여 결과 영상 dst를 생성
		add(src, noise, dst, Mat(), CV_8U);

		String desc = format("stddev = %d", stddev);
		putText(dst, desc, Point(10, 30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255), 1, LINE_AA);
		imshow("dst", dst);
		waitKey();
	}

	destroyAllWindows();
}

원본 영상에 비해 가우시안 잡음이 추가된 결과 영상은 거칠고 지저분해 보이는 것을 확인할 수 있다. 특히 표준편차 값이 증가함에 따라 잡음의 영향이 커지므로 결과 영상이 더욱 지저분해지는 것을 볼 수 있다

 


양방향 필터

 

대부분의 영상에는 가우시안 잡음이 포함되어 있으며 많은 컴퓨터 시스템이 가우시안 잡음을 제거하기 위해 가우시안 필터를 사용한다. 가우시안 필터를 사용하면 주변 픽셀 값이 부드럽게 블러링되면서 잡음의 영향도 크게 줄어든다, 그러나 픽셀 값이 급격하게 변경되는 에지 근방에 동일한 가우시안 필터가 적용되면 잡음뿐만 아니라 에지 성분까지 함께 감소한다

즉, 잡음이 줄어들면서 함께 에지도 무뎌지기 때문에 객체의 윤곽이 흐릿하게 바뀐다 

 

이런 단점을 보완하기 위해 에지 보전 잡음 제거 필터에 대해 연구했다. 그중 양방향 필터는 에지 성분은 그대로 유지하면서 가우시안 잡음을 효과적으로 제거하는 알고리즘이다

 

f는 입력 영상, g는 출력 영상, p와 q는 픽셀의 좌표, S는 필터 크기, Wp는 양방향 필터 마스크 합이 1이 되도록 만드는 정규화 상수이다. 두 함수의 곱을 통해 에지 근방에서는 가우시안 블러링 효과가 거의 나타나지 않고 에지가 보존된다.

 

OpenCV에서는 bilateralFilter()  함수를 이용하여 양방향 필터를 수행할 수 있다

void filter_bilateral()
{
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return;
	}

	//그레이스케일 레나 영상 src에 평균이 0이고 표준 편차가 5인 가우시안 잡음을 추가
	Mat noise(src.size(), CV_32SC1);
	randn(noise, 0, 5);
	add(src, noise, src, Mat(), CV_8U);

	//표준 편차가 5인 가우시안 필터링을 수행하여 dst1에 저장
	Mat dst1;
	GaussianBlur(src, dst1, Size(), 5);

	//색 공간의 표준 편차는 10, 좌표 공간의 표준 편차는 5를 사용하는 양방향 필터링을 수행하여 dst2에 저장
	Mat dst2;
	bilateralFilter(src, dst2, -1, 10, 5);

	imshow("src", src);
	imshow("dst1", dst1);
	imshow("dst2", dst2);

	waitKey();
	destroyAllWindows();
}

src는 평균이 0이고 표준 편차가 5인 가우시안 잡음이 추가된 영상이다. 이 영상에 대해 표준 편차가 5인 가우시안 필터링을 수행한 dst1을 보면 잡음의 영향을 줄었지만 전체적으로 흐릿하게 변경되었다. 반면에 양방향 필터가 적용된 dst2는배경 사물의 경계는 그대로 유지되었고, 평탄한 영역의 잡음은 크게 줄어들어 눈으로 보기에 매우 깔끔한 느낌을 준다

 


미디언 필터

미디언 필터는 입력 영상에서 자기 자신 픽셀과 주변 픽셀 값 중에서 중간 값을 선택하여 결과 영상 픽셀 값으로 설정하는 필터링 기법이다. 특히 잡음 픽셀 값이 주변 픽셀 값과 큰 차이가 있는 경우 효과적으로 동작한다

 

영상에 추가되는 잡음 중에는 흰색과 검은색으로 구성된 소금&후추 잡음인데 미디언 필터를 사용하면 효과적으로 잡음을 제거할 수 있다

OpenCV에서는 medianBlur() 함수를 사용하여 미디언 필터링을 실행할 수 있다

void filter_median()
{
	Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cerr << "Image load failed!" << endl;
		return;
	}

	//src 영상에서 10%에 해당하는 픽셀 값을 0 또는 255로 설정
	int num = (int)(src.total() * 0.1);
	for (int i = 0; i < num; i++) {
		int x = rand() % src.cols;
		int y = rand() % src.rows;
		src.at<uchar>(y, x) = (i % 2) * 255;
	}

	//표준 편차가 1인 가우시안 필터링을 수행하여 dst1에 저장
	Mat dst1;
	GaussianBlur(src, dst1, Size(), 1);


	//크기가 3인 미디언 필터를 실행하여 dst2에 저장
	Mat dst2;
	medianBlur(src, dst2, 3);

	imshow("src", src);
	imshow("dst1", dst1);
	imshow("dst2", dst2);

	waitKey();
	destroyAllWindows();
}

src 영상은 레나 영상에 10%의 확률로 소금&후추 잡음이 추가된 영상이다. 이 영상에 가우시간 필터를 적용시킨 결과 영상이 dst1이다. 소금&후쿠 잡음에 대해서는 가우시안 블러링을 적용해도 여전히 영상이 지저분하게 보이는 것을 확인할 수 있다. 반면에 미디언 필터를 적용한 dst2 영상에서는 잡음에 의해 추가된 흰색 검은색 픽셀이 효과적으로 제거된 것을 볼 수 있다.

728x90