关于 python:FFTW3 上的复杂 numpy 数组直接在 scipy.weave.inline

FFTW3 on complex numpy array directly in scipy.weave.inline

我正在尝试在 Python 中实现基于 FFT 的亚像素移位(平移)算法。傅里叶位移定理允许将阵列平移一个子像素量:
1.正向FFT阵列
2. 在傅里叶空间中将阵列乘以线性相位斜坡
3. 逆FFT数组

这个算法很容易在 python 中使用 numpy/scipy 实现,但是对于 256**2 数组来说,每班的速度非常慢(~10 毫秒)。我试图通过使用 scipy.weave.inline 直接从 python 调用 c 代码来加快速度。

我在将复杂的 numpy 数组传递给 FFTW 时遇到了麻烦。 c 代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    #include <fftw3.h>
    #include <stdlib.h>

    #define INVERSE +1
    #define FORWARD -1


    fftw_complex *i, *o;
    int n, m;
    fftw_plan pf, pi;
    #line 22"test_scipy_weave.py"

    i = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * xdim*ydim);
    o = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * xdim*ydim);

    pf = fftw_plan_dft_2d(xdim, ydim, i, o, -1, FFTW_PATIENT);
    pi = fftw_plan_dft_2d(xdim, ydim, o, i,  1, FFTW_PATIENT);

    # Copy data to fftw_complex array. How to use python arrays directly
    for (n=0; n<xdim;n++){
        for (m=0; m<ydim; m++){
            i[n*xdim+m][0]=a[n*xdim+m].real();
            i[n*xdim+m][1]=a[n*xdim+m].imag();
        }
    }

    fftw_execute(pf);

    /* Mult by linear phase ramp here */

    fftw_execute(pi);

    for (n=0; n<xdim;n++){
        for (m=0; m<ydim; m++){
            b[n*xdim+m] = std::complex<double>([in*xdim+m][0], i[n*xdim+m][1]);
        }
    }

    fftw_destroy_plan(p);

所以你可以看到我必须将存储在 numpy 数组 "a" 中的数据复制到 fftw_complex 数组 "i" 中。最后,我必须将结果 "i" 复制到输出 numpy 数组 "b" 中。直接在 fftw 中使用 numpy 数组 "a" 和 "b" 会更有效,但我无法让它工作。

有没有人知道如何让 fftw 直接在 scipy.weave.inline 中使用复杂的 numpy 数组?

谢谢


根据fftw手册,可以在fftw.h之前导入complex.h,这样可以保证fftw_complex对应native C数据类型。我很确定 numpy 数据类型也保证(或实际上可能)与本机 C 数据类型兼容。

在这种情况下,您可以像 a.data_as(ctypes.c_void_p) 一样访问指向数组数据的指针。不幸的是,ctypes 不能识别复杂类型,但希望转换为 void 指针可以解决问题。

这样做时,您必须小心您的数组 a 以 C 连续方式存储,由创建数组时的参数 order='C' 指定。