7

我正在编写一些代码来使用相位相关来恢复测试图像相对于模板的旋转、缩放和平移,例如 Reddy & Chatterji 1996。我对原始测试图像进​​行 FFT 以找到比例因子和旋转角度,但随后我需要旋转和缩放测试图像的 FFT 以获得平移。

现在我可以在空间域中应用旋转和缩放然后进行 FFT,但这似乎有点低效 - 是否可以直接在频域中获得旋转/缩放图像的傅立叶系数?

编辑1: 好的,我按照user1816548的建议玩了一下。对于 90o 的倍数的角度,我可以得到模糊合理的旋转,尽管图像的极性发生了奇怪的变化。不是 90o 的倍数的角度给了我非常滑稽的结果。

编辑 2: 我对图像应用了零填充,并且在旋转它时包裹了 FFT 的边缘。我很确定我正在围绕 FFT 的直流分量旋转,但对于不是 90o 倍数的角度,我仍然会得到奇怪的结果。

示例输出:


10o旋转角度

可执行的 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
4

3 回答 3

5

我不确定这是否已经解决,但我相信我已经解决了您关于第三个图中观察到的效果的问题:

您观察到的这种奇怪效果是由于您实际计算 FFT 的来源。本质上,FFT 从数组的第一个像素处开始M[0][0]。但是,您定义围绕 的旋转M[size/2+1,size/2+1],这是正确的方法,但错误:)。傅立叶域是从M[0][0]! 如果你现在在傅里叶域中旋转,你是在旋转M[0][0]而不是在旋转M[size/2+1,size/2+1]。我无法完全解释这里到底发生了什么,但你也会得到我以前得到的相同效果。为了在傅里叶域中旋转原始图像,您必须首先将 2DfftShift应用于原始图像 M,然后计算 FFT、旋转、IFFT,然后再应用ifftShift。这样,图像的旋转中心和傅里叶域的中心就会同步。

AFAI 记得我们还在两个单独的数组中旋转实部和虚部,然后将它们合并。我们还在复数上测试了各种插值算法,但效果不大:)。它在我们的包pytom中。

然而,这可能是超级损失少,但两个额外的转变并不是真的很快,除非你指定一些时髦的数组索引算法。

于 2014-09-29T22:41:57.200 回答
2

好吧,旋转和缩放的图像会导致旋转和缩放(具有反比例)傅立叶变换。

另请注意,旋转和缩放在像素数上都是线性的,而 FFT 是 O(w*logw*h*logh),因此最终它实际上并没有那么昂贵。

于 2012-12-06T13:26:11.407 回答
1

我意识到这很晚了,但我只是想在这里回答这个问题,因为我回顾了我关于移位不变性的基本知识。问题是您在旋转之前扩展了傅立叶空间(如考虑混叠)。查看旋转图像的 FT:轴向尖峰(别名)出现在傅里叶旋转的 IFT 中没有的边缘。

您应该旋转然后处理锯齿。因为您正在考虑混叠(以周期 = 像素数循环傅立叶空间),然后通过旋转放弃该努力,所以您会导致混叠出现在最终图像中。本质上,您正在分散傅立叶别名,因此将图像空间别名集中在一起。

由于没有锯齿,旋转对于 90 度旋转工作顺利;k空间的角落完美匹配。

于 2014-09-19T06:08:52.527 回答