傅里叶域中的图像高斯卷积:有效,但应该是

时间:2015-09-20 11:06:41

标签: c++ image-processing fft gaussian convolution

问题在于我无法完全理解频域中卷积的原理。

我有一个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;
}


为了得到图像和滤波器内核的FFT,我将它们填零。 sz_common代表扩展的大小。图像和内核分别移动到hg ComplexImage的中心位置,因此它们在右侧,左侧,底部和顶部均为零填充。


由于循环卷积属性,我已经读过该大小应为sz_common >= sz+gsz-1:过滤器可以更改边界上不需要的图像值。
但它不起作用:仅在sz_common = szsz_common = sz+gsz-1sz_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);
}

我尝试在右侧和底部零填充图像,这样较小的图像被复制到较大的开头,但它也不起作用。
我在空间域中编写了卷积来比较结果,频率模糊结果几乎与空间域相同(平均误差btw像素为5),仅在sz_common = sz时。

<小时/> 那么,你能解释一下这种情况下零填充和归一化的现象吗?在此先感谢。

1 个答案:

答案 0 :(得分:2)

空间域中的卷积等效于傅里叶域中的乘法。

这是连续功能的真相,这些功能在任何地方都有定义 然而在实践中,我们有离散信号和卷积核 这需要更温柔的关怀。

如果你有一个大小为M x N的图像和一个大小为MM x NN的内核,如果你应用DFT(FFT是计算DFT的一种有效方法),你将得到大小为的函数分别为M x N和MM x NN 此外,关于乘法等价的上述定理要求将相同的频率彼此相乘。

由于内核实际上比图像小得多,因此通常将其填充到图像大小为零。
现在,通过应用DFT,您将获得相同M x N尺寸的矩阵,并且可以将它们相乘。
然而,这将等同于图像和内核之间的循环卷积。

要应用线性卷积,您应使它们的大小均为(M + MM - 1)x(N + NN - 1)。
通常这是通过在图像上应用“复制”边界条件并将零填充到内核。

...享受

P.S。 您是否可以在http://area51.stackexchange.com/proposals/86832/支持新的SE社区提案 我们需要更多人关注,投票少于10票的投票问题以及更多问题。

谢谢。