gpt4 book ai didi

c++ - 傅立叶域 : works, 中的图像高斯卷积,但不应该

转载 作者:行者123 更新时间:2023-11-28 02:20:37 25 4
gpt4 key购买 nike

问题是频域的卷积原理我还不能完全理解。

我有一个 大小为 256x256 的图像,我想将其与 3x3 高斯矩阵 进行卷积。它的系数是 (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 .


那么,您能解释一下这种情况下的零填充和归一化现象吗?提前致谢。

最佳答案

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

这是定义在各处的连续函数的真理。
然而在实践中,我们有离散信号和卷积核。
更需要温柔的呵护。

如果你有一个大小为 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)。
通常,这是通过在图像上应用“复制”边界条件并对内核进行零填充。

享受...

附言您能否支持 SE 的新社区提案 - http://area51.stackexchange.com/proposals/86832/ .
我们需要更多人关注,赞成票少于 10 票的问题和更多问题要问。

谢谢。

关于c++ - 傅立叶域 : works, 中的图像高斯卷积,但不应该,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32678652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com