如何使用 iOS 加速框架正确填充 FFT 的二维数组
how to correctly pad 2D array for FFT with iOS Accelerate framework
我正在使用 iOS Accelerate 框架来查找二维数组的 FFT。下面的代码可以正常工作仅 2 图像的幂。我们必须用 zeros
填充输入数组以获得非 2 图像的幂。但我无法正确进行填充。目前我填充数组如下
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 数组输出,在 (0,0) 处的值为 16。
加速 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;
}
您可能正确地进行了零填充。任何认为在补零后结果相同的期望都是不正确的。所有 FFT bin 频率将改为与较大尺寸的阵列相关。
添加我的 假设 根据 Paul R 对问题的评论回答(可能是错误的,因为我对 FFT usage/purpose 的理解几乎为零)
- 使用 iOS Accelerate 框架,您无法精确计算大小为非 2 的幂的 2D array/matrix 的 FFT。您可以将数组零填充为 2 的幂,但这会影响结果.
- 大多数情况下,您可以使用 2 的非幂来完成。例如,我正在尝试计算两个 2D 矩阵之间的卷积,并且没有必要这样做以获得精确的 m * n FFT。在此处示例(1).
- 与问题无关:如果你试图用 Accelerate
vDSP_fft2d_zripD
替换 OpenCV 的 dft
方法,希望获得更好的性能,我觉得有 none 或者只有差远了。即使接受缓冲区的重用对 Accelerate 的性能至关重要,也令人失望。可能是我的错误代码。
我正在使用 iOS Accelerate 框架来查找二维数组的 FFT。下面的代码可以正常工作仅 2 图像的幂。我们必须用 zeros
填充输入数组以获得非 2 图像的幂。但我无法正确进行填充。目前我填充数组如下
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 数组输出,在 (0,0) 处的值为 16。
加速 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;
}
您可能正确地进行了零填充。任何认为在补零后结果相同的期望都是不正确的。所有 FFT bin 频率将改为与较大尺寸的阵列相关。
添加我的 假设 根据 Paul R 对问题的评论回答(可能是错误的,因为我对 FFT usage/purpose 的理解几乎为零)
- 使用 iOS Accelerate 框架,您无法精确计算大小为非 2 的幂的 2D array/matrix 的 FFT。您可以将数组零填充为 2 的幂,但这会影响结果.
- 大多数情况下,您可以使用 2 的非幂来完成。例如,我正在尝试计算两个 2D 矩阵之间的卷积,并且没有必要这样做以获得精确的 m * n FFT。在此处示例(1).
- 与问题无关:如果你试图用 Accelerate
vDSP_fft2d_zripD
替换 OpenCV 的dft
方法,希望获得更好的性能,我觉得有 none 或者只有差远了。即使接受缓冲区的重用对 Accelerate 的性能至关重要,也令人失望。可能是我的错误代码。