C - Mask Filter 적용해보기
Updated:
제가 C언어를 공부하면서 배웠던 문제를 공유하겠습니다.
이번 post는 여러 Filter를 이미지에 적용해보는 저장하는 문제입니다.
입력의 lena파일은 512*512 size의 raw 파일입니다.
파일 입,출력 포스팅에 있는 주석들은 생략하였습니다.
적용해본 필터는 Mean, Laplacian, Sobel, Median filter입니다. 각 필터의 특징은 아래와 같습니다.
- Mean Filter
- 평균값 필터라고도 하며, 영상을 부드럽게 하는 효과가 있다.
- Laplacian Filter
- 영상의 경계를 돋보이게 하거나 경계점들을 추출한다.
- Sobel Filter
- 영상의 경계점들을 추출한다.
- 가로방향의 Mask와 세로방향의 Mask를 각각 영상에 적용한 후 그 결과들을 더하여 결과 영상을 출력한다.
- Median Filter
- Median Filter는 Mask를 사용하지 않지만, 3 x 3단위로 Filtering을 하는 것은 동일하다.
- 위의 그림에서 T의 값은 A~I의 평균값이 아닌 중간값(순서가 중간 즉, 5번째)인 값이 된다.
각 mask filter는 아래와 같습니다.
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HEI 512
#define WID 512
#define BYTE unsigned char
#define mask_size 3
int sobel_ver[3][3] = { { -1,-2,-1 },{ 0,0,0 },{ 1,2,1 } };
int sobel_hor[3][3] = { { -1,0,1 },{ -2,0,2 },{ -1,0,1 } };
void main()
{
int i, j;
int k, z = 0;
FILE *fin = fopen("Lena_512.raw", "rb");
FILE *fout1 = fopen("Mean_Lena.raw", "wb");
FILE *fout2 = fopen("Median_Lena.raw", "wb");
FILE *fout3 = fopen("Laplacian_1_Lena.raw", "wb");
FILE *fout4 = fopen("Laplacian_2_Lena.raw", "wb");
FILE *fout5 = fopen("Sobel_Ver_Lena.raw", "wb");
FILE *fout6 = fopen("Sobel_Hor_Lena.raw", "wb");
BYTE **ori_pic = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
ori_pic[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
for (i = 0; i < HEI; i++)
{
fread(ori_pic[i], sizeof(BYTE), WID, fin);
}
//////////////////////////////////////////////////////////////////
BYTE **modi_Mean = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
modi_Mean[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
BYTE **modi_Median = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
modi_Median[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
BYTE **modi_Laplacian_1 = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
modi_Laplacian_1[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
BYTE **modi_Laplacian_2 = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
modi_Laplacian_2[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
BYTE **modi_Sobel_Ver = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
modi_Sobel_Ver[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
BYTE **modi_Sobel_Hor = (BYTE**)malloc(HEI * sizeof(BYTE*));
for (i = 0; i < HEI; i++)
{
modi_Sobel_Hor[i] = (BYTE*)malloc(WID * sizeof(BYTE));
}
/////////////////////////////////////////////////////////////////////// MEAN MASK
const int half_mask_size = mask_size / 2;
for (i = half_mask_size; i < HEI - half_mask_size; i++)
{
for (j = half_mask_size; j < WID - half_mask_size; j++)
{
double temp = 0;
for (int my = -half_mask_size; my <= half_mask_size; my++)
{
for (int mx = -half_mask_size; mx <= half_mask_size; mx++)
{
temp += ori_pic[i + my][j + mx];
}
}
temp /= (mask_size * mask_size);
modi_Mean[i][j] = (BYTE)(temp + 0.5);
}
}
/////////////////////////////////////////////////////////////////////// MEDIAN MASK
int num[mask_size*mask_size];
for (i = half_mask_size; i < HEI - half_mask_size; i++)
{
for (j = half_mask_size; j < WID - half_mask_size; j++)
{
z = 0;
for (int my = -half_mask_size; my <= half_mask_size; my++)
{
for (int mx = -half_mask_size; mx <= half_mask_size; mx++)
{
num[z] = ori_pic[i + my][j + mx];
z++;
}
}
int temp = 0;
for (z = 0; z < mask_size*mask_size; z++)
{
for (int l = 0; l < mask_size*mask_size - 1; l++)
{
if (num[l] > num[l + 1]) //오름차순 배열
{
temp = num[l];
num[l] = num[l + 1];
num[l + 1] = temp;
}
}
}
k = num[mask_size*mask_size / 2];
modi_Median[i][j] = (BYTE)k;
for (z = 0; z < mask_size*mask_size; z++)
{
num[z] = 0;
}
}
}
/////////////////////////////////////////////////////////////////////// Laplacian MASK_경계 돋보이게
for (i = half_mask_size; i < HEI - half_mask_size; i++)
{
for (j = half_mask_size; j < WID - half_mask_size; j++)
{
int temp = 0;
for (int my = -half_mask_size; my <= half_mask_size; my++)
{
for (int mx = -half_mask_size; mx <= half_mask_size; mx++)
{
if (mx == 0 && my == 0)
temp += 9 * ori_pic[i + my][j + my];
else
temp += (-1) * ori_pic[i + my][j + mx];
}
}
if (temp >= 0)
if (temp < 255)
modi_Laplacian_1[i][j] = (BYTE)temp;
else
modi_Laplacian_1[i][j] = 255;
else
modi_Laplacian_1[i][j] = 0;
}
}
/////////////////////////////////////////////////////////////////////// Laplacian MASK_경계점 추출
for (i = half_mask_size; i < HEI - half_mask_size; i++)
{
for (j = half_mask_size; j < WID - half_mask_size; j++)
{
int temp = 0;
for (int my = -half_mask_size; my <= half_mask_size; my++)
{
for (int mx = -half_mask_size; mx <= half_mask_size; mx++)
{
if (mx == 0 && my == 0)
temp += 8 * ori_pic[i + my][j + my];
else
temp += (-1) * ori_pic[i + my][j + mx];
}
}
if (temp >= 0)
modi_Laplacian_2[i][j] = (BYTE)temp;
else
modi_Laplacian_2[i][j] = 0;
}
}
/////////////////////////////////////////////////////////////////////// Sobel MASK_세로 방향의 경계점 추출
for (i = half_mask_size; i < HEI - half_mask_size; i++)
{
for (j = half_mask_size; j < WID - half_mask_size; j++)
{
int temp = 0;
int o = 0, p = 0;
for (int my = -half_mask_size; my <= half_mask_size; my++, o++)
{
for (int mx = -half_mask_size; mx <= half_mask_size; mx++, p++)
{
temp += ori_pic[i + my][j + mx] * sobel_ver[o][p];
//if ((mx == -half_mask_size || mx == half_mask_size) && my == -half_mask_size)
// temp += -1 * ori_pic[i + my][j + my];
//else if(mx == 0 && my == -half_mask_size)
// temp += -2 * ori_pic[i + my][j + my];
//else if((mx == -half_mask_size || mx == half_mask_size) && my == half_mask_size)
// temp += ori_pic[i + my][j + my];
//else if (mx == 0 && my == half_mask_size)
// temp += 2 * ori_pic[i + my][j + my];
}
}
o = 0; p = 0;
if (temp >= 0)
modi_Sobel_Ver[i][j] = (BYTE)temp;
else
modi_Sobel_Ver[i][j] = 0;
}
}
/////////////////////////////////////////////////////////////////////// Sobel MASK_가로 방향의 경계점 추출
for (i = half_mask_size; i < HEI - half_mask_size; i++)
{
for (j = half_mask_size; j < WID - half_mask_size; j++)
{
int temp = 0;
int o = 0, p = 0;
for (int my = -half_mask_size; my <= half_mask_size; my++, o++)
{
for (int mx = -half_mask_size; mx <= half_mask_size; mx++, p++)
{
temp += ori_pic[i + my][j + mx] * sobel_hor[o][p];
//if(mx == -half_mask_size && (my == -half_mask_size || my == half_mask_size))
// temp += -1 * ori_pic[i + my][j + my];
//else if (mx == -half_mask_size && my == 0)
// temp += -2 * ori_pic[i + my][j + my];
//else if (mx == half_mask_size && (my == -half_mask_size || my == half_mask_size))
// temp += 1 * ori_pic[i + my][j + my];
//else if (mx == -half_mask_size && my == 0)
// temp += 2 * ori_pic[i + my][j + my];
}
}
o = 0; p = 0;
if (temp >= 0)
modi_Sobel_Hor[i][j] = (BYTE)temp;
else
modi_Sobel_Hor[i][j] = 0;
}
}
//////////////////////
// 가로 세로 1픽셀씩 못 넣으므로 ori_pic 에서 복사
for (j = 0; j < WID; j++)
{
modi_Mean[0][j] = ori_pic[0][j];
modi_Mean[HEI - 1][j] = ori_pic[HEI - 1][j];
modi_Median[0][j] = ori_pic[0][j];
modi_Median[HEI - 1][j] = ori_pic[HEI - 1][j];
modi_Laplacian_1[0][j] = ori_pic[0][j];
modi_Laplacian_1[HEI - 1][j] = ori_pic[HEI - 1][j];
modi_Laplacian_2[0][j] = ori_pic[0][j];
modi_Laplacian_2[HEI - 1][j] = ori_pic[HEI - 1][j];
modi_Sobel_Ver[0][j] = ori_pic[0][j];
modi_Sobel_Ver[HEI - 1][j] = ori_pic[HEI - 1][j];
modi_Sobel_Hor[0][j] = ori_pic[0][j];
modi_Sobel_Hor[HEI - 1][j] = ori_pic[HEI - 1][j];
}
for (i = 1; i < HEI - 1; i++)
{
modi_Mean[i][0] = ori_pic[i][0];
modi_Mean[i][HEI - 1] = ori_pic[i][HEI - 1];
modi_Median[i][0] = ori_pic[i][0];
modi_Median[i][HEI - 1] = ori_pic[i][HEI - 1];
modi_Laplacian_1[i][0] = ori_pic[i][0];
modi_Laplacian_1[i][HEI - 1] = ori_pic[i][HEI - 1];
modi_Laplacian_2[i][0] = ori_pic[i][0];
modi_Laplacian_2[i][HEI - 1] = ori_pic[i][HEI - 1];
modi_Sobel_Ver[i][0] = ori_pic[i][0];
modi_Sobel_Ver[i][HEI - 1] = ori_pic[i][HEI - 1];
modi_Sobel_Hor[i][0] = ori_pic[i][0];
modi_Sobel_Hor[i][HEI - 1] = ori_pic[i][HEI - 1];
}
////////////////////////////////////////////////////////////
for (i = 0; i < HEI; i++)
{
fwrite(modi_Mean[i], WID, sizeof(BYTE), fout1);
fwrite(modi_Median[i], WID, sizeof(BYTE), fout2);
fwrite(modi_Laplacian_1[i], WID, sizeof(BYTE), fout3);
fwrite(modi_Laplacian_2[i], WID, sizeof(BYTE), fout4);
fwrite(modi_Sobel_Ver[i], WID, sizeof(BYTE), fout5);
fwrite(modi_Sobel_Hor[i], WID, sizeof(BYTE), fout6);
}
///////////////////////////////////////////////////////////////////
for (i = 0; i < HEI; i++)
{
free(ori_pic[i]);
free(modi_Mean[i]);
free(modi_Median[i]);
free(modi_Laplacian_1[i]);
free(modi_Laplacian_2[i]);
free(modi_Sobel_Ver[i]);
free(modi_Sobel_Hor[i]);
}
free(ori_pic);
free(modi_Mean);
free(modi_Median);
free(modi_Laplacian_1);
free(modi_Laplacian_2);
free(modi_Sobel_Ver);
free(modi_Sobel_Hor);
fclose(fin);
fclose(fout1);
fclose(fout2);
fclose(fout3);
fclose(fout4);
fclose(fout5);
fclose(fout6);
}
Leave a comment