c++ 计算正弦的近似值_深度学习之卷积与卷积计算

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第1张图片

一、卷积介绍

泛函分析[1]中,卷积(又称叠积(convolution)、褶积旋积),是透过两个函数[2] fg 生成第三个函数的一种数学算子[3],表征函数 f 与经过翻转和平移的 g 的乘积函数所围成的曲边梯形的面积。如果将参加卷积的一个函数看作区间[4]指示函数[5],卷积还可以被看作是“移动平均[6]”的推广。

% Create folding of two rectangular impulses

clear

X=-2.6:0.001:3;
F1=abs(X)<=0.5;
F2=abs(X)<=0.5;
clf

mkdir('tmp');
[tmp zero_offset] = min(abs(X));

SyncFrames=[1 round(18.67*(1:numel(X)))];
integral=nan(size(X));
frame=1;
for offset_i=1:numel(X);
  offset=X(offset_i);
  shift=offset_i-zero_offset;
  F2_shifted = circshift(F2, [0 shift]);
  product = F2_shifted.*F1;
  integral(offset_i) = sum(product)/numel(X)*(X(end)-X(1));
  
    if offset_i==SyncFrames(frame)
        frame=frame+1;
        area(X, product, 'facecolor', 'yellow');
        hold on
        plot(X, F1, 'b', X, F2_shifted, 'r', X, integral, 'k', [offset offset], [0 2], 'k:')
        hold off
        axis image
        axis([-2.1 2.1 0 1.1])
        xlabel('tau & t');
        grid on
        legend('Area under f(tau)g(t-tau)', 'f(tau)', 'g(t-tau)', '(fastg)(t)');
        print('-dpng','-r72',sprintf('tmp/conv_box_box_%06d.png', offset_i));
        drawnow
    end
end

system('"C:Program FilesImageMagick-6.6.3-Q16convert.exe" -layers Optimize -delay 5 tmp/conv_box_box_*.png conv_box_box.gif');
delete('tmp/*');
rmdir('tmp');

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第2张图片

图示是两个方形脉冲信号波的卷积。其中函数"g"首先对

反射,接着平移"t",成为
。那么重叠部分的面积就相当于"t"处的卷积,其中横坐标代表待变量
以及新函数
的自变量"t"。

详细说明可参考:维基百科或者百度

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第3张图片

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第4张图片

傅里叶变换

卷积定理

卷积定理及其证明

卷积定理是傅立叶变换满足的一个重要性质。卷积定理指出,函数卷积的傅立叶变换是函数傅立叶变换的乘积。换言之,一个域中的卷积对应于另一个域中的乘积,例如,时域中的卷积对应于频域中的乘积。

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第5张图片

这一定理对拉普拉斯变换、Z变换等各种傅立叶变换的变体同样成立。需要注意的是,以上写法只对特定形式的变换正确,因为变换可能由其它方式正规化,从而使得上面的关系式中出现其它的常数因子。

下面我们来证明时域卷积定理,频域卷积定理的证明与此类似,读者可以自行证明。 证明:将卷积的定义

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第6张图片

傅立叶变换的作用在频域对信号进行分析,我们可以把时域的信号看做是若干正弦波的线性叠加,傅立叶变换的作用正是求得这些信号的幅值和相位。

既然固定的时域信号是若干固定正弦信号的叠加,在不改变幅值的情况下,在时间轴上移动信号,也就相当于同时移动若干正弦信号,这些正弦信号的相位改变、但幅值不变,反映在频域上就是傅立叶变换结果的模不变、而相位改变。所以,时移性质其实就表明当一个信号沿时间轴平移后,各频率成份的大小不发生改变,但相位发生变化。

既然这里提到了傅立叶变换的性质,这里我们还将补充一些关于帕塞瓦尔定理的有关内容。该定理最早是由法国数学家帕塞瓦尔(Marc-Antoine Parseval)在1799年推导出的一个关于级数的理论,该定理随后被应用于傅立叶级数。帕塞瓦尔定理的表述是这样的:

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第7张图片

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第8张图片

综上所述,原结论得证。 前面我们也介绍过复数形式的傅立叶级数,下面我们来推导与复数形式傅立叶变换相对应的帕塞瓦尔等式。这里再次给出傅立叶级数的复数形式表达式,具体推导过程请读者参阅前文

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第9张图片

