位相相関を使用して、テンプレートに対するテスト画像の回転、スケーリング、および平行移動を復元するためのコードを作成しています。これは、Reddy&Chatterji1996です。倍率と回転角を見つけるために元のテスト画像のFFTを取得しますが、平行移動を取得するには、回転およびスケーリングされたテスト画像のFFTが必要です。
これで、空間領域で回転とスケーリングを適用してからFFTを取得できますが、それは少し非効率的です-回転/スケーリングされた画像のフーリエ係数を周波数領域で直接取得することは可能ですか?
編集1: OK、user1816548の提案に従って遊んだ。画像の極性に奇妙な変化がありますが、90°の倍数の角度で漠然と感覚的に見える回転を得ることができます。90°の倍数ではない角度は、かなりおかしな結果をもたらします。
編集2: 画像にゼロパディングを適用し、画像を回転させるときにFFTのエッジをラップしています。FFTのDC成分を中心に回転していることは確かですが、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