【问题标题】:How to correctly replace the real part of the FFT?如何正确替换 FFT 的实部?
【发布时间】:2021-11-30 06:58:04
【问题描述】:

我尝试重现一种数据增强方法,来自论文:

Qinwei Xu、Ruipen Zhang、Ya Zhang、Yanfeng Wang 和 Qi Tian "A Fourier-based Framework for Domain Generalization" (CVPR 2021)。

论文中提到他们将实部设置为常数(论文中的常数为20000)以消除幅度,实现仅依赖相位的图像重建。 以下是我的代码:

img = process_img("./data/house.jpg", 128)
img_fft = torch.fft.fft2(img, dim=(-2, -1))
amp = torch.full(img_fft.shape, 200000)
img_fft.real = amp
img_ifft = torch.fft.ifft2(img_fft, dim=(-2, -1))

img_ifft = img_ifft.squeeze(0)
img_ifft = img_ifft.transpose(2, 0)

img_ifft = np.array(img_ifft)

cv2.imshow("", img_ifft.real)

其中process_img函数仅用于将ndarray转换为张量,如下图:

loader = transforms.Compose([transforms.ToTensor()])
def process_img(img_path, img_size):
    img = cv2.imread(img_path)
    img = cv2.resize(img, (img_size, img_size))
    img = img.astype(np.float32) / 255.0
    img = loader(img)
    img = img.unsqueeze(0)
    return img

第一个是原图,第二个是论文提供的图像,第三个是我的代码生成的图像:

可以看出,我的方法生成的图像与论文中提供的图像有很大不同,并且存在一些伪影。为什么会有这样的结果?

【问题讨论】:

  • 你也可以链接论文吗?
  • 对不起,我忘了放论文的链接,我的错。基于傅里叶的域泛化框架:openaccess.thecvf.com/content/CVPR2021/papers/…
  • 我尝试重现您的代码并使用不同的常量值(20000、2000、200、20、2 甚至 0,所以这里似乎没有意义)得到相同的结果.而且我在论文中找不到20000。
  • 在论文的补充材料“B.2. PACS 上的单域评估”中有说明
  • 请注意,当您将实部设置为 1 时,部分效果是您将零频率分量更改为 1。零频率分量是图像的均值。这相当于在输入图像中减去平均值并加 1,这会将许多像素设置为负值(显示为黑色)。如果您对生成的图像进行对比拉伸,您会看到添加了图像并且图像旋转了 180 度并反转。

标签: python pytorch conv-neural-network fft complex-numbers


【解决方案1】:

您将complex numbers 的“实”/“虚”部分与“幅度”/“相位”表示混淆了。

这里是快速指南:
复数 z 可以用其实部 x 和虚部 ysum 表示:
z = x + j y
或者,一次可以将相同的复数 z 表示为幅度为 r 和角度为 phi 的旋转向量:
z = r exp(j phi) 其中r = sqrt(x^2 + y^2)phi=atan2(x,y)

这张图片(来自Wikipedia)直观地解释了这一点:

在您的代码中,您替换了“真实”部分,但在论文中,他们建议替换“幅度”。

如果要替换幅度:

const_amp = ... # whatever the constant amplitude you want
new_fft = const_amp * torch.exp(1j * img_fft.angle())

# reconstruct the new image from the modulated Fourier:
img_ifft = torch.fft.ifft2(new_fft, dim=(-2, -1))

结果如下图:

【讨论】:

  • 非常感谢!之前在幅度和相位的概念上犯了一个错误,感谢您让我改正这个错误。
  • 如何更换相位?我试图保持幅度恒定并将相位设置为 20000,但结果是一幅完全黑色的画面。我只改了new_fft = torch.abs(img_fft) * torch.exp(img_fft.angle() * 20000j)
  • @wenjiezhu 20000相是什么意思?
  • 我想更换相位部分,保持幅度不变。
  • 哦,非常感谢!你帮了我很多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-06
  • 1970-01-01
  • 2014-07-06
  • 2011-12-06
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多