2011-10-17 10 views
7

http://www.fftw.org/のライブラリを使用してイメージをFFTして、周波数領域で畳み込みを行うことができます。しかし、私はそれを動作させる方法を理解できません。 これを行う方法を理解するには、イメージをピクセルカラーの配列としてFFTを転送し、ピクセルカラーの同じ配列を取得するために逆FFTを実行しようとしています。ここで私は何をすべきかです:イメージを前方にFFTし、イメージを逆FFTして同じ結果を得る

fftw_plan planR, planG, planB; 
fftw_complex *inR, *inG, *inB, *outR, *outG, *outB, *resultR, *resultG, *resultB; 

//Allocate arrays. 
inR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
inG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
inB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 

outR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
outG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
outB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 

resultR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
resultG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
resultB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 

//Fill in arrays with the pixelcolors. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     inR[y * width + x][0] = pixelColors[currentIndex]; 
     inG[y * width + x][0] = pixelColors[currentIndex + 1]; 
     inB[y * width + x][0] = pixelColors[currentIndex + 2]; 
    } 
} 

//Forward plans. 
planR = fftw_plan_dft_2d(width, width, inR, outR, FFTW_FORWARD, FFTW_MEASURE); 
planG = fftw_plan_dft_2d(width, width, inG, outG, FFTW_FORWARD, FFTW_MEASURE); 
planB = fftw_plan_dft_2d(width, width, inB, outB, FFTW_FORWARD, FFTW_MEASURE); 

//Forward FFT. 
fftw_execute(planR); 
fftw_execute(planG); 
fftw_execute(planB); 

//Backward plans. 
planR = fftw_plan_dft_2d(width, width, outR, resultR, FFTW_BACKWARD, FFTW_MEASURE); 
planG = fftw_plan_dft_2d(width, width, outG, resultG, FFTW_BACKWARD, FFTW_MEASURE); 
planB = fftw_plan_dft_2d(width, width, outB, resultB, FFTW_BACKWARD, FFTW_MEASURE); 

//Backward fft 
fftw_execute(planR); 
fftw_execute(planG); 
fftw_execute(planB); 

//Overwrite the pixelcolors with the result. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     pixelColors[currentIndex] = resultR[y * width + x][0]; 
     pixelColors[currentIndex + 1] = resultG[y * width + x][0]; 
     pixelColors[currentIndex + 2] = resultB[y * width + x][0]; 
    } 
} 

は、誰かが私にFFT画像、その後、後方FFT同じ結果を得るためにFFTWを使用して画像を転送する方法の例を示していただけますか?私は、FFTWをFFTに使用する方法を示す多くの例を見てきましたが、イメージを表すピクセルカラーの配列を持つ私の状況にどのように適用されるのか理解できません。

答えて

15

逆FFTを実行した後にFFTを実行するときに重要な点の1つは、通常は結果のNにスケーリングファクタNが適用されることです。つまり、結果の画像ピクセル値をNで割る必要があります。元のピクセル値と一致させる。 (Nは、FFTのサイズである。)だからあなたの出力ループは、おそらく次のようになります。

//Overwrite the pixelcolors with the result. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     pixelColors[currentIndex] = resultR[y * width + x][0]/(width * height); 
     pixelColors[currentIndex + 1] = resultG[y * width + x][0]/(width * height); 
     pixelColors[currentIndex + 2] = resultB[y * width + x][0]/(width * height); 
    } 
} 

はまた、あなたはおそらく、複雑なツー続いリアル - 複素数FFTをしたいということに注意してください実IFFT(メモリとパフォーマンスの面でいくらか効率的です)。今のところは両方向で複雑な複雑な処理を行っているようですが、入力配列を正しく埋めるわけではありません。あなたは、複雑なツー複雑に固執するつもりなら、あなたはおそらく、あなたの入力ループは、このようなものに変更したい:ピクセル値は、複雑な入力値の実部に入る。すなわち

//Fill in arrays with the pixelcolors. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     inR[y * width + x][0] = (double)pixelColors[currentIndex]; 
     inR[y * width + x][1] = 0.0; 
     inG[y * width + x][0] = (double)pixelColors[currentIndex + 1]; 
     inG[y * width + x][1] = 0.0; 
     inB[y * width + x][0] = (double)pixelColors[currentIndex + 2]; 
     inB[y * width + x][1] = 0.0; 
    } 
} 

と虚数部はゼロにする必要があります。

もう1つ注意してください。実際にこの作業を行うと、パフォーマンスがひどくなることがわかります。実際のFFTにかかる時間に比べて計画を作成するまでには時間がかかります。計画は一度作成するだけですが、多くのFFTを実行するために使用します。したがって、プランの作成を実際のFFTコードから切り離して、初期化ルーチンやコンストラクタなどに入れたいと思うでしょう。

2

realToComplexまたはComplexToRealFunctionを使用する場合は、イメージが次元[高さx(幅/ 2 +1)]のマトリックスに格納されることに注意してください。中間の計算を周波数領域、彼らは少し難しくなります...

関連する問題