卷积神经网络相关函数的实现--c语言

一、介绍
这里主要介绍卷积相关函数用c语言实现,如卷积、池化、全零填充等等

二、单核单通道卷积

//单卷积 
#define IMG_SIZE 5
#define W_SIZE 3
#define OUT_SIZE 3
int conv(float img[IMG_SIZE][IMG_SIZE], float w[W_SIZE][W_SIZE], float out[OUT_SIZE][OUT_SIZE])
{
	int i,j,k,r,m,n;
	float tmp;
	
	//单张图片卷积 
	for(k = 0; k <= (IMG_SIZE - W_SIZE); k++)//行卷积 
	{
		for(r = 0; r <= (IMG_SIZE - W_SIZE); r++)//列 
		{
			//单次卷积 
			//点对点相乘,然后结果相加 
			tmp = 0.0;
			for(i = 0; i < W_SIZE; i++)//行 
			{
				for(j = 0; j < W_SIZE; j++)//列 
				{
					//单点计算 
					tmp = tmp + img[i+k][j+r]*w[i][j];
				}
			}
			out[k][r] = tmp;
		}
	}
}

int conv_test()
{
	float x[IMG_SIZE][IMG_SIZE] = { 1,1,1,0,0,
									0,1,1,1,0,
									0,0,1,1,1,
									0,0,1,1,0,
									0,1,1,0,0};
								
	float conv_w[W_SIZE][W_SIZE] = {1,0,1,
									0,1,0,
									1,0,1};
									
	float img_out[OUT_SIZE][OUT_SIZE] = {0};
	int i,j,k,r,m,n;
	
	conv(x, conv_w, img_out);
	printf("输入图片\n");
	for(i = 0; i < 5; i++)
	{
		for(j = 0; j < 5; j++)
			printf("%.1f ", x[i][j]);
		printf("\n ");
	}
	
	printf("输出图片\n");
	for(i = 0; i < 3; i++)
	{
		for(j = 0; j < 3; j++)
			printf("%.1f ", img_out[i][j]);
		printf("\n ");
	}
}

三、单通道池化
最大值池化和平均值池化

//池化 
#define IN_SIEZE  4
#define OUT_SIEZE 2
int pool(float in[IN_SIEZE][IN_SIEZE], float out[OUT_SIEZE][OUT_SIEZE])
{
	int i,j;
	float tmp1,tmp2,tmp3;
	
	//单张图片池化 
	for(i = 0; i < IN_SIEZE; i+=2)//行 
	{
		for(j = 0; j < IN_SIEZE; j+=2)//列 
		{
			//单次池化 最大值池化 
			tmp1 = in[i][j] > in[i][j+1] ? in[i][j] : in[i][j+1];
			tmp2 = in[i+1][j] > in[i+1][j+1] ? in[i+1][j] : in[i+1][j+1];
			tmp3 = tmp1 > tmp2 ? tmp1 : tmp2;
			
			out[i/2][j/2] = tmp3;
		}
	}
}

int pool1(float in[IN_SIEZE][IN_SIEZE], float out[OUT_SIEZE][OUT_SIEZE])
{
	int i,j;
	float tmp1,tmp2,tmp3;
	
	//单张图片池化 
	for(i = 0; i < IN_SIEZE; i+=2)//行 
	{
		for(j = 0; j < IN_SIEZE; j+=2)//列 
		{
			//单次池化 平均值池化 
			tmp1 = in[i][j] + in[i][j+1];
			tmp2 = in[i+1][j] + in[i+1][j+1];
			tmp3 = (tmp1 + tmp2)/4;
			
			out[i/2][j/2] = tmp3;
		}
	}
}

int pool_test()
{
	float input[IN_SIEZE][IN_SIEZE] = {
	1,2,3,4,
	5,6,7,8,
	9,10,11,12,
	2,2,3,4
	};
	float output[OUT_SIEZE][OUT_SIEZE]= {0};
	int i,j;
	
	pool(input, output);
	
	printf("最大值池化\n ");
	printf(" 输入图片\n ");
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
			printf("%.1f ", input[i][j]);
		printf("\n ");
	}
	printf("输出图片\n ");
	for(i = 0; i < 2; i++)
	{
		for(j = 0; j < 2; j++)
			printf("%.1f ", output[i][j]);
		printf("\n ");
	}
	pool1(input, output);
	printf("平均值池化\n ");
	printf(" 输入图片\n ");
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
			printf("%.1f ", input[i][j]);
		printf("\n ");
	}
	printf("输出图片\n ");
	for(i = 0; i < 2; i++)
	{
		for(j = 0; j < 2; j++)
			printf("%.1f ", output[i][j]);
		printf("\n ");
	}
}

