Проблема в том, что я не могу полностью понять принципы свертки в частотной области.
У меня есть image of size 256x256
, который я хочу свернуть с 3x3 gaussian matrix
. Его коэффициенты (1/16, 1/8, 1/4
):
PlainImage<float> FourierRunner::getGaussMask(int sz)
{
PlainImage<float> G(3,3);
*G.at(0, 0) = 1.0/16; *G.at(0, 1) = 1.0/8; *G.at(0, 2) = 1.0/16;
*G.at(1, 0) = 1.0/8; *G.at(1, 1) = 1.0/4; *G.at(1, 2) = 1.0/8;
*G.at(2, 0) = 1.0/16; *G.at(2, 1) = 1.0/8; *G.at(2, 2) = 1.0/16;
return G;
}
Чтобы получить БПФ как изображения, так и ядра фильтра, я обнуляю их. sz_common
означает увеличенный размер. Изображение и ядро перемещаются в центр h
и g
ComplexImage
соответственно, поэтому они заполняются нулями справа, слева, снизу и сверху.
Я читал, что размер должен быть
sz_common >= sz+gsz-1
из-за свойство круговой свертки: фильтр может изменять нежелательные значения изображения на границах. Но это не работает: адекватные результаты будут только тогда, когда
sz_common = sz
, когда sz_common = sz+gsz-1
или sz_common = 2*sz
, после IFFT я получаю свернутое изображение в 2-3 раза меньше! Почему? Также меня смущает, что значения матрицы фильтров должны быть умножены на 256, как и значения пикселей: другие вопросы по SO содержат код Matlab без такой нормализации. Как и в предыдущем случае, без такого умножения работает плохо: получается черное изображение. Почему?
//
fft_in
сдвинутое изображение Фурье с центром в [sz/2;sz/2]
void FourierRunner::convolveImage(ComplexImage& fft_in)
{
int sz = 256; // equal to fft_in.width()
// Get original complex image (backward fft_in)
ComplexImage original_complex = fft_in;
fft2d_backward(fft_in, original_complex);
int gsz = 3;
PlainImage<float> filter = getGaussMask(gsz);
ComplexImage filter_complex = ComplexImage::fromFloat(filter);
int sz_common = pow2ceil(sz); // should be sz+gsz-1 ???
ComplexImage h = ComplexImage::zeros(sz_common,sz_common);
ComplexImage g = ComplexImage::zeros(sz_common,sz_common);
copyImageToCenter(h, original_complex);
copyImageToCenter(g, filter_complex);
LOOP_2D(sz_common, sz_common) g.setPoint(x, y, g.at(x, y)*256);
fft2d_forward(g, g);
fft2d_forward(h, h);
fft2d_fft_shift(g);
// CONVOLVE
LOOP_2D(sz_common,sz_common) h.setPoint(x, y, h.at(x, y)*g.at(x, y));
copyImageToCenter(fft_in, h);
fft2d_backward(fft_in, fft_in);
fft2d_fft_shift(fft_in);
// TEST DIFFERENCE BTW DOMAINS
PlainImage<float> frequency_res(sz,sz);
writeComplexToPlainImage(fft_in, frequency_res);
fft2d_forward(fft_in, fft_in);
}
Я попытался обнулить изображение справа и снизу, так что меньшее изображение копируется в начало большего, но это тоже не работает.
Я написал свертку в пространственной области, чтобы сравнить результаты, результаты размытия по частоте < em> почти то же, что и в пространственной области (средняя ошибка между пикселями составляет 5), только когда sz_common = sz
.
Итак, не могли бы вы объяснить явления заполнения нулями и нормализации для этого случая? Заранее спасибо.