//РЕДАКТИРОВАТЬ...
Я немного изменяю свой вопрос, чтобы решить проблему работы с изображениями, отличными от двух. У меня есть базовая структура, которая работает с квадратными изображениями в оттенках серого с размерами, такими как 256x256 или 1024x1024, но не может понять, как обобщать изображения произвольного размера. Fft-функции, похоже, хотят, чтобы вы включили log2 ширины и высоты, но затем неясно, как распаковывать результирующие данные или если данные не просто скремблируются. Я полагаю, что очевидным было бы сосредоточить изображение npot в более крупном, черном изображении, а затем игнорировать любые значения в этих позициях при просмотре данных. Но интересно, есть ли менее неудобный способ работы с данными npot.
//... END EDIT
У меня возникли проблемы с документацией Accelerate Framework. Я бы обычно использовал FFTW3, но у меня возникли проблемы с этим, чтобы скомпилировать на реальном устройстве IOS (см. Этот question). Может ли кто-нибудь указать мне на суперпростую реализацию, используя Accelerate, что-то вроде следующего:
1) Поворачивает данные изображения в соответствующую структуру данных, которые можно передать методам ускорения FFT.
В FFTW3, в самом простом, используя изображение в градациях серого, это включает в себя размещение беззнаковых байтов в массиве "fftw_complex", который представляет собой просто структуру из двух поплавков, один из которых содержит реальное значение, а другой - мнимый (и где мнимый инициализируется до нуля для каждого пикселя).
2) Принимает эту структуру данных и выполняет БПФ на ней.
3) Распечатывает величину и фазу.
4) Выполняет на нем IFFT.
5) Восстанавливает исходное изображение из данных, полученных в результате IFFT.
Хотя это очень простой пример, у меня возникли проблемы с использованием документации с сайта Apple. Ответ SO от Pi здесь очень полезен, но я все еще несколько смущен тем, как использовать Accelerate для выполнения этой базовой функции с использованием полутонового (или цветного) 2D-изображения.
Во всяком случае, любые указатели или особенно простой рабочий код, обрабатывающий 2D-изображение, будут чрезвычайно полезны!
\\\ EDIT \\\
Хорошо, потратив некоторое время на погружение в документацию и очень полезный код на SO, а также на pkmital 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;
}
}
Запустите БПФ на данные преобразованного изображения, затем захватите величину и фазу:
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]);
}
Теперь вы можете запустить IFFT по данным out_fft, чтобы получить исходное изображение...
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, чтобы получить исходное изображение. Но если попытаться сделать автокорреляцию (с величиной БПФ), то мое изображение получится неустойчивым. Я не уверен в лучшем способе правильно подставить изображение, так что, надеюсь, у кого-то есть идея, как это сделать. (Или поделитесь рабочей версией метода vDSP_conv!)