四、padding全零填充

#define P_IN_SIZE 4
#define P_OUT_SIZE 6
int padding_1(float in[P_IN_SIZE][P_IN_SIZE], float out[P_OUT_SIZE][P_OUT_SIZE])
{
	int i,j;
	
	//清零输出
	for(i = 0; i < P_OUT_SIZE; i++)
		for(j = 0; j < P_OUT_SIZE; j++)
			out[i][j] = 0.0;
	//填充输入
	for(i = 1; i < (P_OUT_SIZE - 1); i++)
		for(j = 1; j < (P_OUT_SIZE - 1); j++) 
			out[i][j] = in[i-1][j-1];
}

int padding_test()
{
	int i,j;
	float input[P_IN_SIZE][P_IN_SIZE] = {
	1,2,3,4,
	5,6,7,8,
	9,10,11,12,
	2,2,3,4
	};
	float output[P_OUT_SIZE][P_OUT_SIZE];
	
	padding_1(input, output);
	printf(" 输入图片\n ");
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4; j++)
			printf("%.1f ", input[i][j]);
		printf("\n ");
	}
	printf("输出图片\n ");
	for(i = 0; i < 6; i++)
	{
		for(j = 0; j < 6; j++)
			printf("%.1f ", output[i][j]);
		printf("\n ");
	}
}

五、多核多通道卷积

#define IMG_SIZE 7
#define IMG_CH   3
#define CONV_W_SIZE 3
#define CONV_W_CH 3
#define CONV_W_NUM 2
#define CONV_O_SIZE 5
int conv(float img[IMG_SIZE][IMG_SIZE][IMG_CH], 
float conv_w[CONV_W_SIZE][CONV_W_SIZE][CONV_W_CH][CONV_W_NUM],
float out[CONV_O_SIZE][CONV_O_SIZE][CONV_W_NUM])
{
	int i,j,k,r,m,n;
	float tmp1,tmp2;
	
	//多核多通道卷积 
	//多核卷积
	for(r = 0; r < CONV_W_NUM; r++)
	{
		//多特征平面卷卷积 
		for(m = 0; m <= (IMG_SIZE-CONV_W_SIZE); m++)//特征平面行 
		{
			for(n = 0; n <= (IMG_SIZE-CONV_W_SIZE); n++)//特征平面的列 
			{
				tmp2 = 0.0;//清零多通道单次卷积结果 
				//多通道 
				for(k = 0; k < IMG_CH; k++)
				{
					tmp1 = 0.0;//清零单次卷积结果 
					//单次卷积
					for(i = 0; i < CONV_W_SIZE; i++)//卷积核行
					{
						for(j = 0; j < CONV_W_SIZE; j++)//卷积核列
						{
							//单点计算 
							tmp1 = tmp1 + img[i+m][j+n][k]*conv_w[i][j][k][r];
						}
					}
					//累加多个特征平面的卷积结果
					tmp2 = tmp2 + tmp1;
				}
				//偏置
				
				//激活 
				
				out[m][n][r] = tmp2;
			}
		}
	}
}

