【发布时间】:2012-05-29 08:03:30
【问题描述】:
//编辑...
我正在稍微编辑我的问题,以解决专门处理非二次幂图像的问题。我有一个基本结构,适用于大小为 256x256 或 1024x1024 的方形灰度图像,但看不到如何推广到任意大小的图像。 fft 函数似乎希望您包含宽度和高度的 log2,但随后不清楚如何解压缩结果数据,或者数据是否只是被打乱。我想显而易见的事情是将 npot 图像居中在一个更大的全黑图像中,然后在查看数据时忽略这些位置的任何值。但想知道是否有一种不那么尴尬的方式来处理 npot 数据。
//...结束编辑
我在使用 Accelerate Framework 文档时遇到了一些问题。我通常会使用 FFTW3,但我无法在实际的 IOS 设备上编译它(请参阅question)。谁能给我指出一个使用 Accelerate 的超级简单实现,它执行以下操作:
1) 将图像数据转换为可以传递给 Accelerate 的 FFT 方法的适当数据结构。
在 FFTW3 中,最简单的是,使用灰度图像,这涉及将无符号字节放入“fftw_complex”数组中,该数组只是两个浮点数的结构,一个保存实数,另一个保存虚数(虚数在每个像素初始化为零)。
2) 采用此数据结构并对其执行 FFT。
3) 打印出幅度和相位。
4) 对其执行 IFFT。
5) 根据 IFFT 产生的数据重新创建原始图像。
虽然这是一个非常基本的示例,但我在使用 Apple 网站上的文档时遇到了问题。 SO answer by Pi here 非常有帮助,但我仍然对如何使用 Accelerate 使用灰度(或彩色)2D 图像执行此基本功能感到有些困惑。
无论如何,任何指针或特别是一些处理 2D 图像的简单工作代码都会非常有帮助!
\\\编辑\\\
好的,在花了一些时间深入研究文档和一些非常有用的 SO 以及 pkmital's github repo 的代码之后,我有一些我认为我会发布的工作代码 1) 我花了虽然要弄清楚,2)因为我还有几个问题......
初始化 FFT“计划”。假设一个二次方图像:
#include <Accelerate/Accelerate.h>
...
UInt32 N = log2(length*length);
UInt32 log2nr = N / 2;
UInt32 log2nc = N / 2;
UInt32 numElements = 1 << ( log2nr + log2nc );
float SCALE = 1.0/numElements;
SInt32 rowStride = 1;
SInt32 columnStride = 0;
FFTSetup setup = create_fftsetup(MAX(log2nr, log2nc), FFT_RADIX2);
为一个二次方灰度图像传入一个字节数组并将其转换为 COMPLEX_SPLIT:
COMPLEX_SPLIT in_fft;
in_fft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
in_fft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );
for ( UInt32 i = 0; i < numElements; i++ ) {
if (i < t->width * t->height) {
in_fft.realp[i] = t->data[i] / 255.0;
in_fft.imagp[i] = 0.0;
}
}
对转换后的图像数据运行 FFT,然后获取幅度和相位:
COMPLEX_SPLIT out_fft;
out_fft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
out_fft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );
fft2d_zop ( setup, &in_fft, rowStride, columnStride, &out_fft, rowStride, columnStride, log2nc, log2nr, FFT_FORWARD );
magnitude = (float *) malloc(numElements * sizeof(float));
phase = (float *) malloc(numElements * sizeof(float));
for (int i = 0; i < numElements; i++) {
magnitude[i] = sqrt(out_fft.realp[i] * out_fft.realp[i] + out_fft.imagp[i] * out_fft.imagp[i]) ;
phase[i] = atan2(out_fft.imagp[i],out_fft.realp[i]);
}
现在您可以对 out_fft 数据运行 IFFT 以获取原始图像...
COMPLEX_SPLIT out_ifft;
out_ifft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
out_ifft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );
fft2d_zop (setup, &out_fft, rowStride, columnStride, &out_ifft, rowStride, columnStride, log2nc, log2nr, FFT_INVERSE);
vsmul( out_ifft.realp, 1, SCALE, out_ifft.realp, 1, numElements );
vsmul( out_ifft.imagp, 1, SCALE, out_ifft.imagp, 1, numElements );
或者您可以在幅度上运行 IFFT 以获得自相关...
COMPLEX_SPLIT in_ifft;
in_ifft.realp = ( float* ) malloc ( numElements * sizeof ( float ) );
in_ifft.imagp = ( float* ) malloc ( numElements * sizeof ( float ) );
for (int i = 0; i < numElements; i++) {
in_ifft.realp[i] = (magnitude[i]);
in_ifft.imagp[i] = 0.0;
}
fft2d_zop ( setup, &in_fft, rowStride, columnStride, &out_ifft, rowStride, columnStride, log2nc, log2nr, FFT_INVERSE );
vsmul( out_ifft.realp, 1, SCALE, out_ifft.realp, 1, numElements );
vsmul( out_ifft.imagp, 1, SCALE, out_ifft.imagp, 1, numElements );
最后,您可以将 ifft 结果放回图像数组中:
for ( UInt32 i = 0; i < numElements; i++ ) {
t->data[i] = (int) (out_ifft.realp[i] * 255.0);
}
我还没有弄清楚如何使用 Accelerate 框架来处理非二次幂图像。如果我在设置中分配了足够的内存,那么我可以进行 FFT,然后进行 IFFT 以获得我的原始图像。但是,如果尝试进行自相关(与 FFT 的幅度),那么我的图像会得到不稳定的结果。我不确定适当填充图像的最佳方法,所以希望有人知道如何做到这一点。 (或分享 vDSP_conv 方法的工作版本!)
【问题讨论】:
-
看起来你只是在这里做自相关?我认为 Accelerate/vDSP 已经具有自相关功能,因此您不必使用 FFT/IFFT 等自行推出?
-
嗨,加速库中似乎并不存在 vDSP_acor。 vDSP_conv 存在,但它给了我奇怪的结果......也许我错误地使用它来进行图像自相关。如果您(或任何人)有一个使用 vDSP_conv 进行自相关的工作示例,那么很高兴看到它。部分问题在于它对期望和输出中的哪些数据等感到困惑。
标签: ios signal-processing fft vdsp