单通单卷积
卷积其实就是个点成相加的过程 原理图如下: 关键代码实现:
#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])
{
float tmp=0.0;
for(int k=0;k<=IMG_SIZE - W_SIZE;k++)
{
for(int r=0;r<=IMG_SIZE - W_SIZE;r++)
{
tmp = 0.0;
for(int i=0;i<W_SIZE;i++)
{
for(int j=0;j<W_SIZE;j++)
{
tmp += img[i+k][j+r]*w[i][j];
}
}
out[k][r] = tmp;
}
}
return 0;
}
运行结果:
多通道多卷积
原理示意图:
关键代码实现如下:
#define IMG_SIZE 7
#define IMG_CH 3
#define CONV_KERNEL_SIZE 3
#define CONV_KERNEL_CH 3
#define CONV_KERNEL_NUM 2
#define OUT_SIZE 5
#define OUT_CH 2
int convs( float img[IMG_SIZE][IMG_SIZE][IMG_CH],
float w[CONV_KERNEL_SIZE][CONV_KERNEL_SIZE][CONV_KERNEL_CH][CONV_KERNEL_NUM],
float out[OUT_SIZE][OUT_SIZE][OUT_CH])
{
float tmp=0.0,tmp1=0.0;
for(int m=0;m<CONV_KERNEL_NUM;m++)
{
for(int k=0;k<=IMG_SIZE - W_SIZE;k++)
{
for(int r=0;r<=IMG_SIZE - W_SIZE;r++)
{
tmp1 = 0.0;
for(int n=0;n<CONV_KERNEL_CH;n++)
{
tmp = 0.0;
for(int i=0;i<W_SIZE;i++)
{
for(int j=0;j<W_SIZE;j++)
{
tmp += img[i+k][j+r][n]*w[i][j][n][m];
}
}
tmp1 += tmp;
}
out[k][r][m] = tmp1;
}
}
}
}
运行结果:
维度转换(多维转一维)
#define IN_SIZE 3
#define IN_CH 3
#define OUT_LEN (IN_SIZE*IN_SIZE*IN_CH)
int convert(float in[IN_SIZE][IN_SIZE][IN_CH],float out[OUT_LEN])
{
for(int k=0;k<IN_CH;k++)
{
for(int i=0;i<IN_SIZE;i++)
{
for(int j=0;j<IN_SIZE;j++)
{
#if 0
*p = in[i][j][k];
#else
out[k*IN_SIZE*IN_SIZE+i*IN_SIZE+j] = in[i][j][k];
#endif
}
}
}
return 0;
}
运行结果:
完整代码实现:
#include <stdio.h>
#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])
{
float tmp=0.0;
for(int k=0;k<=IMG_SIZE - W_SIZE;k++)
{
for(int r=0;r<=IMG_SIZE - W_SIZE;r++)
{
tmp = 0.0;
for(int i=0;i<W_SIZE;i++)
{
for(int j=0;j<W_SIZE;j++)
{
tmp += img[i+k][j+r]*w[i][j];
}
}
out[k][r] = tmp;
}
}
return 0;
}
int conv_test()
{
float img_in[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};
conv(img_in,conv_w,img_out);
int i,j;
printf("Input picture:\n");
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
printf("%.1f ",img_in[i][j]);
}
printf("\n");
}
printf("Input weight:\n");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.1f ",conv_w[i][j]);
}
printf("\n");
}
printf("Output picture:\n");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.1f ",img_out[i][j]);
}
printf("\n");
}
return 0;
}
#define IMG_SIZE 7
#define IMG_CH 3
#define CONV_KERNEL_SIZE 3
#define CONV_KERNEL_CH 3
#define CONV_KERNEL_NUM 2
#define OUT_SIZE 5
#define OUT_CH 2
int convs( float img[IMG_SIZE][IMG_SIZE][IMG_CH],
float w[CONV_KERNEL_SIZE][CONV_KERNEL_SIZE][CONV_KERNEL_CH][CONV_KERNEL_NUM],
float out[OUT_SIZE][OUT_SIZE][OUT_CH])
{
float tmp=0.0,tmp1=0.0;
for(int m=0;m<CONV_KERNEL_NUM;m++)
{
for(int k=0;k<=IMG_SIZE - W_SIZE;k++)
{
for(int r=0;r<=IMG_SIZE - W_SIZE;r++)
{
tmp1 = 0.0;
for(int n=0;n<CONV_KERNEL_CH;n++)
{
tmp = 0.0;
for(int i=0;i<W_SIZE;i++)
{
for(int j=0;j<W_SIZE;j++)
{
tmp += img[i+k][j+r][n]*w[i][j][n][m];
}
}
tmp1 += tmp;
}
out[k][r][m] = tmp1;
}
}
}
}
int convs_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_KERNEL_NUM][CONV_KERNEL_CH][CONV_KERNEL_SIZE][CONV_KERNEL_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 conv_w1[CONV_KERNEL_SIZE][CONV_KERNEL_SIZE][CONV_KERNEL_CH][CONV_KERNEL_NUM] = {0};
float img_out[OUT_SIZE][OUT_SIZE][OUT_CH] = {0};
int i,j,k,r,m,n;
printf("Input picture\n");
for(k =0;k<IMG_CH;k++)
{
for(i=0;i<IMG_SIZE;i++)
{
for(j=0;j<IMG_SIZE;j++)
{
input1[i][j][k] = input[k][i][j];
printf("%.1f ",input1[i][j][k]);
}
printf("\n");
}
printf("\n");
}
printf("\n");
printf("CONV_KERNEL:\n");
for(r=0;r<CONV_KERNEL_NUM;r++)
{
for(k=0;k<CONV_KERNEL_CH;k++)
{
for(i=0;i<CONV_KERNEL_SIZE;i++)
{
for(j=0;j<CONV_KERNEL_SIZE;j++)
{
conv_w1[i][j][k][r] = conv_w[r][k][i][j];
printf("%.1f ",conv_w1[i][j][k][r]);
}
printf("\n");
}
printf("\n");
}
}
printf("\n");
convs(input1,conv_w1,img_out);
printf("Output picture\n");
for(k=0;k<OUT_CH;k++)
{
for(i=0;i<OUT_SIZE;i++)
{
for(j=0;j<OUT_SIZE;j++)
{
printf("%.1f ",img_out[i][j][k]);
}
printf("\n");
}
printf("\n");
}
printf("\n");
return 0;
}
#define IN_SIZE 3
#define IN_CH 3
#define OUT_LEN (IN_SIZE*IN_SIZE*IN_CH)
int convert(float in[IN_SIZE][IN_SIZE][IN_CH],float out[OUT_LEN])
{
for(int k=0;k<IN_CH;k++)
{
for(int i=0;i<IN_SIZE;i++)
{
for(int j=0;j<IN_SIZE;j++)
{
#if 0
*p = in[i][j][k];
#else
out[k*IN_SIZE*IN_SIZE+i*IN_SIZE+j] = in[i][j][k];
#endif
}
}
}
return 0;
}
int convert_test()
{
float input[IN_CH][IN_SIZE][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[IN_SIZE][IN_SIZE][IN_CH] = {0};
float output[OUT_LEN] ={0};
int i,j,k,r,m,n;
float *p = output;
printf("Input picture\n");
for(k=0;k<IN_CH;k++)
{
for(i=0;i<IN_SIZE;i++)
{
for(j=0;j<IN_SIZE;j++)
{
input1[i][j][k] = input[k][i][j];
printf("%.1f ",input1[i][j][k]);
}
printf("\n");
}
printf("\n");
}
printf("\n");
convert(input1,output);
printf("Output picture\n");
for(k=0;k<IN_CH;k++)
{
for(i=0;i<IN_SIZE;i++)
{
for(j=0;j<IN_SIZE;j++)
{
printf("%.1f ",output[k*IN_SIZE*IN_SIZE+i*IN_SIZE+j]);
}
}
}
return 0;
}
int main()
{
convert_test();
return 0;
}
|