这几天一直学习傅立叶变换,看了很多国内外资料,网上讲原理的很多,到了程序实现这块大多是Matlab,opencv等,这些软件的api对于我们理解DFT在计算机中的实现并没有多大帮助。于是想用C/C++实现DFT,经过不断的阅读与编程实验,最终程序有了还算满意的结果。
“关于傅立叶变换,无论是书本还是在网上可以很容易找到关于傅立叶变换的描述,但是大都是些故弄玄虚的文章,太过抽象,尽是一些让人看了就望而生畏的公式的罗列,让人很难能够从感性上得到理解”—dznlong
这是在网上看到的一句话,也是我一直以来的心声,要想弄明白一些事情,终究是要自己动手。
至于原理性的内容,网上太多,我这里不多说了,仅列几个连接供参考。
https://en.wikipedia.org/wiki/Fourier_series
http://www.cnblogs.com/v-July-v/archive/2011/02/20/1983676.html
http://www.dspguide.com/pdfbook.htm
for (int u = 0; u < width; u ++)
for (int v =0; v < height; v ++){
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
real += srcMat.at<Vec3b>(y, x)[0] * cos(- ((double)2 * PI * u * x / width + (double)2 * PI * v * y / height )) * 1;
imaginary += srcMat.at<Vec3b>(y, x)[0] * sin(-((double)2 * PI * u * x / width + (double)2 * PI * v * y /height)) * 1;
}
}
u和v是变换后的变量,从程序可以看出,每一个F(u,v)的计算都需要遍历整副图像,确实是相当费时间,我只用了100 × 100 的图像,计算速度慢的惊人。
real = 100 * real / (width * height);
imaginary =100 * imaginary / (width * height);
为什么要乘以100呢?因为此时的real和imaginary值很小,如果显示出来基本是黑色,所以为了显示清楚,我们随便乘以个值放大一下,这应该就是Opencv例子里说的归一化。
“`
tmpMat.at(u, v) = sqrt(real * real + imaginary * imaginary);
“`
上面那个小方块窗口是原图像变换后的图像,用的是opencv的方法。
这个图是用C语言实现的DFT,为了看得清晰点,我把它放大了,相比与opencv的图这个没有做坐标的变换。
这个程序不是完美的,只是一种尝试,通过这个过程,对DFT有进一步了解,养成这种自己动手的习惯后,对学习其他的算法有一定帮助,接下来我该转移到其他问题学习,当知识丰富后还会在回过头来重新审视今天这些内容,并加以完善。