數字影象處理成長之路4: C語言與離散傅立葉變換(DFT)
阿新 • • 發佈:2019-01-09
這幾天一直學習傅立葉變換,看了很多國內外資料,網上講原理的很多,到了程式實現這塊大多是Matlab,opencv等,這些軟體的api對於我們理解DFT在計算機中的實現並沒有多大幫助。於是想用C/C++實現DFT,經過不斷的閱讀與程式設計實驗,最終程式有了還算滿意的結果。
“關於傅立葉變換,無論是書本還是在網上可以很容易找到關於傅立葉變換的描述,但是大都是些故弄玄虛的文章,太過抽象,盡是一些讓人看了就望而生畏的公式的羅列,讓人很難能夠從感性上得到理解”—dznlong
這是在網上看到的一句話,也是我一直以來的心聲,要想弄明白一些事情,終究是要自己動手。
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有進一步瞭解,養成這種自己動手的習慣後,對學習其他的演算法有一定幫助,接下來我該轉移到其他問題學習,當知識豐富後還會在回過頭來重新審視今天這些內容,並加以完善。