卷积C语言实现

Keras入门(四)之利用CNN模型轻松网站验证码

 

https://frank909.blog.csdn.net/article/details/103149407?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-18.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-18.control

一文看懂YOLO v3

https://blog.csdn.net/jclian91/article/details/88777456?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242

https://www.zhihu.com/collection/366298672

opencv : https://github.com/gzr2017/ImageProcessing100Wen/blob/master/Question_01_10/answers_py/answer_1.py

https://blog.csdn.net/weixin_42109012/article/details/90680460?utm_medium=distribute.pc_relevant_download.none-task-blog-blogcommendfrombaidu-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-blogcommendfrombaidu-1.nonecas

https://blog.csdn.net/qq_38269418/article/details/78991649?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242 

pyQT5 http://code.py40.com/1995.html

Embedding理解与代码实现

https://hichenway.blog.csdn.net/article/details/85100616?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

 

 

 

卷积的三种模式:full,same,valid

这三种模式是对卷积核移动范围的不同限制

1、full mode

橙色部分为image(大小为N1*M1),蓝色部分为filter(大小为N2*M2),full模式下输出矩阵大小为(N1+N2-1)*(M1+M2-1)

即从filter右下角一个单元与image的第一个单元重叠开始计算,依次将filter的右下角单元与image的每一个单元重叠并计算。

2、same mode

将filter中心与image左上角单元重合,并依次与image的每个单元重合计算,最终输出结果为N1*M1

3、valid mode

filter在image内部进行卷积运算

 

需要注意的是,‘same’和‘full’只是将被卷积的矩阵做了相应尺寸的0填充后再进行‘valid’卷积即可。

此处默认步长1。

三种卷积操作的示意图:

Valid:

Same:

Full:

 

 

 

C语言代码实现

 
  1. #include<stdio.h>

  2.  
  3. #define N1 3

  4. #define M1 3

  5. #define N2 3

  6. #define M2 3

  7.  
  8. //x需要运算的矩阵

  9. //y卷积核

  10. //z(full模式的输出)

  11. //z2(same模式的输出)

  12. int x[N1][M1];//需要运算矩阵

  13. int y[N2][M2];//卷积核

  14. int z[N1+N2-1][M1+M2-1];//full模式下的输出

  15. int z2[N1][M1];//same模式下的输出

  16.  
  17. void conv2(int x[N1][M1],int y[N2][M2],int z[N1+N2-1][M1+M2-1],int z2[N1][M1])

  18. {

  19. int i,j;

  20. int n,m;

  21. for(i=0; i<N1+N2-1; i++)

  22. for(j=0; j<M1+M2-1; j++)

  23. {

  24. int temp = 0;

  25. for(m=0; m<N1; m++)

  26. for(n=0; n<M1; n++)

  27. if((i-m)>=0&&(i-m)<N2&&(j-n)>=0&&(j-n)<M2)

  28. temp+=x[m][n]*y[i-m][j-n];

  29. z[i][j]=temp;

  30. }

  31. for(i=0; i<N1; i++)

  32. for(j=0; j<M1; j++)

  33. {

  34. z2[i][j]=z[i+(N2-1)/2][j+(M2-1)/2];

  35. }

  36.  
  37.  
  38.  
  39. }

  40.  
  41.  
  42. int main()

  43. {

  44. int i,j;

  45.  
  46.  
  47. printf("请输入需要运算的矩阵:\n");

  48. for(i=0;i<N1;i++)

  49. {

  50. for(j=0;j<M1;j++)

  51. {

  52. scanf("%d",&x[i][j]);

  53. }

  54.  
  55. }

  56.  
  57. printf("请输入卷积核:\n");

  58. for(i=0;i<N2;i++)

  59. {

  60. for(j=0;j<M2;j++)

  61. {

  62. scanf("%d",&y[i][j]);

  63. }

  64.  
  65. }

  66.  
  67. conv2(x,y,z,z2);//卷积运算

  68.  
  69. printf("same model下结果输出:\n");

  70. for(i=0;i<N1;i++)

  71. {

  72. for(j=0;j<M1;j++)

  73. {

  74. printf("%d ",z2[i][j]);

  75. }

  76.  
  77. printf("\n");

  78. }

  79.  
  80. return 0;

  81. }

 

 

上信号与系统后,做实验用Matlab做的卷积,一个函数搞定,但是写实验报告时需要用C语言实现,额,虽说原理不难,实现起来浪费了我好久时间

一、卷积公式

Y(n)=x(n)h(n)=∑x(i)h(n-i)

先用Matlab演示卷积,后面以这个为例。
在这里插入图片描述

a=[1,2,3,4]
b=[1,2,3]
conv(a,b)
ans =
	1     4    10    16    17    12
  • 1
  • 2
  • 3
  • 4
  • 5

二、对卷积的求解

这个一般有两种方法实现
1、第一种是交叉相乘相加法(对于1维的卷积,注意一定要将其中一个倒叙或者翻转180度)

在这里插入图片描述
对于同一时间接触到的面积进行相乘,再相加即是这个时刻的值
例子
在这里插入图片描述
代码实现

