如何使用iOS Accelerate框架正确填充用于FFT的2D阵列

时间:2015-04-02 15:07:25

标签: ios fft accelerate-framework vdsp

我正在使用iOS Accelerate框架来查找2D数组的FFT。对于2张图片的功能,下面的代码正常。对于2个图像的非幂,我们必须使用zeros填充输入数组。但我无法正确填充。目前我填充如下的数组

float inputImg2D[3][3] = { 1,1,1, 1,1,1, 1,1,1 }; 
float paddedImg2D[4][4] = { 1,1,1,0, 1,1,1,0, 1,1,1,0, 0,0,0,0 };
float expectedOutput[6]6] = { 9,0,0,0,0,0
                              0,0,0,0,0,0
                              0,0,0,0,0,0
                              0,0,0,0,0,0
                              0,0,0,0,0,0
                              0,0,0,0,0,0 };

对于4 * 4数组,我正确输出为8 * 8数组,值为16(0,0)。

加速FFT代码。

/* 
 * 2D fft sample working only for power of 2 images.
 * expected output for below 3*3 array is a 6*6 array with value 9 at ( 0,0) - all other values will be zero
 * expected output for below 4*4 array is a 8*8 array with value 16 at (0,0) - all other values will be zero
 */

#include <stdio.h>
#include "Accelerate/Accelerate.h"

#define NON_POWER_OF_2_TEST_WILL_FAIL

int main(int argc, const char * argv[]) {

#ifdef NON_POWER_OF_2_TEST_WILL_FAIL
    const int IMG_ROWS = 3;
    const int IMG_COLS = 3;
    float img2D[3][3] = { 1,1,1, 1,1,1, 1,1,1 };
#else
    const int IMG_ROWS = 4;
    const int IMG_COLS = 4;
    float img2D[4][4] = { 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 };
#endif

    /*  build necessary values for fft setup */
    int maxDimension = ( IMG_ROWS > IMG_COLS ) ? IMG_ROWS : IMG_COLS;
    int optimalDftSize = ceil( log2( maxDimension) );

    /* fft setup */
    FFTSetup fftSetup = vDSP_create_fftsetup( optimalDftSize, FFT_RADIX2 );

    /* expand images to power of two size with zero values*/
    COMPLEX_SPLIT in_fft;
    int optimalDftWidth = 1 << optimalDftSize;
    int optimalDftHeight = 1 << optimalDftSize;
    int numElements = optimalDftWidth * optimalDftHeight;
    in_fft.realp = ( float* ) calloc ( numElements, sizeof(float) );
    in_fft.imagp = ( float* ) calloc ( numElements, sizeof(float) );

    /* assign image pixels if only in range */
    for ( int i = 0; i < optimalDftWidth; i++ ) {
        for ( int j = 0; j < optimalDftHeight; j++ ) {
            if (i < IMG_ROWS && j < IMG_COLS) {
                in_fft.realp[i * optimalDftHeight + j] = img2D[i][j];
                //in_fft.imagp[i] = 0.0;
            }
        }
    }

    /* do fft in place */
    int rowStride = 1;
    int columnStride = 0;
    vDSP_fft2d_zip(fftSetup, &in_fft, rowStride, columnStride, optimalDftSize, optimalDftSize, FFT_FORWARD);

    /* print results */
    for(int i=0; i < optimalDftWidth; ++i) {
        for(int j=0; j < optimalDftHeight; ++j) {
            printf (" %.2f, %.2f, ", in_fft.realp[i*optimalDftHeight+j], in_fft.imagp[i*optimalDftHeight+j] );
        }
        printf("\n");
    }

    /* TODO: free resources */
    return 0;
}

2 个答案:

答案 0 :(得分:2)

您可能正确进行零填充。在零填充之后结果将是相同的任何期望是不正确的。相反,所有FFT bin频率都与较大尺寸的阵列相关。

答案 1 :(得分:1)

添加我的假设由Paul R对问题的评论回复(可能是错误的,因为我对FFT使用/目的的理解几乎为零)

  1. 使用iOS Accelerate框架,您无法精确计算尺寸为2的非幂的二维数组/矩阵的FFT。您可以将数组填充为2的幂,但这会影响结果。
  2. 大多数情况下你可以完成非2的幂。例如,我试图计算两个二维矩阵之间的卷积,并且没有必要做一个精确的m * n FFT。此处示例(1)。
  3. 与问题无关:如果您尝试使用加速dft替换OpenCV的vDSP_fft2d_zripD方法,为了获得更好的性能,我觉得没有或只有更糟糕的情况。即使接受重用缓冲区对于加速性能至关重要,也令人失望。可能是我糟糕的代码。