我正在编写一些代码来使用相位相关来恢复测试图像相对于模板的旋转、缩放和平移,例如 Reddy & Chatterji 1996。我对原始测试图像进行 FFT 以找到比例因子和旋转角度,但随后我需要旋转和缩放测试图像的 FFT 以获得平移。
现在我可以在空间域中应用旋转和缩放然后进行 FFT,但这似乎有点低效 - 是否可以直接在频域中获得旋转/缩放图像的傅立叶系数?
编辑1: 好的,我按照user1816548的建议玩了一下。对于 90o 的倍数的角度,我可以得到模糊合理的旋转,尽管图像的极性发生了奇怪的变化。不是 90o 的倍数的角度给了我非常滑稽的结果。
编辑 2: 我对图像应用了零填充,并且在旋转它时包裹了 FFT 的边缘。我很确定我正在围绕 FFT 的直流分量旋转,但对于不是 90o 倍数的角度,我仍然会得到奇怪的结果。
示例输出:
可执行的 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