C - 기본적인 영상처리

Updated:

제가 C언어를 공부하면서 배웠던 문제를 공유하겠습니다.

이번 post는 간단히 raw 이미지파일을 읽어 들이고, 색 반전, 밝기 조절, 회전을 한 뒤 파일에 저장하는 것입니다.

입력의 lena파일은 512*512 size의 사진파일입니다.

원본_rena

#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