我正在编写一些代码来恢复相对于使用相位相关( A la Reddy & Chatterji 1996 )的模板的测试图像的旋转、缩放和平移。为了找到标度因子和旋转角度,我采用了原始测试图像的FFT,但是为了得到平移,我需要旋转和缩放测试图像的FFT。
现在我可以在空域应用旋转和缩放,然后采取FFT,但这似乎有点低效-它有可能直接获得频域旋转/缩放图像的傅里叶系数吗?
编辑1: OK,我按照用户1816548的建议做了一个游戏。我可以得到模糊的感觉-旋转角度是90度倍数,尽管在图像的极性发生了奇怪的变化。不是90度倍数的角度给了我相当有趣的结果。
编辑2:,我在图像上加了零填充,当我旋转它的时候,我正在包装FFT的边缘。我很确定我在旋转FFT的直流电分量,但是对于不是90度倍数的角度,我仍然得到了奇怪的结果。
示例输出:
可执行的Numpy/Scipy代码:
import numpy as np
from scipy.misc import lena
from scipy.ndimage.interpolation import rotate,zoom
from scipy.fftpack import fft2,ifft2,fftshift,ifftshift
from matplotlib.pyplot import subplots,cm
def testFourierRotation(angle):
M = lena()
newshape = [2*dim for dim in M.shape]
M = procrustes(M,newshape)
# rotate, then take the FFT
rM = rotate(M,angle,reshape=False)
FrM = fftshift(fft2(rM))
# take the FFT, then rotate
FM = fftshift(fft2(M))
rFM = rotatecomplex(FM,angle,reshape=False)
IrFM = ifft2(ifftshift(rFM))
fig,[[ax1,ax2,ax3],[ax4,ax5,ax6]] = subplots(2,3)
ax1.imshow(M,interpolation='nearest',cmap=cm.gray)
ax1.set_title('Original')
ax2.imshow(rM,interpolation='nearest',cmap=cm.gray)
ax2.set_title('Rotated in spatial domain')
ax3.imshow(abs(IrFM),interpolation='nearest',cmap=cm.gray)
ax3.set_title('Rotated in Fourier domain')
ax4.imshow(np.log(abs(FM)),interpolation='nearest',cmap=cm.gray)
ax4.set_title('FFT')
ax5.imshow(np.log(abs(FrM)),interpolation='nearest',cmap=cm.gray)
ax5.set_title('FFT of spatially rotated image')
ax6.imshow(np.log(abs(rFM)),interpolation='nearest',cmap=cm.gray)
ax6.set_title('Rotated FFT')
fig.tight_layout()
pass
def rotatecomplex(a,angle,reshape=True):
r = rotate(a.real,angle,reshape=reshape,mode='wrap')
i = rotate(a.imag,angle,reshape=reshape,mode='wrap')
return r+1j*i
def procrustes(a,target,padval=0):
b = np.ones(target,a.dtype)*padval
aind = [slice(None,None)]*a.ndim
bind = [slice(None,None)]*a.ndim
for dd in xrange(a.ndim):
if a.shape[dd] > target[dd]:
diff = (a.shape[dd]-target[dd])/2.
aind[dd] = slice(np.floor(diff),a.shape[dd]-np.ceil(diff))
elif a.shape[dd] < target[dd]:
diff = (target[dd]-a.shape[dd])/2.
bind[dd] = slice(np.floor(diff),target[dd]-np.ceil(diff))
b[bind] = a[aind]
return b
发布于 2014-09-29 14:41:57
我不知道这件事是否已经解决,但我相信我有办法解决你在第三个数字中观察到的影响的问题:
你观察到的这个奇怪的效果是由于你实际计算FFT的起源。从本质上说,快速傅立叶变换从M[0][0]
阵列的第一个像素开始。然而,您定义了围绕M[size/2+1,size/2+1]
的旋转,这是正确的方法,但却是错误的。傅里叶域已经从M[0][0]
计算出来了!如果你现在在傅里叶域中旋转,你是围绕M[0][0]
旋转,而不是围绕M[size/2+1,size/2+1]
旋转。我不能完全解释这里到底发生了什么,但你得到的效果和我以前一样。为了在傅里叶域中旋转原始图像,首先必须将二维fftShift
应用于原始图像M,然后计算FFT、旋转、IFFT,然后应用ifftShift
。这样,图像的旋转中心和傅里叶域的中心就同步了。
AFAI记得,我们还在两个独立的数组中旋转实和虚分量,然后将它们合并。我们还对复数上的各种插值算法进行了测试,但效果不大:)。它在我们的包裹化脓性里。
然而,这可能是超级los较少,但与两个额外的移动并不是真正的快速,除非您指定一些时髦的数组索引算法。
发布于 2012-12-06 05:26:11
嗯,旋转和缩放图像的结果是旋转和缩放(用逆尺度)傅里叶变换。
还请注意,旋转和缩放都是线性的像素数,而FFT是O(w*logw*h*logh),所以它实际上并不昂贵。
发布于 2014-09-18 22:08:52
我意识到这太晚了,但我只是想在这里回答这个问题,因为我复习了我关于移位不变的基本知识。问题是,在旋转之前,您是在扩展傅里叶空间(如考虑混叠)。看看旋转图像的FT :轴向尖峰(别名)出现在没有在傅里叶旋转的IFT中的边缘。
你应该旋转,然后处理混叠。因为您正在考虑混叠(在周期=像素数处循环您的傅里叶空间),然后通过旋转丢弃这种努力,所以您将导致混叠出现在您的最终图像中。本质上,你是在展开傅立叶别名,因此把图像空间别名拉到一起.
旋转为90度旋转平稳,因为没有混叠;k空间的角点完全匹配。
https://stackoverflow.com/questions/13744171
复制