《二维卷积运算》由会员分享,可在线阅读,更多相关《二维卷积运算(10页珍藏版)》请在金锄头文库上搜索。
1、一、二维卷积运算Gabor变换的本质实际上还是对二维图像求卷积。因此二维卷积运算的效率就直接决定了Gabor变换的效率。在这里我先说说二维卷积运算以及如何通过二维傅立叶变换提高卷积运算效率。在下一步分内容中我们将此应用到Gabor变换上,抽取笔迹纹理的特征。1、离散二维叠加和卷积关于离散二维叠加和卷积的运算介绍的书籍比较多,我这里推荐William K. Pratt著,邓鲁华 张延恒 等译的数字图像处理(第3版),其中第7章介绍的就是这方面的运算。为了便于理解,我用下面几个图来说明离散二维叠加和卷积的求解过程。A可以理解成是待处理的笔迹纹理,B可以理解成Gabor变换的核函数,现在要求A与B的
2、离散二维叠加卷积,我们首先对A的右边界和下边界填充0(zero padding),然后将B进行水平翻转和垂直翻转,如下图:然后用B中的每个值依次乘以A中相对位置处的值并进行累加,结果填入相应位置处(注意红圈位置)。通常二维卷积的结果比A、B的尺寸要大。如下图所示:2、快速傅立叶变换卷积根据傅立叶变换理论,对图像进行二维卷积等价于对图像的二维傅立叶变换以及核函数的二维傅立叶变换在频域求乘法。通过二维傅立叶变换可以有效提高卷积的运算效率。但在进行傅立叶变换时一定要注意“卷绕误差效应”,只有正确对原有图像以及卷积核填补零后,才能得到正确的卷积结果。关于这部分内容可以参考William K. Prat
3、t著,邓鲁华 张延恒 等译的数字图像处理(第3版)第9章的相关内容,此处就不再赘述。目前网上可以找到开源C#版的快速傅立叶变换代码(Exocortex.DSP),我使用的是1.2版,2.0版似乎只能通过CVS从SourceForge上签出, 并且功能没有什么太大改变。将Exocortex.DSP下载下来后,将源代码包含在自己的项目中,然后就可以利用它里面提供的复数运算以及傅立叶变换功能了。为了测试通过傅立叶变换求卷积的有效性,特编写以下代码: using System;using Exocortex.DSP;class MainEntry static void Main() fftConv2
4、 c = new fftConv2(); c.DoFFTConv2(); public class fftConv2 double, kernel = -1, 1, 0, 1; double, data = 10,5,20,20,20, 10,5,20,20,20, 10,5,20,20,20, 10,5,20,20,20, 10,5,20,20,20; Complex Kernel = new Complex8*8; Complex Data = new Complex8*8; Complex Result = new Complex8*8; private void Init() for(
5、int y=0; y2; y+) for(int x=0; x2; x+) Kernely*8+x.Re = kernely,x; for(int y=0; y5; y+) for(int x=0; x5; x+) Datay*8+x.Re = datay,x; public void DoFFTConv2() Init(); Fourier.FFT2(Data, 8, 8, FourierDirection.Forward); Fourier.FFT2(Kernel, 8, 8, FourierDirection.Forward); for(int i=0; i8*8; i+) Result
6、i = Datai * Kerneli / (8*8); Fourier.FFT2(Result, 8, 8, FourierDirection.Backward); for(int y=0; y6; y+) for(int x=0; x6; x+) Console.Write(0,8:F2, Resulty*8+x.Re); Console.WriteLine(); 程序的运行结果与离散二维叠加和卷积的运算结果完全相同。由于卷积结果与原始输入图片的大小是不一样的,存在着所谓“边界”,在我的实际应用程序中,为了避免这些“边界”对结果过多的影响,我采用的是居中阵列定义,并且从卷积结果中只截取需要
7、的那部分内容,确保和原始图片的大小完全一致,如下图:这就需要对卷积的傅立叶求法做些微小的调整,具体调整办法就不说了,主要是坐标的变换,将示例代码贴上来供大家参考:using System;using Exocortex.DSP;class MainEntry static void Main() CenterfftConv2 s = new CenterfftConv2(); s.CommonMethod(); s.DoFFTConv2(); public class CenterfftConv2 double, kernel = 0, 1, 0, 1, 2, 0, 0, 0, 3; doub
8、le, data = new double12,12; Complex Kernel = new Complex16*16; Complex Data = new Complex16*16; Complex Result = new Complex16*16; public CenterfftConv2() Random r = new Random(); for(int y=0; y12; y+) for(int x=0; x12; x+) datay,x = r.NextDouble(); for(int y=0; y3; y+) for(int x=0; x3; x+) Kernely*
9、16+x.Re = kernely,x; for(int y=1; y13; y+) for(int x=1; x13; x+) Datay*16+x.Re = datay-1,x-1; public void DoFFTConv2() Console.WriteLine( = By FFT2Conv2 Method =); Fourier.FFT2(Data, 16, 16, FourierDirection.Forward); Fourier.FFT2(Kernel, 16, 16, FourierDirection.Forward); for(int i=0; i16*16; i+) R
10、esulti = Datai * Kerneli / (16*16); Fourier.FFT2(Result, 16, 16, FourierDirection.Backward); for(int y=2; y14; y+) for(int x=2; x14; x+) Console.Write(0,5:F2, Resulty*16+x.GetModulus(); Console.WriteLine(); public void CommonMethod() double real = 0; Console.WriteLine( = Direct Transform =); for(int
11、 y=0; y 12; y+) for(int x=0; x 12; x+) for(int y1=0; y1 3; y1+) for(int x1=0; x1 =0) & (y - 1 + y1)=0) & (x - 1 + x1)12) real += datay - 1 + y1, x - 1 + x1 * kernel2 - x1, 2 - y1; Console.Write(0,5:F2, real); real=0; Console.WriteLine(); Console.WriteLine(n); 有了此部分的基础知识后,我们就要步入笔迹识别中最核心的部分Gabor变换,提取笔迹的特征了。二、Gabor函数Gabor变换属于加窗傅立叶变换,Gabor函数可以在频域不同尺度、不同方向上提取相关的特征。另外Gabor函数与人眼的生物作用相仿,所以经常用作纹理识别上,并取得了较好的效果。二维Gabor函数可以表示为:其中:v的取值决定了Gabor滤波的波长,u的取值表示Gabor核函数的方向,K表示总的方向数。参数决定了高斯窗口的大小,这里取。程序中取4个频率(v=0, 1, ., 3),8个方向(即K=8,u0, 1, . ,7),共32个Gabor核函数。不同频率不同方向的Gabor函数可通过下图表示: