영상 처리하는 공간을 크게 공간 영역, 주파수 영역 2가지로 나눌 수 있습니다.
공간영역에서 처리는 단순히 위치 변수 x,y에 대한 픽셀 값을 처리해주는 과정이라고 생각할 수 있습니다.
그래서 각 픽셀들의 위치 변수 값들이 중요한 역할을 하는 처리 방식입니다.
Mask Filter
이번에는 공간역에서의 다양한 3x3 Mask를 사용하여 영상에 더해줄 수 있는 효과들을 알아보겠습니다.
Mask 필터의 적용 방식은 각 이미지의 공간영역에 마스크를 올려 놓고 대응되는 위치 변수에 대한 픽셀 값들을 곱하여 더한 값을 Mask의 중심점의 새로운 값으로 매핑하는 방식입니다.
( Mask의 영역이 닿지 않는 영상의 외각지역 같은 경우는 padding 기법을 활용합니다. 최외곽의 pixel를 복사해주거나 0또는 255의 값들로 채워서 사이즈를 Mask의 크기에 비례해 증량하고 필터를 적용합니다.)
Mean Filter
평균값 필터라고도 하며 마스크 단위로 평균 값을 새로운 값으로 매핑해주는 방식입니다. 영상을 부드럽게 해주는 효과가 있습니다.
Laplacian Filter
미분을 활용하여 픽셀이 변화하는 지점을 찾아 영상의 경계를 돋보이게 하거나 추출하는 효과를 얻을 수 있습니다.
Sobel Filter
픽셀이 변화하는 지점을 찾아 영상의 경계를 찾는 방식입니다.
가로 방향의 Mask와 세로방향의 Mask가 각각 따로 있으며, 각 각의 중복으로 적용했을 때 효과를 볼 수 있습니다.
Median Filter
Median Filter는 따로 Mask를 사용하지 않습니다. 하지만 의미 자체는 Mask를 씌우것과 동일한 의미로 볼 수 있습니다.
3x3 단위로 중간값을 취득하여 매핑해줍니다. 이럴 경우 noise를 제거하는 효과를 얻을 수 있습니다.
코드 실습
3x3 Mask를 적용하는 과정을 실습합니다.
double Laplacian_[3][3] = { {-1,-1,-1},{-1,9,-1},{-1,-1,-1} };
double Laplacian_E[3][3] = { {-1,-1,-1},{-1,8,-1},{-1,-1,-1} };
double Sobel_VER[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
double Sobel_HOR[3][3] = { {-1,0,1},{-2,0,2},{-1,0,1} };
double Mean[3][3] = { {double(1)/9,double(1) / 9,double(1) / 9},{double(1) / 9,double(1) / 9,double(1) / 9} ,{double(1) / 9,double(1) / 9,double(1) / 9} };
먼저 Mask를 생성해줍니다.
unsigned char** convolution(unsigned char** arr, double filter[3][3]) {
int i, j;
unsigned char** result = alloc_pic_2d(VER, HOR);
for (j = 1; j < VER-1; j++) {
for (i = 1; i < HOR-1; i++) {
int sum = 0;
for (int m = 0; m < 3; m++) {
for (int n = 0; n < 3; n++) {
sum += arr[j + m - 1][ i + n - 1] * filter[m][n];
}
}
if (sum < 0) sum = 0;
else if (sum > 255) sum = 255;
result[j][i] = sum;
}
}
///pading///
for (i = 0; i < VER; i++) {
result[i][0] = 0;
result[i][VER - 1] = 0;
result[0][i] = 0;
result[0][HOR - 1] = 0;
}
return result;
}
다음으로 Mask 연산을 정의해줍니다.
unsigned char** median(unsigned char** arr) {
int i, j;
unsigned char** result = alloc_pic_2d(VER, HOR);
int s[9];
for (j = 1; j < VER - 1; j++) {
for (i = 1; i < HOR - 1; i++) {
s[0] = arr[j - 1][i - 1];
s[1] = arr[j - 1][i];
s[2] = arr[j - 1][i + 1];
s[3] = arr[j][i - 1];
s[4] = arr[j][i];
s[5] = arr[j][i + 1];
s[6] = arr[j + 1][i - 1];
s[7] = arr[j + 1][i];
s[8] = arr[j + 1][i + 1];
std::sort(s, s + 9);
result[j][i] = s[4];
if (result[j][i] < 0) result[j][i] = 0;
else if (result[j][i] > 255) result[j][i] = 255;
}
}
for (i = 0; i < VER; i++) {
result[i][0] = 0;
result[i][VER - 1] = 0;
result[0][i] = 0;
result[0][HOR - 1] = 0;
}
return result;
}
Median 필터의 경우 c++의 algorithm 라이브러리의 sort를 활용하여 정렬을 해주고, 그 중간값을 취득합니다.
output1 = convolution(input, Laplacian_);
output2 = convolution(input, Laplacian_E);
output3 = median(input);
output4 = convolution(input, Mean);
output5 = convolution(input, Sobel_VER);
output6 = convolution(input, Sobel_HOR);
이렇게 총 6개의 처리된 이미지를 획득 할 수 있습니다.
결과
위처럼 공간영역에서 필터를 적용한 영상 처리 이미지를 획득 할 수 있습니다.