언어/C

C언어 영상처리 - padding, filters

이게될까 2024. 3. 28. 20:10
728x90
728x90

CNN에서 사용했던 패딩과 똑같은 개념입니다.

2023.12.13 - [인공지능/공부] - CNN - 기본 개념

 

CNN - 기본 개념

우리는 여태까지 FCN으로 tensorflow에서 Dense만 사용해왔다. 그러나 사진과 같은 경우엔 해상도가 만만치 않아 대충 1000*1000이라고 하면 일렬로 나열하면 1000000이 된다. 이게 Dense layer 하나만 거쳐서

yoonschallenge.tistory.com

median filter

중앙값으로 필터를 취하는 것이다.

 

mean filter

여기선 평균값을 취하는 필터이다.

여기서 한번 진행할 때 마다 원래 행렬 크기가 k*k -> (k-2) * (k-2)가 되므로 padding을 붙여준다.

//padding
int padding = 1;

int pwidth = width + padding * 2;
int pheight = height + padding * 2;
int psize = pwidth * pheight;
double* py;
py = (double*)calloc(pwidth * pheight, sizeof(double));
// 일단 원본 값 집어넣기
for (int j = 0; j < height; j++) {
	for (int i = 0; i < width; i++) {
		py[(j + padding) * pwidth + (i + padding)] = y2[j * width + i];
	}
}
// 패딩 값 집어넣기
//하
for (int p = 0; p < padding; p++) {
	for (int i = 0; i < width; i++) {
		py[(p)*pwidth + (i + padding)] = y2[0 * width + i];
	}
}
//좌
for (int p = 0; p < padding; p++) {
	for (int j = 0; j < height; j++) {
		py[(j+padding) * pwidth + p] = y2[j * width];
	}
}
//우
for (int p = 0; p < padding; p++) {
	for (int j = 0; j < height; j++) {
		py[(j + padding) * pwidth + (width + padding)+ p] = y2[(j+1) * width-1];
	}
}

//상
for (int p = 0; p < padding; p++) {
	for (int i = 0; i < width; i++) {
		py[(p+ width + padding)*pwidth + (i + padding)] = y2[(height-1) * width + i];
	}
}

// 좌하 ( 0,0) ~ (padding-1,padding-1)
for (int j = 0; j < padding; j++) {
	for (int i = 0; i < padding; i++) {
		py[(j) * pwidth + (i)] = y2[0 * width + 0];
	}
}
// 우하 (0,pwidth-1 -padding) ~ (padding-1,pwidth-1)
for (int j = 0; j < padding; j++) {
	for (int i = 0; i < padding; i++) {
		py[(j)*pwidth + (width + padding + i)] = y2[1 * width-1];
	}
}
// 좌상
for (int j = 0; j < padding; j++) {
	for (int i = 0; i < padding; i++) {
		py[(height + padding+j)*pwidth + (i)] = y2[(height-1) * width];
	}
}
//우상
for (int j = 0; j < padding; j++) {
	for (int i = 0; i < padding; i++) {
		py[(height + padding + j) * pwidth + (width + padding + i)] = y2[(height) * width-1];
	}
}

일단은 바로 주변값을 집어 넣는 코드이다.

나중에 평균을 취하든 할 것인데 지금은 이거 짜는데만 수정을 많이해서....

// filter

int fsize = 3;

// mean filter
printf("filter start\n");
double* filter;
filter = (double*)calloc(fsize * fsize, sizeof(double));
for (int i = 0; i < fsize * fsize; i++) {
	filter[i] = 1.0 / (fsize * fsize);
}
// 3*3 Gussian Filter
double G3filter[] = {1.0/16,2.0/16,1.0/16,2.0/16,4.0/16,2.0/16,1.0/16,2.0/16,1.0/16};
for (int i = 0; i < 9; i++) printf("%lf ", G3filter[i]);
printf("\n");
double G5filter[] = {1/273.0, 4/ 273.0, 7/ 273.0, 4/ 273.0, 1/ 273.0, 4/ 273.0, 16/ 273.0, 26/ 273.0, 16/ 273.0, 4/ 273.0, 7/ 273.0, 26/ 273.0, 41/ 273.0, 26/ 273.0, 7/ 273.0, 4 / 273.0, 16 / 273.0, 26 / 273.0, 16 / 273.0, 4 / 273.0,1 / 273.0, 4 / 273.0, 7 / 273.0, 4 / 273.0, 1 / 273.0 };
for (int i = 0; i < 25; i++) printf("%lf ", G5filter[i]);
double* y3,sumf;
y3 = (double*)calloc(width * height, sizeof(double));

