使用IOS加速框架在非电源 – 二 – 图像上进行二维信号处理?
//编辑…
我正在编辑我的问题,以解决与非功率的两个图像专门工作的问题。 我有一个基本的结构,与像256×256或1024×1024尺寸的方形灰度图像,但不能看到如何推广到任意大小的图像。 fft函数似乎希望您包含宽度和高度的log2,但是不清楚如何解压缩结果数据,或者数据是不是只是乱七八糟。 我认为显而易见的事情是将npot图像集中在一个更大的全黑图像中,然后在查看数据时忽略这些位置的任何值。 但想知道是否有一个尴尬的方式来处理npot数据。
//…END编辑
我在加速框架文档中遇到了一些麻烦。 我通常使用FFTW3,但我有麻烦得到编译在一个实际的IOS设备(见这个问题 )。 任何人都可以指向我一个超级简单的实现使用加速,如下所示:
1)将图像数据转换为适当的数据结构,然后传递给Accelerate的FFT方法。
在FFTW3中,最简单的方法是使用灰度图像,这涉及将无符号字节放入一个“fftw_complex”数组中,该数组只是两个浮点数的结构,一个保存实数值,另一个浮点数(虚数对每个像素初始化为零)。
2)采取这种数据结构并对其执行FFT。
3)打印幅度和相位。
4)对其执行IFFT。
5)从IFFT产生的数据重build原始图像。
虽然这是一个非常基本的例子,但我在使用苹果网站的文档时遇到了麻烦。 这里的答复是非常有用的,但是我仍然对如何使用加速来使用灰度(或彩色)2D图像来完成这个基本function感到困惑。
总之,任何处理2D图像的指针或特别是一些简单的工作代码都会非常有帮助!
\\\编辑\\\
好吧,花了一些时间深入到文档和一些非常有用的代码,以及在pkmital的github回购 ,我有一些工作代码,我想我会发布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方法的工作版本!)
我会说,为了执行任意图像大小的工作,所有你需要做的就是适当地将input值数组的大小设置为2的下一个幂。
困难的部分是在哪里把你的原始图像数据和填补什么。 你真正想要从图像中挖掘图像或数据是至关重要的。
在下面的链接PDF中,要特别注意12.4.2以上的段落http://www.mathcs.org/java/programs/FFT/FFTInfo/c12-4.pdf
虽然上面谈到了沿着2轴的操纵,但我们可以在第二维之前执行一个类似的想法,并且继续到第二维。 如果我是正确的,那么这个例子可以应用(而这绝不是一个确切的algorithm):
比方说我们有一个900×900的图像:首先我们可以将图像分割成512,256,128和4的垂直条纹。然后我们将为每一行处理4个1D FFT,其中一个为前512个像素,下一个对于接下来的256个像素,下一个接下来的128个,然后是剩下的最后一个4.由于FFT的输出本质上是频率的普及,所以这些可以简单地加上(从频率ONLYangular度而不是angular度偏移)。 然后我们可以把这个相同的技术推向第二维。 在这一点上,我们会考虑到每一个input像素,而不必实际填充。
这实在是一种思考,我自己也没有尝试过,而且确实应该自己研究一下。 如果你现在正在做这样的工作,那么在这一点上你可能比我有更多的时间。