int conv_test()
{
	float input[IMG_CH][IMG_SIZE][IMG_SIZE] = {
	0,0,0,0,0,0,0,
	0,1,1,2,2,1,0,
	0,1,1,1,2,1,0,
	0,2,1,1,0,2,0,
	0,2,1,0,1,2,0,
	0,2,1,2,2,2,0,
	0,0,0,0,0,0,0,
	
	0,0,0,0,0,0,0,
	0,0,1,2,0,1,0,
	0,2,2,1,1,0,0,
	0,2,1,0,0,2,0,
	0,1,0,0,0,2,0,
	0,0,1,0,1,2,0,
	0,0,0,0,0,0,0,
	
	0,0,0,0,0,0,0,
	0,2,2,0,1,2,0,
	0,0,0,2,1,2,0,
	0,2,1,0,2,1,0,
	0,1,1,0,0,0,0,
	0,0,0,1,1,1,0,
	0,0,0,0,0,0,0,};
	float conv_w[CONV_W_NUM][CONV_W_CH][CONV_W_SIZE][CONV_W_SIZE] = {
	1,1,1,
	-1,-1,0,
	-1,1,0,
	
	-1,-1,1,
	-1,1,0,
	-1,1,0,
	
	1,0,-1,
	0,0,0,
	1,-1,-1,
	
	0,0,-1,
	-1,1,1,
	0,0,0,
	
	0,0,1,
	1,0,1,
	0,-1,-1,
	
	-1,1,1,
	0,1,1,
	1,-1,1};
	float input1[IMG_SIZE][IMG_SIZE][IMG_CH] = {0};
	float conv1_w[CONV_W_SIZE][CONV_W_SIZE][CONV_W_CH][CONV_W_NUM] = {0};
	float output[CONV_O_SIZE][CONV_O_SIZE][CONV_W_NUM] = {0};
	
	int i,j,k,r,m,n;
	printf("imge data \n");
	for(i = 0; i < IMG_CH; i++)
	{
		for(j = 0; j < IMG_SIZE; j++)
		{
			for(k = 0; k < IMG_SIZE; k++)
			{
				input1[j][k][i] = input[i][j][k];
				printf("%.1f ", input1[j][k][i]);
			}
			printf("\n");
		}
		printf("\n");
	}
	printf("\n");
	printf("conv w \n");
	for(i = 0; i < CONV_W_NUM; i++)
	{
		for(j = 0; j < CONV_W_CH; j++)
		{
			for(k = 0; k < CONV_W_SIZE; k++)
			{
				for(r = 0; r < CONV_W_SIZE; r++)
				{
					conv1_w[k][r][j][i] = conv_w[i][j][k][r];
					printf("%.1f ", conv1_w[k][r][j][i]);
				}
				printf("\n");
			}
			printf("\n");
		}
		printf("\n");
	}
	printf("\n");
	conv(input1, conv1_w, output);
	
	printf("result data \n");
	for(i = 0; i < CONV_W_NUM; i++)
	{
		for(j = 0; j < CONV_O_SIZE; j++)
		{
			for(k = 0; k < CONV_O_SIZE; k++)
			{
				printf("%.1f ", output[j][k][i]);
			}
			printf("\n");
		}
		printf("\n");
	}
}

六、多维转一维

#define SW_IN_SIZE  3
#define SW_IN_CH	3
#define SW_OUT_LEN (SW_IN_SIZE*SW_IN_SIZE*SW_IN_CH)
int Narry_1(float in[SW_IN_SIZE][SW_IN_SIZE][SW_IN_CH], float out[SW_OUT_LEN])
{
	int i,j,k;
	float *p = out;
	
	for(i = 0; i < SW_IN_CH; i++)
	{
		for(j = 0; j < SW_IN_SIZE; j++)
		{
			for(k = 0; k < SW_IN_SIZE; k++)
			{
				#if 1
				*p = in[j][k][i];
				p++;
				#else
				out[(i*SW_IN_SIZE*SW_IN_SIZE + j*SW_IN_SIZE + k)] = in[j][k][i];
				#endif
			}
		}
	}
}

int Narry_1_test()
{
	float input[SW_IN_CH][SW_IN_SIZE][SW_IN_SIZE] = {
	1,1,1,
	-1,-1,0,
	-1,1,0,
	
	-1,-1,1,
	-1,1,0,
	-1,1,0,
	
	1,0,-1,
	0,0,0,
	1,-1,-1,
	};
	float input1[SW_IN_SIZE][SW_IN_SIZE][SW_IN_CH];
	
	float output[SW_IN_SIZE*SW_IN_SIZE*SW_IN_CH] = {0};
	int i,j,k;
	float *p = output;
	
	//转换输入 
	for(i = 0; i < SW_IN_CH; i++)
	{
		for(j = 0; j < SW_IN_SIZE; j++)
		{
			for(k = 0; k < SW_IN_SIZE; k++)
			{
				input1[j][k][i] = input[i][j][k];
				printf("%.1f ", input1[j][k][i]);
			}
			printf("\n");
		}
		printf("\n");
	}
	Narry_1(input1, output);
	
	printf("input data \n");
	for(i = 0; i < SW_IN_CH; i++)
	{
		for(j = 0; j < SW_IN_SIZE; j++)
		{
			for(k = 0; k < SW_IN_SIZE; k++)
			{
				printf("%.1f ", input1[j][k][i]);
			}
			printf("\n");
		}
		printf("\n");
	}
	printf("output data \n");
	for(i = 0; i < SW_IN_CH; i++)
	{
		for(j = 0; j < SW_IN_SIZE; j++)
		{
			for(k = 0; k < SW_IN_SIZE; k++)
			{
				printf("%.1f ", *p);
				p++;
			}
			printf(" ");
		}
		printf(" ");
	}
}
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值