for (int j = 0; j < height; j++) {
	for (int i = 0; i < width; i++) {
		sumf = 0;
		for (int k = 0; k < fsize; k++) {
			for (int l = 0; l < fsize; l++) {
				sumf += G3filter[k * fsize + l] * py[(j+k) * pwidth + (i+l)];
			}
		}
		y3[j * width + i] = sumf;
	}
	//printf("\n");
}

여기는 필터 관련 코드이다

mean이든 가우시안이든 편한 것으로 사용하면 된다.

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
#include<math.h>

int main() {
	BITMAPFILEHEADER bmpFile, bmpFile2;
	BITMAPINFOHEADER bmpInfo, bmpInfo2;
	FILE* inputFile = NULL, * inputFile2 = NULL;
	inputFile = fopen("originalY.bmp", "rb");
	inputFile2 = fopen("AICenterY_Noise.bmp", "rb");
	//inputFile2 = fopen("AICenterY.bmp", "rb");

	fread(&bmpFile, sizeof(BITMAPFILEHEADER), 1, inputFile);
	fread(&bmpInfo, sizeof(BITMAPINFOHEADER), 1, inputFile);
	fread(&bmpFile2, sizeof(BITMAPFILEHEADER), 1, inputFile2);
	fread(&bmpInfo2, sizeof(BITMAPINFOHEADER), 1, inputFile2);

	int width = bmpInfo.biWidth;
	int height = bmpInfo.biHeight;
	int size = bmpInfo.biSizeImage;
	int bitCnt = bmpInfo.biBitCount;
	int stride = (((bitCnt / 8) * width) + 3) / 4 * 4,max;
	double Y, Cb, Cr,*y,*cb,*cr,*y2,mse=0,psnr=0;
	printf("width,height,size,bitCnt,stride\n");
	printf("%d %d %d %d %d\n",width,height,size,bitCnt,stride);
	int width2 = bmpInfo2.biWidth;
	int height2 = bmpInfo2.biHeight;
	int size2 = bmpInfo2.biSizeImage;
	int bitCnt2 = bmpInfo2.biBitCount;
	int stride2 = (((bitCnt2 / 8) * width2) + 3) / 4 * 4;
	printf("%d %d %d %d %d\n", width2, height2, size2, bitCnt2, stride2);

	unsigned char* inputImg = NULL, * outputImg = NULL,* I, * inputImg2 = NULL;
	inputImg = (unsigned char*)calloc(size, sizeof(unsigned char));
	inputImg2 = (unsigned char*)calloc(size, sizeof(unsigned char));
	outputImg = (unsigned char*)calloc(size, sizeof(unsigned char));
	y = (double*)calloc(width* height, sizeof(double));
	y2 = (double*)calloc(width * height, sizeof(double));

	cb = (double*)calloc(width * height, sizeof(double));
	cr = (double*)calloc(width * height, sizeof(double));
	I = (unsigned char*)calloc(width * height, sizeof(unsigned char));
	fread(inputImg, sizeof(unsigned char), size, inputFile);
	fread(inputImg2, sizeof(unsigned char), size, inputFile2);
	// input 
	for (int j = 0; j < height; j++) {
		for (int i = 0; i < width; i++) {
			y[j * width + i] = inputImg[j * stride + 3 * i ];
			y2[j * width + i] = inputImg2[j * stride + 3 * i ];
		}
	}


	// Algorithm
	
	//padding
	int padding = 1;

	int pwidth = width + padding * 2;
	int pheight = height + padding * 2;
	int psize = pwidth * pheight;
	double* py;
	py = (double*)calloc(pwidth * pheight, sizeof(double));
	// 일단 원본 값 집어넣기
	for (int j = 0; j < height; j++) {
		for (int i = 0; i < width; i++) {
			py[(j + padding) * pwidth + (i + padding)] = y2[j * width + i];
		}
	}
	// 패딩 값 집어넣기
	//하
	for (int p = 0; p < padding; p++) {
		for (int i = 0; i < width; i++) {
			py[(p)*pwidth + (i + padding)] = y2[0 * width + i];
		}
	}
	//좌
	for (int p = 0; p < padding; p++) {
		for (int j = 0; j < height; j++) {
			py[(j+padding) * pwidth + p] = y2[j * width];
		}
	}
	//우
	for (int p = 0; p < padding; p++) {
		for (int j = 0; j < height; j++) {
			py[(j + padding) * pwidth + (width + padding)+ p] = y2[(j+1) * width-1];
		}
	}
	
	//상
	for (int p = 0; p < padding; p++) {
		for (int i = 0; i < width; i++) {
			py[(p+ width + padding)*pwidth + (i + padding)] = y2[(height-1) * width + i];
		}
	}

	// 좌하 ( 0,0) ~ (padding-1,padding-1)
	for (int j = 0; j < padding; j++) {
		for (int i = 0; i < padding; i++) {
			py[(j) * pwidth + (i)] = y2[0 * width + 0];
		}
	}
	// 우하 (0,pwidth-1 -padding) ~ (padding-1,pwidth-1)
	for (int j = 0; j < padding; j++) {
		for (int i = 0; i < padding; i++) {
			py[(j)*pwidth + (width + padding + i)] = y2[1 * width-1];
		}
	}
	// 좌상
	for (int j = 0; j < padding; j++) {
		for (int i = 0; i < padding; i++) {
			py[(height + padding+j)*pwidth + (i)] = y2[(height-1) * width];
		}
	}
	//우상
	for (int j = 0; j < padding; j++) {
		for (int i = 0; i < padding; i++) {
			py[(height + padding + j) * pwidth + (width + padding + i)] = y2[(height) * width-1];
		}
	}



	// filter

	int fsize = 3;

	// mean filter
	printf("filter start\n");
	double* filter;
	filter = (double*)calloc(fsize * fsize, sizeof(double));
	for (int i = 0; i < fsize * fsize; i++) {
		filter[i] = 1.0 / (fsize * fsize);
	}
	// 3*3 Gussian Filter
	double G3filter[] = {1.0/16,2.0/16,1.0/16,2.0/16,4.0/16,2.0/16,1.0/16,2.0/16,1.0/16};
	for (int i = 0; i < 9; i++) printf("%lf ", G3filter[i]);
	printf("\n");
	double G5filter[] = {1/273.0, 4/ 273.0, 7/ 273.0, 4/ 273.0, 1/ 273.0, 4/ 273.0, 16/ 273.0, 26/ 273.0, 16/ 273.0, 4/ 273.0, 7/ 273.0, 26/ 273.0, 41/ 273.0, 26/ 273.0, 7/ 273.0, 4 / 273.0, 16 / 273.0, 26 / 273.0, 16 / 273.0, 4 / 273.0,1 / 273.0, 4 / 273.0, 7 / 273.0, 4 / 273.0, 1 / 273.0 };
	for (int i = 0; i < 25; i++) printf("%lf ", G5filter[i]);
	double* y3,sumf;
	y3 = (double*)calloc(width * height, sizeof(double));

	for (int j = 0; j < height; j++) {
		for (int i = 0; i < width; i++) {
			sumf = 0;
			for (int k = 0; k < fsize; k++) {
				for (int l = 0; l < fsize; l++) {
					sumf += G3filter[k * fsize + l] * py[(j+k) * pwidth + (i+l)];
				}
			}
			y3[j * width + i] = sumf;
		}
		//printf("\n");
	}
	

	//get Quality
	unsigned char org, out;
	for (int j = 0; j < height; j++) {
		for (int i = 0; i < width; i++) {
			org = (unsigned char)(y[j * width + i] > 255 ? 255 : (y[j * width + i] < 0 ? 0 : y[j * width + i]));
			out = (unsigned char)(y3[j * width + i] > 255 ? 255 : (y3[j * width + i] < 0 ? 0 : y3[j * width + i]));
			mse += (double)((org - out) * (org - out));

		}
	}
	mse /= (height * width);
	max = pow(2, bitCnt/3) - 1;
	psnr = mse != 0.0 ? 10.0 * log10(max * max / mse) : 99.99;
	printf("mse = %.2lf\npsnr = %.2lf\n", mse, psnr);

	// output

	for (int j = 0; j < height; j++) {
		for (int i = 0; i < width; i++) {
			outputImg[j * stride + 3 * i + 0] = (unsigned char)(y3[j * width + i]>255 ? 255 : (y3[j * width + i]< 0 ? 0 : y3[j * width + i]));
			outputImg[j * stride + 3 * i + 1] = (unsigned char)(y3[j * width + i] > 255 ? 255 : (y3[j * width + i] < 0 ? 0 : y3[j * width + i]));
			outputImg[j * stride + 3 * i + 2] = (unsigned char)(y3[j * width + i] > 255 ? 255 : (y3[j * width + i] < 0 ? 0 : y3[j * width + i]));
		}
	}

	FILE* outputFile = fopen("Output.bmp", "wb");
	fwrite(&bmpFile, sizeof(BITMAPFILEHEADER),1,outputFile);
	fwrite(&bmpInfo, sizeof(BITMAPINFOHEADER), 1, outputFile);
	fwrite(outputImg, sizeof(unsigned char), size, outputFile);
	free(outputImg);
	fclose(outputFile);
	free(inputImg);
	free(inputImg2);

	free(y);
	free(y2);
	free(py);
	free(y3);
	fclose(inputFile);
	return 0; 
}

 

총 코드이다.

728x90