C - 기본적인 영상처리
Updated:
제가 C언어를 공부하면서 배웠던 문제를 공유하겠습니다.
이번 post는 간단히 raw 이미지파일을 읽어 들이고, 색 반전, 밝기 조절, 회전을 한 뒤 파일에 저장하는 것입니다.
입력의 lena파일은 512*512 size의 사진파일입니다.
#pragma warning(disable:4996);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define VER 512 // VER = 512
#define HOR 512 // HOR = 512
#define F_SIZE (VER*HOR) //F_SIZE = 512*512
/* 함수선언*/
unsigned char* alloc_pic(int SIZE); //함수 포인터 선언
unsigned char** alloc_pic_2d(int width, int height); //더블 함수 포인터 선언
int main()
{
int i, j;
unsigned char* ori_pic = alloc_pic(F_SIZE);
//alloc_pic(사이즈가 512*512)일 때 포인터 변수 *ori_pic
unsigned char* modi_pic = alloc_pic(F_SIZE);
//alloc_pic(사이즈가 512*512)일 때 포인터 변수 *modi_pic : 밝기 조절한 값
unsigned char** ori_pic_2d = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *ori_pic_2d
unsigned char** modi_pic_2d = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *modi_pic_2d : 색반전 시킨 값
unsigned char** ori_pic_reloc = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *ori_pic_reloc
unsigned char** modi_pic_reloc1 = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *modi_pic_reloc1 : 90도 돌린 값
unsigned char** modi_pic_reloc2 = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *modi_pic_reloc : 180도 돌아간 값 // 이 변수의 갯수를 조절하여 회전각을 바꿀 수 있음(0도,90도,180도,270도)
unsigned char** ori_pic_rev1 = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *ori_pic_rev1
unsigned char** modi_pic_rev1 = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *modi_pic_rev1 : 상하 반전
unsigned char** ori_pic_rev2 = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *ori_pic_rev1
unsigned char** modi_pic_rev2 = alloc_pic_2d(HOR, VER);
//alloc_pic_2d(사이즈가 512*512)일 때 더블 포인터 변수 *modi_pic_rev2 : 좌우 반전
FILE* fin1, *fin2, *fout1, *fout2;
fin1 = fopen("Lena_512.raw", "rb"); //"Lena_512"를 만들고 입력 스트림 생성
fout1 = fopen("Copy_Lena_512_Inc.raw", "wb"); //"Copy_Lena"를 만들고 출력 스트림 생성
fin2 = fopen("Lena_512.raw", "rb"); //"Lena_512"를 만들고 입력 스트림 생성
fout2 = fopen("Copy_Lena_512_2d_Rev.raw", "wb"); //"Copy_Lena_2d"를 만들고 출력 스트림 생성
FILE* fin3 = fopen("Lena_512.raw", "rb"); //"Lena_512"를 만들고 입력 스트림 생성
FILE* fout3 = fopen("Copy_Lena_512_reloc.raw", "wb"); //"Copy_Lena_512_reloc"를 만들고 출력 스트림 생성
FILE* fin4 = fopen("Lena_512.raw", "rb"); //"Lena_512"를 만들고 입력 스트림 생성
FILE* fout4 = fopen("Copy_Lena_512_rev_UD.raw", "wb"); //"Copy_Lena_512_rev1"를 만들고 출력 스트림 생성
FILE* fin5 = fopen("Lena_512.raw", "rb"); //"Lena_512"를 만들고 입력 스트림 생성
FILE* fout5 = fopen("Copy_Lena_512_rev2_LR.raw", "wb"); //"Copy_Lena_512_rev2"를 만들고 출력 스트림 생성
if (!fin1)
{
printf("ERROR :: File Can't Read\n"); //fin1이 0일 때 에러 출력 및 종료
exit(1);
}
if (!fout1)
{
printf("ERROR :: File Can't Save\n"); //fout1이 0일 때 에러 출력 및 종료
exit(1);
}
if (!fin2)
{
printf("ERROR :: File Can't Read\n"); //fin2가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fout2)
{
printf("ERROR :: File Can't Save\n"); //fout2가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fin3)
{
printf("ERROR :: File Can't Read\n"); //fin3가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fout3)
{
printf("ERROR :: File Can't Save\n"); //fout3가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fin4)
{
printf("ERROR :: File Can't Read\n"); //fin4가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fout4)
{
printf("ERROR :: File Can't Save\n"); //fout4가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fin5)
{
printf("ERROR :: File Can't Read\n"); //fin5가 0일 때 에러 출력 및 종료
exit(1);
}
if (!fout5)
{
printf("ERROR :: File Can't Save\n"); //fout5가 0일 때 에러 출력 및 종료
exit(1);
}
//===============================================================================
// 밝기 증가
fread((void*)ori_pic, sizeof(unsigned char), F_SIZE, fin1);
memcpy(modi_pic, ori_pic, F_SIZE * sizeof(unsigned char));
for (i = 0; i < F_SIZE; i++)
{
modi_pic[i] += 25;
if (modi_pic[i] > 255) // 255 초과시 255로 saturation
modi_pic = 255;
} // 그림의 밝기 증가
fwrite((void*)modi_pic, sizeof(unsigned char), F_SIZE, fout1);
//=================================================================================
// 색 반전
for (i = 0; i < VER; i++)
fread(ori_pic_2d[i], sizeof(unsigned char), HOR, fin2);
for (j = 0; j < VER; j++)
{
for (i = 0; i < HOR; i++)
{
modi_pic_2d[j][i] = ori_pic_2d[j][i];
}
}
for (j = 0; j < VER; j++)
{
for (i = 0; i < HOR; i++)
{
modi_pic_2d[j][i] = 255 - modi_pic_2d[j][i];
}
} //modi_pic_2d 의 파일들 색반전시킨다.(흑백이므로 255에 가까울수록 백색을 띔)
for (i = 0; i < VER; i++)
fwrite((void*)modi_pic_2d[i], sizeof(unsigned char), HOR, fout2);
//===================================================================================
// 그림 회전
for (i = 0; i < VER; i++)
fread(ori_pic_reloc[i], sizeof(unsigned char), HOR, fin3);
for (j = 0; j < VER; j++)
{
for (i = 0; i < HOR; i++)
{
modi_pic_reloc1[j][i] = ori_pic_reloc[HOR - 1 - i][j];
}
} // ori_pic_2d의 값들을 90도 회전시켜 modi_pic_reloc의 값에 저장(복사)
for (j = 0; j < VER; j++)
{
for (i = 0; i < HOR; i++)
{
modi_pic_reloc2[j][i] = modi_pic_reloc1[HOR - 1 - i][j];
}
} // ori_pic_2d의 값들을 한번 더 90도 회전시켜 modi_pic_reloc의 값에 저장(복사)
for (i = 0; i < VER; i++)
fwrite((void*)modi_pic_reloc2[i], sizeof(unsigned char), HOR, fout3);
//===================================================================================
// 상하 반전
for (i = 0; i < VER; i++)
fread(ori_pic_rev1[i], sizeof(unsigned char), HOR, fin4);
for (j = 0; j < VER; j++)
{
for (i = 0; i < HOR; i++)
{
modi_pic_rev1[j][i] = ori_pic_rev1[HOR - 1 - j][i];
}
} // ori_pic_2d의 값들을 상하 반전시켜 modi_pic_reloc의 값에 저장(복사)
for (i = 0; i < VER; i++)
fwrite((void*)modi_pic_rev1[i], sizeof(unsigned char), HOR, fout4);
//===================================================================================
// 좌우 반전
for (i = 0; i < VER; i++)
fread(ori_pic_rev2[i], sizeof(unsigned char), HOR, fin5);
for (j = 0; j < VER; j++)
{
for (i = 0; i < HOR; i++)
{
modi_pic_rev2[j][i] = ori_pic_rev2[j][HOR - 1 - i];
}
} // ori_pic_2d의 값들을 좌우 반전시켜 modi_pic_reloc의 값에 저장(복사)
for (i = 0; i < VER; i++)
fwrite((void*)modi_pic_rev2[i], sizeof(unsigned char), HOR, fout5);
fclose(fin1);
fclose(fout1);
fclose(fin2);
fclose(fout2);
fclose(fin3);
fclose(fout3);
fclose(fin4);
fclose(fout4);
fclose(fin5);
fclose(fout5);
for (i = 0; i < VER; i++)
{
free(ori_pic_2d[i]);
free(modi_pic_2d[i]);
free(ori_pic_reloc[i]);
free(modi_pic_reloc1[i]);
free(modi_pic_reloc2[i]);
free(ori_pic_rev1[i]);
free(modi_pic_rev1[i]);
free(ori_pic_rev2[i]);
free(modi_pic_rev2[i]);
}
free(ori_pic_rev1);
free(modi_pic_rev1);
free(ori_pic_rev2);
free(modi_pic_rev2);
free(ori_pic_reloc);
free(modi_pic_reloc1);
free(modi_pic_reloc2);
free(ori_pic_2d);
free(modi_pic_2d);
free(ori_pic);
free(modi_pic);
return 0;
}
unsigned char** alloc_pic_2d(int width, int height)
{
unsigned char** pic;
int i;
if ((pic = (unsigned char**)calloc(width, sizeof(unsigned char*))) == NULL)
{
printf("\n malloc_picture : Picture structure \n");
exit(1);
}
for (i = 0; i < height; i++)
{
if ((pic[i] = (unsigned char*)calloc(height, sizeof(unsigned char))) == NULL)
{
printf("\n malloc_picture : Picture structure \n");
exit(1);
}
}
return pic;
}
unsigned char* alloc_pic(int SIZE)
{
unsigned char* pic;
if ((pic = (unsigned char*)calloc(SIZE, sizeof(unsigned char))) == NULL)
{
printf("\n malloc_picture : Picture structure \n");
exit(1);
}
return pic;
}
/*회전시키는 파일을 만들었을 때 행렬 수를 잘못 세어서 HOR-i를 적용하였더니 상관없는 색 반전시키는 파일까지 결과가 이상하게 나오는 현상 발생. 다시 적용하여 [HOR-1-i]로 수정후 확인 한 결과 모든 결과가 정상적으로 출력됨을 확인할 수 있었다.*/
폴더에 잘 생성됨을 확인할 수 있습니다.
- 밝기 변화(증가)
- 색 반전
- 회전(180도)
- 상하 반전
- 좌우 반전
코드가 길게 느껴질 수도 있지만 차근차근 읽다보면 굉장히 쉬운 문제입니다.
반복되는 코드에 대해 함수로 변환하는 것은 추후에 수정하도록 하겠습니다.
Leave a comment