Keras入门(四)之利用CNN模型轻松网站验证码
一文看懂YOLO v3
https://www.zhihu.com/collection/366298672
opencv : https://github.com/gzr2017/ImageProcessing100Wen/blob/master/Question_01_10/answers_py/answer_1.py
pyQT5 http://code.py40.com/1995.html
Embedding理解与代码实现
卷积的三种模式: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语言代码实现
-
#include<stdio.h>
-
#define N1 3
-
#define M1 3
-
#define N2 3
-
#define M2 3
-
//x需要运算的矩阵
-
//y卷积核
-
//z(full模式的输出)
-
//z2(same模式的输出)
-
int x[N1][M1];//需要运算矩阵
-
int y[N2][M2];//卷积核
-
int z[N1+N2-1][M1+M2-1];//full模式下的输出
-
int z2[N1][M1];//same模式下的输出
-
void conv2(int x[N1][M1],int y[N2][M2],int z[N1+N2-1][M1+M2-1],int z2[N1][M1])
-
{
-
int i,j;
-
int n,m;
-
for(i=0; i<N1+N2-1; i++)
-
for(j=0; j<M1+M2-1; j++)
-
{
-
int temp = 0;
-
for(m=0; m<N1; m++)
-
for(n=0; n<M1; n++)
-
if((i-m)>=0&&(i-m)<N2&&(j-n)>=0&&(j-n)<M2)
-
temp+=x[m][n]*y[i-m][j-n];
-
z[i][j]=temp;
-
}
-
for(i=0; i<N1; i++)
-
for(j=0; j<M1; j++)
-
{
-
z2[i][j]=z[i+(N2-1)/2][j+(M2-1)/2];
-
}
-
}
-
int main()
-
{
-
int i,j;
-
printf("请输入需要运算的矩阵:\n");
-
for(i=0;i<N1;i++)
-
{
-
for(j=0;j<M1;j++)
-
{
-
scanf("%d",&x[i][j]);
-
}
-
}
-
printf("请输入卷积核:\n");
-
for(i=0;i<N2;i++)
-
{
-
for(j=0;j<M2;j++)
-
{
-
scanf("%d",&y[i][j]);
-
}
-
}
-
conv2(x,y,z,z2);//卷积运算
-
printf("same model下结果输出:\n");
-
for(i=0;i<N1;i++)
-
{
-
for(j=0;j<M1;j++)
-
{
-
printf("%d ",z2[i][j]);
-
}
-
printf("\n");
-
}
-
return 0;
-
}
上信号与系统后,做实验用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