5

通常の畳み込みを使用したガウスぼかしの現在の実装があります。小さなカーネルには十分効率的ですが、カーネルのサイズが少し大きくなると、パフォーマンスが低下します。そこで、FFTを使って畳み込みを実装することを考えています。FFT関連の画像処理の経験がないので、いくつか質問があります。

  1. 2D FFTベースの畳み込みも2つの1D畳み込みに分離できますか?

    • trueの場合、次のようになりますか?すべての行で1D FFT、次にすべての列で1D FFT、次に2Dカーネルで乗算し、次にすべての列の逆変換とすべての行の逆変換を行いますか?または、各1D FFT変換の後に1Dカーネルで乗算する必要がありますか?
  2. これで、カーネルサイズは画像と同じサイズ(1Dの場合は行)である必要があることがわかりました。しかし、それはエッジにどのように影響しますか?画像の端をゼロで埋める必要がありますか?もしそうなら、カーネルサイズはパディングの前後の画像サイズと等しくなければなりませんか?

また、これはC ++プロジェクトであり、商用プロジェクトであるため、kissFFTを使用する予定です。より良い代替案を提案することを歓迎します。ありがとうございました。

編集:回答ありがとうございますが、もう少し質問があります。

  1. 入力画像の虚数部がすべてゼロになることがわかります。しかし、出力の虚数部もゼロになりますか?ガウスカーネルを実数部と虚数部の両方に乗算する必要がありますか?

  2. 同じ画像のインスタンスが異なるスケールでぼやけています。つまり、同じ画像が異なるサイズにスケーリングされ、異なるカーネルサイズでぼやけています。画像を拡大縮小するたびにFFTを実行する必要がありますか、それとも同じFFTを使用できますか?

  3. 最後に、FFTを視覚化する場合は、ログフィルターをFFTに適用する必要があることを理解しています。しかし、FFTを視覚化するためにどの部分を使用すべきか本当に迷っていますか?実数部または虚数部。

  4. また、512x512のサイズの画像の場合、実数部と虚数部のサイズはどうなりますか。それらは同じ長さになりますか?

詳細な返信ありがとうございます。

4

2 に答える 2

12
  1. 2-D FFTは分離可能であり、2Dカーネルの2-D FFTを乗算する必要があることを除いて、実行方法は正しいです。kissfftを使用している場合、2-D FFTを実行する簡単な方法kiss_fftndは、kissfftパッケージのtoolsディレクトリで使用することです。これにより、多次元FFTが実行されます。

  2. カーネルサイズは特定のサイズである必要はありません。カーネルが画像よりも小さい場合は、2-D FFTを実行する前に、画像サイズまでゼロパッドする必要があります。また、周波数領域での乗算によって実行される畳み込みは実際には巡回畳み込みであり、結果はエッジでラップアラウンドするため、画像のエッジをゼロパッドする必要があります。

要約すると(画像サイズがM x Nであると仮定して):

  1. 任意のサイズ(U x V)の2Dカーネルを考え出す
  2. カーネルを(M + U-1)x(N + V-1)までゼロパッドします。
  3. カーネルの2次元フーリエ変換を取ります
  4. (M + U-1)x(N + V-1)まで画像をゼロパッドします
  5. 画像の2-DFFTを取得します
  6. カーネルのFFTに画像のFFTを掛ける
  7. 結果の逆2-DFFTを取ります
  8. 端のゴミを切り落とす

異なる画像に対して同じフィルターを複数回実行している場合は、毎回1〜3回実行する必要はありません。

注: これを畳み込みの直接計算よりも高速にするには、カーネルサイズをかなり大きくする必要があります。また、2次元ガウスフィルターが分離可能であるという事実を利用して、直接畳み込みを実装しましたか(「力学」セクションのこのいくつかの段落を参照)。つまり、行と列の1次元畳み込みとして2次元畳み込みを実行できます。カーネルが非常に大きくない限り、これはほとんどのFFTベースのアプローチよりも高速であることがわかりました。

編集への応答

  1. 入力が実数の場合、まれな状況を除いて、出力は依然として複雑になります。ガウスカーネルのFFTも複雑になるため、乗算は複雑な乗算である必要があります。逆FFTを実行する場合、入力イメージとカーネルが実数であるため、出力は実数である必要があります。出力は複雑な配列で返されますが、虚数成分はゼロまたは非常に小さい(浮動小数点エラー)必要があり、破棄できます。

  2. 同じイメージを使用している場合は、イメージFFTを再利用できますが、最大のカーネルサイズに基づいてゼロパッドする必要があります。さまざまなカーネルすべてのFFTを計算する必要があります。

  3. 視覚化には、複雑な出力の大きさを使用する必要があります。対数目盛は、大きなコンポーネントが線形スケールでそれらを溺れさせるときに、出力の小さなコンポーネントを視覚化するのに役立ちます。デシベルスケールがよく使用され、どちらか20*log10(abs(x))または10*log10(x*x')同等のものによって与えられます。(xは複素fft出力でありx'、はの複素共役ですx)。

  4. FFTの入力と出力は同じサイズになります。また、1つの実数値と1つの虚数値が単一のサンプルを形成するため、実数部と虚数部は同じサイズになります。

于 2011-08-16T14:40:53.727 に答える
5

空間での畳み込みは、周波数領域での乗算と同等であることを忘れないでください。つまり、画像とマスク(カーネル)の両方のFFTを実行すると、ポイントごとの乗算を実行してから、結果のIFFTを実行するだけで済みます。そうは言っても、ここにいくつかの注意点があります。

デジタル信号処理では、線形畳み込みではなく、巡回畳み込みを使用することがよくあります。これは、不思議な周期性のために発生します。これが簡単に言うと、DFT(およびその計算効率の高いバリアントであるFFT)は、信号が周期的であると想定し、そのような方法で信号をフィルタリングすると(画像がN x Mピクセルであると仮定します)、隣接するピクセル(1、m )または( Nm)のピクセル( m < M )。あなたは事実上それ自体にラップアラウンドすることを合図します。これは、ガウスマスクが右端のピクセルと左端のピクセルを平均化することを意味し、同じことが上下にも当てはまります。これは望ましい場合と望ましくない場合がありますが、一般に、とにかくエッジングアーティファクトを処理する必要があります。ただし、FFT乗算を処理する場合は、問題が明らかにならないため、この問題を忘れるのははるかに簡単です。この問題に対処する方法はたくさんあります。最良の方法は、画像にゼロを埋め込み、後で余分なピクセルを削除することです。

周波数領域でガウスフィルターを使用することの非常に優れた点は、FFTを実際に使用する必要がないことです。ガウスのフーリエ変換がガウスであることはよく知られている事実です技術的な詳細はこちら)。次に行う必要があるのは、画像にゼロ(上部と下部の両方)を埋め込み、周波数領域でガウス分布を生成し、それらを乗算してIFFTを取得することだけです。その後、完了です。

お役に立てれば。

于 2011-08-16T14:49:08.633 に答える