FFT Convolution - как применять ядро - PullRequest
2 голосов
/ 09 августа 2011

Я довольно новичок в области обработки изображений и обнаружил, что свертка 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).

Я читал кое-что о быстрой свертке, но все они разные, в зависимости от реализации БПФ. Есть ли какой-то «список», о чем мне нужно заботиться, прежде чем применять фильтр?

То, как я думаю:

Размер изображения должен быть степенью 2; Я должен создать ядро, такого же размера, как изображение. Установите 9 средних значений на 1/9, остальные на 0, а затем преобразуйте это ядро ​​в частотную область, умножьте на него исходное изображение, а затем преобразуйте исходное изображение обратно. Но это на самом деле не работает: DD

1 Ответ

3 голосов
/ 10 августа 2011

Свертка, выполненная в частотной области, действительно является круговой сверткой. Поэтому, когда ваши ненулевые элементы ядра достигают края изображения, оно оборачивается и включает пиксели с другой стороны изображения, что, вероятно, не то, что вам нужно. Чтобы справиться с этим, просто добавьте ноль к входу с таким количеством элементов, сколько у вас ненулевых элементов в ядре (фактически, на один меньше). С ядром 3x3 вам нужно добавить 3-1 = 2 нулевых пикселя в каждом измерении.

...