2015-06-09 20 views
4

我寫了一個程序,加載,保存,並在黑白png圖像上執行fft和ifft。經過許多調試頭痛之後,我終於得到了一些連貫的輸出,只是發現它扭曲了原始圖像。怪異但密切fft和ifft的圖像在c + +

輸入:

input

FFT:

fft

IFFT:

enter image description here

據我已經測試,像素i的數據每個數組都被正確存儲和轉換。像素存儲在兩個數組中,包含每個像素的b/w值的'data'和'data'的兩倍長的'complex_data',並以交替索引存儲每個像素的實際b/w值和虛部。我的fft算法在像'complex_data'這樣的數組結構上運行。代碼讀取用戶的命令後,這裏是有問題的代碼:

if (cmd == "fft") 
     {    
      if (height > width) size = height; 
      else size = width; 

      N = (int)pow(2.0, ceil(log((double)size)/log(2.0))); 

      temp_data = (double*) malloc(sizeof(double) * width * 2); //array to hold each row of the image for processing in FFT() 

      for (i = 0; i < (int) height; i++) 
      { 
       for (j = 0; j < (int) width; j++) 
       { 
        temp_data[j*2] = complex_data[(i*width*2)+(j*2)]; 
        temp_data[j*2+1] = complex_data[(i*width*2)+(j*2)+1]; 
       } 
       FFT(temp_data, N, 1); 
       for (j = 0; j < (int) width; j++) 
       { 
        complex_data[(i*width*2)+(j*2)] = temp_data[j*2]; 
        complex_data[(i*width*2)+(j*2)+1] = temp_data[j*2+1]; 
       } 
      } 
      transpose(complex_data, width, height); //tested 
      free(temp_data); 
      temp_data = (double*) malloc(sizeof(double) * height * 2); 
      for (i = 0; i < (int) width; i++) 
      { 
       for (j = 0; j < (int) height; j++) 
       { 
        temp_data[j*2] = complex_data[(i*height*2)+(j*2)]; 
        temp_data[j*2+1] = complex_data[(i*height*2)+(j*2)+1]; 
       } 
       FFT(temp_data, N, 1); 
       for (j = 0; j < (int) height; j++) 
       { 
        complex_data[(i*height*2)+(j*2)] = temp_data[j*2]; 
        complex_data[(i*height*2)+(j*2)+1] = temp_data[j*2+1]; 
       } 
      } 
      transpose(complex_data, height, width); 

      free(temp_data); 
      free(data); 

      data = complex_to_real(complex_data, image.size()/4); //tested 
      image = bw_data_to_vector(data, image.size()/4); //tested 
      cout << "*** fft success ***" << endl << endl; 



void FFT(double* data, unsigned long nn, int f_or_b){ // f_or_b is 1 for fft, -1 for ifft 

unsigned long n, mmax, m, j, istep, i; 
double wtemp, w_real, wp_real, wp_imaginary, w_imaginary, theta; 
double temp_real, temp_imaginary; 

// reverse-binary reindexing to separate even and odd indices 
// and to allow us to compute the FFT in place 

n = nn<<1; 
j = 1; 
for (i = 1; i < n; i += 2) { 
    if (j > i) { 
     swap(data[j-1], data[i-1]); 
     swap(data[j], data[i]); 
    } 
    m = nn; 
    while (m >= 2 && j > m) { 
     j -= m; 
     m >>= 1; 
    } 
    j += m; 
}; 

// here begins the Danielson-Lanczos section 

mmax = 2; 
while (n > mmax) { 
    istep = mmax<<1; 
    theta = f_or_b * (2 * M_PI/mmax); 
    wtemp = sin(0.5 * theta); 
    wp_real = -2.0 * wtemp * wtemp; 
    wp_imaginary = sin(theta); 
    w_real = 1.0; 
    w_imaginary = 0.0; 
    for (m = 1; m < mmax; m += 2) { 
     for (i = m; i <= n; i += istep) { 
      j = i + mmax; 
      temp_real = w_real * data[j-1] - w_imaginary * data[j]; 
      temp_imaginary = w_real * data[j] + w_imaginary * data[j-1]; 

      data[j-1] = data[i-1] - temp_real; 
      data[j] = data[i] - temp_imaginary; 
      data[i-1] += temp_real; 
      data[i] += temp_imaginary; 
     } 
     wtemp = w_real; 
     w_real += w_real * wp_real - w_imaginary * wp_imaginary; 
     w_imaginary += w_imaginary * wp_real + wtemp * wp_imaginary; 
    } 
    mmax=istep; 
}} 

我IFFT是一樣的只能用f_or_b設置爲-1,而不是1我的程序上的每一行調用FFT(),轉置該圖像再次調用每行的FFT(),然後轉換回來。我的索引可能有錯誤嗎?

+3

與你的問題沒有關係,但你應該真的在C++中避免malloc/free,並使用new/delete代替。 – Christophe

+0

編碼中的舊習慣c。 –

+1

[Dangerous habit](http://stackoverflow.com/questions/184537/in-what-c​​ases-do-i-use-malloc-vs-new)只要你使用非POD數據 – Christophe

回答

1

不是一個實際的答案,這個問題是調試只有這麼一些提示,而不是:

你的結果是非常糟糕的

它應該是這樣的:

good results

  • 第一行是實際的DFFT結果
  • Re,Im,Power通過不斷放大,否則,你會看到一個黑色的圖像
  • 最後的圖像是原始的IDFFT沒有放大Re,IM結果
  • 第二行是相同的,但DFFT結果被包裹通過圖像的展臺x,y一半大小,以匹配在大多數DIP/CV共同作用的結果文本

正如你可以看到,如果你我DFFT回裹結果結果是不正確的(棋盤面罩)

你剛纔單一的形象DFFT結果

  • 是它的功率譜?
  • 或者你忘記包含虛部?僅查看或者也可能在某處進行計算?

是你的1D ** DFFT工作?**

  • 對真實數據的結果應該是對稱的
  • 檢查從我的評論的鏈接和一些示例一維數組比較結果
  • 調試/修復您的1D FFT第一,然後才移動到一個新的水平
  • 不要忘記測試真實和複雜的數據...

您IDFFT看起來BW(無灰)飽和

  • 所以你放大DFFT結果看到的圖像與使用提供IDFFT代替原有的DFFT結果?
  • 也檢查,如果你不這樣做輪整數沿着計算

提防(I)DFFT溢出的地方/下溢

如果圖像像素強度大,圖像的分辨率也那麼你的計算可能會損失精度。較新的在圖像中看到了這一點,但如果你的圖像是HDR那麼這是可能的。對於大多項式,這是一個通過DFFT計算的卷積的常見問題。

0

建議你看文章http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

克里斯托夫好點,但他誤以爲這不相關的問題,因爲它似乎在現代使用malloc,而不是新的()/免費()不初始化內存或選擇最佳的數據類型,這將導致在下面列出的所有問題: -

可能的原因是:

  1. 簽署一些地方不斷變化的,我也有類似的問題,當一個平臺invok e已經在dll上使用過,值是通過值而不是引用傳遞的。這是由於內存不一定是空的,所以當你的圖像數據進入時,它會對其數值執行布爾數學運算。我建議您在將圖像數據放在那裏之前確保內存是空的。

  2. 內存向右旋轉(ROR以彙編語言)或向左旋轉(ROL)。如果正在使用不一定匹配的數據類型,則會發生這種情況,例如。輸入無符號數據類型的有符號值,或者如果一個變量中的位數不同。

  3. 由於輸入有符號變量的無符號值而丟失數據。結果是1位被丟失,因爲它將被用來確定負值或正值,或者在極端情況下如果二進制補碼發生,數字將在意義上反轉,在維基百科上尋找二進制補碼。

另請參閱如何在使用前清除/分配內存。 http://www.cprogramming.com/tutorial/memory_debugging_parallel_inspector.html

+0

將來,請「編輯」您的答案以添加更多信息,而不是在相同問題中發佈多個答案。 – Matt

1

謝謝大家的意見。所有關於內存破壞的內容,雖然有一點說明問題,但這不是問題的根源。我正在配置的數據大小不是太大,我將它們放在正確的位置。在學習c時,我有很多練習。這個問題不是fft算法,也不是我的2D實現。

我錯過的是在我的ifft代碼最後的縮放1 /(M * N)。由於圖像是512x512,我需要將我的ifft輸出縮放1 /(512 * 512)。此外,我的fft看起來像白噪聲,因爲像素數據沒有重新調整到適合0和255之間。

+0

您應該接受您的答案(點擊左側選票櫃檯旁邊的支票圖標,以便其他人清楚快速地看到您的問題已解決(以及如何) – Spektre