帕塞瓦尔定理把一个信号的能量或功率的计算和频谱函数或频谱联系起来了,它表明一个信号所含有的能量(功率)恒等于此信号在完备正交函数集中各分量能量(功率)之和。换言之,能量信号的总能量等于各个频率分量单独贡献出来的能量的连续和;而周期性功率信号的平均功率等于各个频率分量单独贡献出来的功率之和。

二、卷积计算

假设有一个卷积核H,就一般为3*3的矩阵:

573fb4084b576406c263b962daaddf17.png

有一个待处理矩阵X:

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第10张图片

H*X的计算过程分为三步

第一步,将卷积核翻转180°,也就是成为了

9d130187a5946cb4885c70d8bba840d6.png

第二步,将卷积核h的中心对准x的第一个元素,然后对应元素相乘后相加,没有元素的地方补0。

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第11张图片

这样结果Y中的第一个元素值Y11=10+20+10+00+01+02+-10+-25+-1*6=-16

第三步每个元素都像这样计算出来就可以得到一个输出矩阵,就是卷积结果

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第12张图片

像这样计算,其他过程略了。

最后结果

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第13张图片

注意:

我这里是用0补全原矩阵的,但我们不一定选择0。在Opencv的cvFilter2D函数中,就没有使用0来补全矩阵,而是用了边缘拷贝的方式。

###三、cvFilter2D卷积函数的计算过程分析

cvFilter2D卷积函数的形式如下:

void cvFilter2D( const CvArr* src, CvArr* dst,const CvMat* kernel, CvPoint anchor=cvPoint(-1,-1));
src
输入图像.
dst
输出图像.
kernel
卷积核, 单通道浮点矩阵. 如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。
anchor
核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。
函数 cvFilter2D 对图像进行线性滤波,支持 In-place 操作。当核运算部分超出输入图像时,函数从最近邻的图像内部象素差值得到边界外面的象素值。

先上代码,

#include  	
for (i = 0; irows; i++)	
	for (j = 0; jcols; j++)		
	double ImgPixelVal = cvGetReal2D(m, i, j);	
		cout << ImgPixelVal << "  ";
	CvMat Ma = cvMat(3, 3, CV_32FC1, A);//核矩阵
	CvMat Mb = cvMat(3, 3, CV_32FC1, B);//输入
	CvMat *C = cvCreateMat(3, 3, CV_32FC1);
	cvFilter2D(&Mb, C, &Ma, cvPoint(1, 1));

输出的结果

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第14张图片

为了不让数据有偶然性,所以卷积核很古怪,大家不要在意,我们只是要研究他的计算过程。

首先我们发现91 这个值就是 19+28+37+44+55+66-17-28-1*9=91。即对应的元素相乘后,求和。而且卷积核没有旋转180°

然后我们可以看到如果用我上一篇介绍的边缘用0补全,是得不到这个结果的,所以我们肯定Opencv不是用0补全。

那下面的问题就是Opencv到底是怎么补全的

问号里面该填什么

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第15张图片

???

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第16张图片

???

之后,我们就猜测是不是边缘复制,

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第17张图片

------>

c++ 计算正弦的近似值_深度学习之卷积与卷积计算_第18张图片

通过计算后发现,果然是这样。19+29+38+49+59+68-14-24-1*5=163

其他也逐一验证 。

结论:

1.Opencv中,卷积核不会进行180°的旋转

2.CvFilter2D是边缘拷贝,通过边缘拷贝补全矩阵进行计算。

参考文献

opencv安装教程参考文献

库文件下载地址: opencv-4-3-0文献资料 opencv-4.3.0开源计算机视觉库

参考资料

[1]

泛函分析: https://zh.wikipedia.org/wiki/%E6%B3%9B%E5%87%BD%E5%88%86%E6%9E%90

[2]

函数: https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0

[3]

算子: https://zh.wikipedia.org/wiki/%E7%AE%97%E5%AD%90

[4]

区间: https://zh.wikipedia.org/wiki/%E5%8C%BA%E9%97%B4

[5]

指示函数: https://zh.wikipedia.org/wiki/%E6%8C%87%E7%A4%BA%E5%87%BD%E6%95%B0

[6]

移动平均: https://zh.wikipedia.org/wiki/%E6%BB%91%E5%8B%95%E5%B9%B3%E5%9D%87

你可能感兴趣的:(c++,计算正弦的近似值)