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