** OPENCV 4로 배우는 컴퓨터 비전과 머신러닝 도서 정리내용
영상처리에서 필터링이란 영상에서 원하는 정보만 통과시키고 원치 않는 정보는 걸러 내는 작업이다. 보통 마스크 라고 부르는 작은 크기의 행렬을 이용한다. 마스크는 필터링의 성격을 정의하는 행렬이며 커널, 윈도우 라고도 부르고 경우에 따라 마스크 자체를 필터라고 부르기도 한다. 마스크 행렬의 원소는 보통 실수로 구성된다. 다양한 크기의 행렬로 표현되며 현재 필터링 작업을 수행하는 기준 픽셀 위치를 나타내는 고정점이 있다.
입력 영상의 모든 픽셀 위로 마스크 행렬을 이동시키면서 마스크 연산을 수행하는 방식이다. 마스크 연산이란 마스크 행렬의 모든 원소에 대하여 마스크 행렬 원소 값과 같은 위치에 있는 입력 영상 픽셀 값을 서로 곱한 후, 그 결과를 모두 더하는 연산이다. 그리고 그 결과를 출력 영상에서 고정점 위치에 대응되는 픽셀 값으로 설정한다.
필터링 결과 영상의 픽셀 값
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)
이때 가장자리에 있는 픽셀은 양 옆과 위의 픽셀이 존재하지 않을 수 있다. 이때는 수식을 적용할 수 없으며 특별한 처리가 필요하다. OpenCV 는 영상의 필터링을 수행할때, 영상의 가장자리 픽셀을 확장하여 영상 바깥쪽에 가상의 픽셀을 만든다. 이때 영상의 바깥쪽 가상의 픽셀값을 어떻게 설정하는가에 따라 필터링 연산 결과가 달라진다. 대부분 실제 영상 픽셀값의 대칭 형태가 되도록 설정되어 있다.
가장자리 픽셀 확장 방식
그 외에 가상 픽셀 값을 0으로 설정하는 BORDER_CONSTANT,
가장자리 픽셀 값을 그대로 연장하는 BORDER_REPLICATE,
가장자리 픽셀값을 한번 더 입력 후 대칭하는 BORDER_REFLECT,
가장자리 픽셀값 입력을 생략 후 대칭하는 BORDER_REFLECT_101 등이 있다.
OpenCV에서 필터 마스크를 사용하는 일반적인 필터링은 filter2D()함수를 이용하여 수행한다.
filter2D(InputArray src, OutputArray dst, int ddepth,
InputArray kernel, Point anchor = Point(-1,-1),
double delta = 0, int borderType = BORDER_DEFAULT);
src : 입력 영상
dst : 출력 영상
ddepth : 결과 영상의 깊이
kernel : 필터링 커널
anchor : 고정점 좌표
delta : 필터링 연산 후 추가적으로 더할 값
borderType : 가장자리 픽셀 확장 방식
filter2D()함수를 사용하여 영상에 엠보싱 필터링을 적용해본다. 입력영상에서 픽셀 값 변화가 적은 평탄한 영역은 회색으로 설정하고 객체의 경계 부분은 좀 더 밝거나 어둡게 설정하면 엠보싱 느낌이 난다.
void filter_embossing() {
Mat src = imread("rose.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return;
}
float data[] = { -1, -1, 0, -1, 0, 1, 0, 1, 1 };
Mat emboss(3, 3, CV_32FC1, data);
Mat dst;
filter2D(src, dst, -1, emboss, Point(-1, -1), 128);
imshow("src", src);
imshow("dst", dst);
waitKey();
destroyAllWindows();
}
대각선 방향으로 픽셀 값이 급격하게 변할때 결과 영상의 픽셀값이 0보다 훨씬 크거나 또는 0보다 훨씬 작은 값을 가지게 한다. 픽셀값이 크게 바뀌지 않는 영역은 픽셀값이 0에 가까운 값을 가지게 된다. 결과영상에 128을 더해 어두워 진것을 밝게 만들어 보기 좋게 만든다.
커널 원소 값을 오른쪽 아래로 향하는 대각선이 아닌 왼쪽 아래로 향하는 대각선으로 마스크 필터링 행렬을 새로 생성하니 위 결과와 반대로 명암의 방향이 반대로 출력된 모습을 볼 수 있었다.