gpt4 book ai didi

ios - 使用 IOS Accelerate Framework 对非二次幂图像进行二维信号处理?

转载 作者:技术小花猫 更新时间:2023-10-29 10:27:49 24 4
gpt4 key购买 nike

//编辑...

我正在稍微编辑我的问题,以解决专门处理非二次幂图像的问题。我有一个基本结构,适用于大小为 256x256 或 1024x1024 的方形灰度图像,但看不到如何推广到任意大小的图像。 fft 函数似乎希望您包括宽度和高度的 log2,但不清楚如何解压缩结果数据,或者数据是否只是被扰乱。我想最明显的做法是将 npot 图像置于更大的全黑图像的中心,然后在查看数据时忽略这些位置的任何值。但想知道是否有更简单的方法来处理 npot 数据。

//...结束编辑

我在使用 Accelerate Framework 文档时遇到了一些问题。我通常会使用 FFTW3,但我无法在实际的 IOS 设备上进行编译(参见 question)。谁能给我指出一个使用 Accelerate 的 super 简单的实现,它执行如下操作:

1) 将图像数据转换为可传递给 Accelerate 的 FFT 方法的适当数据结构。
在 FFTW3 中,在最简单的情况下,使用灰度图像,这涉及将无符号字节放入“fftw_complex”数组中,该数组只是两个 float 的结构,一个保存实值,另一个保存虚数(虚数在哪里)每个像素初始化为零)。

2) 获取此数据结构并对其执行 FFT。

3) 打印出幅度和相位。

4) 对其执行 IFFT。

5) 根据 IFFT 产生的数据重新创建原始图像。

尽管这是一个非常基本的示例,但我在使用 Apple 网站上的文档时遇到了问题。所以 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 方法的工作版本!)

最佳答案

我想说的是,为了对任意大小的图像执行操作,您所要做的就是将输入值数组的大小适本地调整为 2 的下一次幂。

困难的部分是将原始图像数据放在哪里以及填充什么。您真正想对图像做什么或从图像中挖掘数据是至关重要的。

在下面链接的 PDF 中,请特别注意 12.4.2 上面的段落 http://www.mathcs.org/java/programs/FFT/FFTInfo/c12-4.pdf

虽然上面谈到了沿 2 个轴的操作,但我们可以在第二维度之前执行类似的想法,然后进入第二维度。如果我是正确的,那么这个例子可以应用(这绝不是一个精确的算法):

假设我们有一张 900 x 900 的图像:首先,我们可以将图像拆分为 512、256、128 和 4 的垂直 strip 。然后我们将为每一行处理 4 个 1D FFT,一个用于前 512 个像素,下一个用于接下来的 256 个像素,下一个用于接下来的 128 个,然后最后一个用于剩余的 4 个。由于 FFT 的输出本质上是流行的的频率,然后可以简单地添加这些(仅从频率的角度来看,而不是角度偏移)。然后我们可以将同样的技术推向二维。在这一点上,我们会考虑到每个输入像素,而无需实际填充。

这真的只是深思熟虑,我自己没有尝试过,确实应该自己研究一下。如果你现在真的在做这种工作,那么此时你可能有比我更多的时间。

关于ios - 使用 IOS Accelerate Framework 对非二次幂图像进行二维信号处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10708667/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com