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

[컴퓨터 비전 & 머신러닝] 영상의 필터링

728x90

영상처리에서 필터링이란 영상에서 원하는 정보만 통과시키고 원치 않는 정보는 걸러 내는 작업이다, 영상에서 지저분한 노이즈를 걸러내어 영상을 깔끔하게 할 수 있고, 부드러운 느낌을 제거함으로써 영상을 좀 더 날카로운 느낌이 나도록 만들 수 있다

 

영상의 필터링은 마스트라도 부르고 작은 크기의 행렬을 이용한다 커널, 윈도우라고도 부르며 경우에 따라서는 마스크 자체를 필터라고 부르기도 한다

 

다양한 필터 마스크 모양

다양한 필터 마스크에서 진한색으로 표시한 위치는 고정점을 나타낸다, 고정점은 현재 필터링 작업을 수행하고 있는 기준 픽셀 위치를 나타내고, 대부분의 경우 마스크 행렬 정중앙을 고정점으로 사용한다

 

마스크를 이용한 필터링은 입력 영상의 모든 픽셀 위로 마스크 행렬을 이동시키면서 마스크 연산을 수행하는 방식으로 이루어진다 마스트 연산의 결과를 출력 영상에서 고정점 위치에 대응되는 픽셀 값으로 설정한다

 

마스크 연산 : 마스크 행렬의 모든 원소에 대하며 마스크 행렬 원소 값과 같은 위치에 있는 입력 영상 픽셀 값을 서로 곱한 후 , 그 결과를 모두 더하는 연산

 

g(x,y) = m(0,0)f(x-1,y-1) + m(1,0)f(x,y-1) + m(2,0)f(x+1,y-1) 

          + m(0,1)f(x-1,y) + m(1,1)f(x,y) + m(2,1)f(x+1,y) 

          + m(0,2)f(x-1,y+1) + m(1,2)f(x,y+1) + m(2,2)f(x+1,y+1) 

 

g(x,y)에 대한 값을 구했다면 한 픽셀 옆으로 이동하면서 영상 전체 픽셀에 대해 수행하면 필터링이 완료된다

 

하지만 영상의 맨 바깥쪽, 가장자리 픽셀에서는 앞서 설명한 수식을 그대로 적용하기가 어렵다 영상의 가장자리 픽셀을 필터링하기 위해서는 특별한 처리가 필요하다

영상의 가장자리 픽셀을 확장하여 영상 바깥쪽에 가상의 픽셀을 만든다. 이때 영상의 바깥쪽 가상의 픽셀 값을 어떻게 설정하는가에 따라 필터링 연산 결과가 달라진다.

 

핑크색 픽셀은 영상에 실제 존재하는 픽셀이고, 점선으로 표현된 파란색 픽셀은 필터링 연산 시 사용할 가상의 픽셀이다

 

BorderTypes 열거형 상수 설명
BORDER_CONSTANT 0 0 0 a b c d e f g h 0 0 0
BORDER_REPLICATE a a a a b c d e f g h h h h
BORDER_REFLECT c b a a b c d e f g h h g f
BORDER_REFLECT_101 d c b a b c d e f g h g f e

OpenCV에서 필터마스크를 사용하는 일반적인 필터링은 filter2D() 함수를 이용하는 것이다

filter2D 함수는 src 영상에 kernel 필터를 이용하여 필터링을 수행하고, 그 결과를 dst에 저장한다

 

filter2D 함수를 사용해서 영상에 엠보싱 필터링을 적용할 수 있다. 엠보싱이란 직물이나 동이, 금속판 등에 올록볼록한 형태로 만든 객체의 윤곽 또는 무늬를 뜻하며 엠보싱 필터는 입력 영상을 엠보싱 느낌이 나도록 변환하는 필터이다, 픽셀 값 변화가 적은 평탄한 영역은 회색으로 설정하고, 객체의 경계 부분은 좀 더 밝거나 어둡게 설정하면 엠보싱 느낌이 난다

 

대각선 방향으로 -1, 1의 값이 지정되어 있는 3x3 행렬이다. 이 필터 마스크를 사용하여 필터링을 수행하면 대각선 방향으로 픽셀 값이 급격하게 변하는 부분에서 결과 영상 픽셀 값이 0보다 훨씬 크거나 0보다 훨씬 작은 값을 가지게 된다

음수 값이 포화연산으로 인해 0이 되어버리기 때문에 엠보싱 필터를 구현할 때에는 결과 영상에 128을 더하는 것이 보기에 좋다

void filter_embossing()
{
	Mat src = imread("rose.bmp", IMREAD_GRAYSCALE);
	Mat src2 = imread("lenna.bmp", IMREAD_GRAYSCALE);
	Mat src3 = imread("hawkes.bmp", IMREAD_GRAYSCALE);


	float data[] = { -1, -1, 0, -1, 0, 1, 0, 1, 1 };
	Mat emboss(3, 3, CV_32FC1, data);

	Mat dst, dst2, dst3;
	filter2D(src, dst, -1, emboss, Point(-1, -1), 128);
	filter2D(src2, dst2, -1, emboss, Point(-1, -1), 128);
	filter2D(src3, dst3, -1, emboss, Point(-1, -1), 128);

	imshow("src", src);
	imshow("dst", dst);
	imshow("src2", src2);
	imshow("dst2", dst2);
	imshow("src3", src3);
	imshow("dst3", dst3);

	waitKey();
	destroyAllWindows();
}

728x90