3

私は画像処理にかなり慣れていませんが、FFT畳み込みにより、カーネルサイズが大きい場合に畳み込みが大幅に高速化されることがわかりました。

私の質問は、kissFFTを使用しているときに、周波数空間の画像にカーネルを適用するにはどうすればよいですか?

私はすでに次のことをしました:

//I have an image with RGB pixels and given width/height

const int dim[2] = {height, width}; // dimensions of fft
const int dimcount = 2; // number of dimensions. here 2
kiss_fftnd_cfg stf = kiss_fftnd_alloc(dim, dimcount, 0, 0, 0); // forward 2d
kiss_fftnd_cfg sti = kiss_fftnd_alloc(dim, dimcount, 1, 0, 0); // inverse 2d

kiss_fft_cpx *a = new kiss_fft_cpx[width * height];
kiss_fft_cpx *r = new kiss_fft_cpx[width * height];
kiss_fft_cpx *g = new kiss_fft_cpx[width * height];
kiss_fft_cpx *b = new kiss_fft_cpx[width * height];
kiss_fft_cpx *mask = new kiss_fft_cpx[width * height];

kiss_fft_cpx *outa = new kiss_fft_cpx[width * height];
kiss_fft_cpx *outr = new kiss_fft_cpx[width * height];
kiss_fft_cpx *outg = new kiss_fft_cpx[width * height];
kiss_fft_cpx *outb = new kiss_fft_cpx[width * height];
kiss_fft_cpx *outmask = new kiss_fft_cpx[width * height];

for(unsigned int i=0; i<height; i++) {
    for(unsigned int l=0; l<width; l++) {
        float red = intToFloat((int)Input(i,l)->Red);
        float green = intToFloat((int)Input(i,l)->Green);
        float blue = intToFloat((int)Input(i,l)->Blue);

        int index = i * height + l;

        a[index].r = 1.0;
        r[index].r = red;
        g[index].r = green;
        b[index].r = blue;
    }
}

kiss_fftnd(stf, a, outa);
kiss_fftnd(stf, r, outr);
kiss_fftnd(stf, g, outg);
kiss_fftnd(stf, b, outb);
kiss_fftnd(stf, mask, outmask);


kiss_fftnd(sti, outa, a);
kiss_fftnd(sti, outr, r);
kiss_fftnd(sti, outg, g);

画像にRGB値を再度設定すると、元の画像が元に戻ります。したがって、変換は機能します。9x9ボックスブラー(1 / 9、1 / 9、... 1/9)などのカーネルを適用する場合は、今何をすべきですか。

高速畳み込みについていくつか読んだことがありますが、FFTの実装によって、それらはすべて異なります。フィルタを適用する前に注意しなければならないことの一種の「リスト」はありますか?

私の考え方:

imagesizeは2の累乗でなければなりません。画像と同じサイズのカーネルを作成する必要があります。9つの中間値を1/9に、残りを0に設定してから、このカーネルを周波数領域に変換し、ソースイメージにそれを乗算してから、ソースイメージを元に戻します。しかし、それは実際には機能しません:DD

4

1 に答える 1

4

周波数領域で実行される畳み込みは、実際には巡回畳み込みです。したがって、カーネルのゼロ以外の要素が画像の端に到達すると、カーネルはラップアラウンドし、画像の反対側からのピクセルを含みますが、これはおそらくあなたが望むものではありません。これに対処するには、カーネルにゼロ以外の要素があるのと同じ数の要素で入力をゼロパッドします(実際には1つ少なくなります)。3x3カーネルでは、各次元に3-1=2のゼロピクセルを追加する必要があります。

于 2011-08-10T07:13:45.963 に答える