使用iOS加速框架在非功率 - 两个图像上进行2D信号处理?
-
13-12-2019 - |
题
//编辑...
我稍微编辑我的问题,以解决专门使用两种图像的工作问题。我有一个基本结构,它适用于平方灰度图像,尺寸为256x256或1024x1024,但看不到如何概括为任意大小的图像。 FFT函数似乎希望您包含宽度和高度的log2,但是它不清楚如何解压缩结果数据,或者数据不只是扰乱。我想要做明显的事情是将NPOT图像中置于较大的黑色图像中,然后在查看数据时忽略这些位置中的任何值。但想知道是否有一个不太尴尬的方式与NPOT数据一起使用。
// ...结束编辑
我对加速框架文档有点麻烦。我通常会使用fftw3,但我无法在实际的iOS设备上编译它(请参阅它问题)。任何人都可以使用加速器指向超级简单的实现,这与以下内容相同:
1)将图像数据转换为可以传递以加速FFT方法的适当数据结构。
在FFTW3中,在最简单的情况下,使用灰度图像,这涉及将无符号字节放入“FFTW_COMPLEX”阵列中,这只是两个浮点数的结构,一个保持真实值,另一个浮动,另一个浮动(以及虚构的位置每个像素初始化为零)。
2)采用此数据结构并对其执行FFT。
3)打印出幅度和相位。
4)对其执行IFFT。
5)从IFFT的数据中重新创建原始图像。
虽然这是一个非常基本的例子,但我无法使用Apple网站的文档遇到问题。所以在这里的pi答案非常有用,但我仍然是有些困惑如何使用加速来使用灰度(或颜色)2D图像来执行此基本功能。
无论如何,任何指针或尤其是处理2D图像的简单工作代码都会非常有帮助!
\\\编辑\\\
好的,在花一段时间后潜入文档和一些非常有用的代码以及 pkmital的github repo ,我有一些工作代码,我以为我发布的1)我花了一段时间来弄明白,因为我有几个剩下的问题...初始化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);
.
以字节数组传递到一个平方电源 - 两个灰度映像,并将其转换为复杂的_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);
}
.
我还没有想出如何使用加速框架来处理非功率的图像。如果我在设置中分配足够的内存,那么我可以执行FFT,然后是IFFT获取我的原始图像。但是,如果尝试进行自相关(具有FFT的幅度),那么我的图像会得到旺盛的结果。我不确定适当地填充图像的最佳方式,所以希望有人知道如何做到这一点。 (或共享VDSP_CONV方法的工作版本!)
解决方案
我会说为了在任意图像大小上执行工作,您必须做的就是适当地将输入值阵列尺寸尺寸为2。
硬部分是将原始图像数据和填写的内容放置的位置。您真正尝试从图像到图像或数据我的数据至关重要。
在下面的联系PDF中,特别注意段落高于12.4.2 http://www.mathcs.org/java/programs/fft /fftinfo/c12-4.pdf
虽然上面谈到沿着2个轴的操纵,我们可以在第二维尔之前和追随第二维度之前的类似思路。如果我是正确的,那么这个例子可以应用(这绝不是一个精确的算法):
假设我们有一个900到900的图像: 首先,我们可以将图像分成512,256,128和4的垂直条带。 然后,我们将处理每行4 1d FFT,一个用于前512像素,下一个用于以下256像素,下次为128,然后剩下的最后128个。由于FFT的输出基本上是流行的频率,然后可以简单地添加这些(从频率仅透视,而不是角偏移)。 然后我们可以向第二个维度推动相同的技术。此时我们将考虑每个输入像素而无需实际填充。
这真的只是为了思想的食物,我还没有尝试过这个,确实应该自己研究这个。如果你现在真的在做这种工作,那么你可能有更多的时间就是这一点。