#include<stdio.h>
#include<stdlib.h>

int min(int x, int y) {
	return x < y ? x : y;
}

int max(int x, int y) {
	return x > y ? x : y;
}

void convolution(int* input1, int* input2, int* output, int mm, int nn)
{
	//存储地址
	int* xx = (int*)malloc(sizeof(int) * (mm + nn - 1));
	//开始卷积
	for (int i = 0; i < mm + nn - 1; i++)
	{
		xx[i] = 0;
		//以位数最少的卷积作为卷积次数
		for (int j = 0; j < min(mm,nn) ; j++) {
			//第一个卷积比第二个卷数积少执行
			if (mm <= nn) {
				if (i - j >= 0 && i - j < max(mm, nn)) {
					printf("%d ", input1[j]);
					printf("%d ", input2[i-j]);
					xx[i] += input1[j] * input2[i - j];
				}
			}
			//第一个卷积比第二个卷积数多执行
			else {
				if (i - j >= 0 && i - j < max(mm, nn)) {
					printf("%d ", input1[i-j]);
					printf("%d ", input2[j]);
					xx[i] += input2[j] * input1[i - j];
				}
			}
			printf("\n");
		}
	}
	printf("\n");
	for (int i = 0; i < mm+nn-1; i++) {
		output[i] = xx[i];
	}
	delete[] xx;
}

int main() {
	int mm, nn;
	printf("请输入第一个卷积数目\n");
	scanf_s("%d", &mm);

	//malloc分配空间
	int* input1 = (int*)malloc(sizeof(int) * mm);
	printf("请输入第一个卷积数值\n");
	for (int i = 0; i < mm; i++) {
		scanf_s("%d", &input1[i]);
	}
	printf("请输入第二个卷积数目\n");
	scanf_s("%d", &nn);
	int* input2 = (int*)malloc(sizeof(int) * nn);
	printf("请输入第二个卷积数值\n");
	for (int j = 0; j < nn; j++) {
		scanf_s("%d", &input2[j]);
	}

	//卷积最大空间
	int* output = (int*)malloc(sizeof(int) * (mm+nn-1));
	convolution(input1, input2, output, mm, nn);

	printf("卷积结果\n");
	for (int i = 0; i < mm + nn - 1; i++)
	{
		printf("%d ", output[i]);
	}
	printf("\n");

	return 0;
}	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

在这里插入图片描述

二、第二种方法是时延法(第二种方法相对来说比较简单,转到z域后,卷积变为多项式相乘,不需要对序列进行移动或处理,仅将结果延时相应位数,然后对应相加、提取系数即可。)

已知y[0] = i, y[1] = j, y[2]=k
这里写图片描述
下面通过演示求x[n] * y[n]的过程,揭示卷积的物理意义。
第一步,x[n]乘以y[0]并平移到位置0
在这里插入图片描述

第二步,x[n]乘以y[1]并平移到位置1
这里写图片描述
第三步,x[n]乘以y[2]并平移到位置2:
在这里插入图片描述
最后,把上面三个图叠加,就得到了x[n] * y[n]:
这里写图片描述
简单吧?无非是平移(没有反褶!)、叠加。
实例
在这里插入图片描述代码实现

#include<stdio.h>
#include<stdlib.h>

void convolution2(int* input1, int* input2, int* output, int mm, int nn)
{
	//存储地址
	int* xx = (int*)malloc(sizeof(int) * (mm + nn - 1));
	for (int i = 0; i < mm + nn - 1; i++) {
		xx[i] = 0;
	}

	//开始卷积
	//利用时延效果,记录所有乘积后,时间位置一样的相加
	for (int i = 0; i < mm; i++) {
		for (int j = 0; j < nn; j++) {
			xx[i + j] += input1[i] * input2[j];
		}
	}

	for (int i = 0; i < mm + nn - 1; i++) {
		output[i] = xx[i];
	}
	delete[] xx;
}

int main() {
	int mm, nn;
	printf("请输入第一个卷积数目\n");
	scanf_s("%d", &mm);

	//malloc分配空间
	int* input1 = (int*)malloc(sizeof(int) * mm);
	printf("请输入第一个卷积数值\n");
	for (int i = 0; i < mm; i++) {
		scanf_s("%d", &input1[i]);
	}
	printf("请输入第二个卷积数目\n");
	scanf_s("%d", &nn);
	int* input2 = (int*)malloc(sizeof(int) * nn);
	printf("请输入第二个卷积数值\n");
	for (int j = 0; j < nn; j++) {
		scanf_s("%d", &input2[j]);
	}

	//卷积最大空间
	int* output = (int*)malloc(sizeof(int) * (mm + nn - 1));
	convolution2(input1, input2, output, mm, nn);

	printf("卷积结果\n");
	for (int i = 0; i < mm + nn - 1; i++)
	{
		printf("%d ", output[i]);
	}
	printf("\n");

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

运行结果

 

https://blog.csdn.net/jclian91/article/details/83024344

 

https://blog.csdn.net/weixin_33994429/article/details/88714099?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.channel_param

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值