如何正确替换FFT的实部?
How to correctly replace the real part of the FFT?
我尝试重现一种数据增强方法,该方法来自论文:
Qinwei Xu、Ruipeng 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转tensor,如下图:
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
第一张是原图,第二张是论文提供的图片,第三张是我的代码生成的图片:
可以看出,我的方法生成的图像与论文中提供的图像差别很大,存在一些伪影。为什么会有这样的结果?
您将 complex numbers 的“实部”/“虚部”部分与“幅度”/“相位”表示混淆了。
这是快速指南:
复数 z
可以表示为实部 x
和虚部 y
的 和 :
z = x + j y
或者,once 可以将相同的复数 z
表示为具有幅度 r
和角度 phi
:
的旋转矢量
z = r exp(j phi)
其中 r = sqrt(x^2 + y^2)
和 phi=atan2(x,y)
.
这张图片(来自 Wikipedia)直观地解释了这一点:
在你的代码中,你替换了“real”部分,但在论文中,他们建议替换“amplitude”。
如果要更换振幅:
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))
结果如下图:
我尝试重现一种数据增强方法,该方法来自论文:
Qinwei Xu、Ruipeng 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转tensor,如下图:
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
第一张是原图,第二张是论文提供的图片,第三张是我的代码生成的图片:
可以看出,我的方法生成的图像与论文中提供的图像差别很大,存在一些伪影。为什么会有这样的结果?
您将 complex numbers 的“实部”/“虚部”部分与“幅度”/“相位”表示混淆了。
这是快速指南:
复数 z
可以表示为实部 x
和虚部 y
的 和 :
z = x + j y
或者,once 可以将相同的复数 z
表示为具有幅度 r
和角度 phi
:
的旋转矢量
z = r exp(j phi)
其中 r = sqrt(x^2 + y^2)
和 phi=atan2(x,y)
.
这张图片(来自 Wikipedia)直观地解释了这一点:
在你的代码中,你替换了“real”部分,但在论文中,他们建议替换“amplitude”。
如果要更换振幅:
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))
结果如下图: