频域旋转 - 关于问题 64441200 的问题

rotation in frequency domain - question about question 64441200

以下:

我只是 运行 这个确切的代码(从作者的代码复制粘贴,只对结果图像在 0 和 255 之间进行额外的规范化,如图所示) ...但是我得到了可怕的“混叠”伪像...这怎么可能?我看到 OP 显示了来自频率旋转的漂亮的非人工图像 space...我很想知道如何获得它,你肯定没有显示所有代码吗?

import numpy as np
import cv2
from numpy.fft import fftshift as fftshift
from numpy.fft import ifftshift as ifftshift

angle = 30
M = cv2.imread("phantom.png")
M = cv2.cvtColor(M, cv2.COLOR_BGR2GRAY)
M=np.float32(M)
hanning=cv2.createHanningWindow((M.shape[1],M.shape[0]),cv2.CV_32F)
M=hanning*M
sM = fftshift(M)
rotation_center=(M.shape[1]/2,M.shape[0]/2)
rot_matrix=cv2.getRotationMatrix2D(rotation_center,angle,1.0)

FsM = fftshift(cv2.dft(sM,flags = cv2.DFT_COMPLEX_OUTPUT))
rFsM=cv2.warpAffine(FsM,rot_matrix,(FsM.shape[1],FsM.shape[0]),flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
IrFsM = ifftshift(cv2.idft(ifftshift(rFsM),flags=cv2.DFT_REAL_OUTPUT))

x = IrFsM
x = ((x-np.min(x[:]))/(np.max(x[:])-np.min(x[:])))*255.0
cv2.imwrite('rotated_phantom.png',x)

输出图像是:

此外,我一直被告知不可能正确旋转(离散的,不连续的)傅立叶 space 因为插值,所以你怎么解释呢?

DFT 在频域和空间域对图像施加周期性(有些人不同意这一点,但仍然同意这种观点是解释 DFT 中发生的几乎所有事情的好方法。. .).因此,假设您的输入不是 Shepp-Logan 幻影,而是它的无限重复。在频域中处理数据时,您不仅会影响您看到的图像的一个副本,还会影响所有图像,而且并不总是以直观的方式。

其中一个后果是您的图像在空间域中的相邻副本会旋转,但也会扩展并进入您的图像。

避免这种情况的最简单方法是用零填充图像以使其大小加倍。

import numpy as np
import cv2
from numpy.fft import fftshift as fftshift
from numpy.fft import ifftshift as ifftshift

angle = 30
M = cv2.imread("shepp-logan-small.tif")
M = cv2.cvtColor(M, cv2.COLOR_BGR2GRAY)
M = np.float32(M)

# Pad
v, h = M.shape
v //= 2
h //= 2
M = cv2.copyMakeBorder(M, v, v, h, h, cv2.BORDER_CONSTANT)

现在您可以像以前一样在频域中应用旋转。但是注意旋转的中心应该是shape//2处的像素点,不要使用真正的分割!另请注意,我们不再需要应用 window 函数。

sM = fftshift(M)
rotation_center = (M.shape[1]//2,M.shape[0]//2)
rot_matrix = cv2.getRotationMatrix2D(rotation_center,angle,1.0)

FsM = fftshift(cv2.dft(sM,flags = cv2.DFT_COMPLEX_OUTPUT))
rFsM = cv2.warpAffine(FsM,rot_matrix,(FsM.shape[1],FsM.shape[0]),flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
IrFsM = ifftshift(cv2.idft(ifftshift(rFsM),flags=cv2.DFT_REAL_OUTPUT))

最后,将结果裁剪回其原始大小。

# Crop
IrFsM = IrFsM[v:-v, h:-h]

请注意,结果并不漂亮。在空间域中旋转要好得多,因为正如您所说,频域中的插值并不是很有意义。