Свертка БПФ - как применить ядро

Я новичок в обработке изображений и обнаружил, что свертка БПФ значительно ускоряет свертку при больших размерах ядра.

Мой вопрос: как я могу применить ядро ​​к изображению в частотном пространстве при использовании 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).

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

Как я думаю:

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


person Marco    schedule 09.08.2011    source источник
comment
Похоже, вы правильно поняли. Когда вы говорите в последнем предложении, что на самом деле не работает, что вы имеете в виду именно?   -  person Paul R    schedule 09.08.2011
comment
Что ж, после обратного преобразования изображение выглядит мусором. Я все еще узнаю изображение, но в нем много цветов, инвертированное изображение в градациях серого и некоторые другие вещи, так что это бесполезно ^^   -  person Marco    schedule 09.08.2011
comment
Я прочитал еще кое-что о свертке БПФ, и некоторые говорят, что мне также нужно заполнить исходное изображение, зачем мне это делать и до какого размера?   -  person Marco    schedule 09.08.2011
comment
В этом PDF-файле есть несколько полезных диаграмм, которые должны помочь объяснить: developer.download.nvidia.com/compute/cuda/2_2/sdk/website/ - фактическая реализация предназначена для CUDA, но вводные детали довольно общие.   -  person Paul R    schedule 09.08.2011
comment
Спасибо, это мне очень помогло;)   -  person Marco    schedule 09.08.2011


Ответы (1)


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

person Jens    schedule 10.08.2011