//РЕДАКТИРОВАТЬ...
Я немного редактирую свой вопрос, чтобы решить проблему работы конкретно с нестепенными -два изображения. У меня есть базовая структура, которая работает с квадратными изображениями в градациях серого размером 256x256 или 1024x1024, но я не вижу, как обобщать изображения произвольного размера. Кажется, что функции fft хотят, чтобы вы включили log2 ширины и высоты, но тогда неясно, как распаковать полученные данные, или данные не просто зашифрованы. Я полагаю, что очевидной вещью было бы центрирование изображения npot внутри большего, полностью черного изображения, а затем игнорирование любых значений в этих позициях при просмотре данных. Но интересно, есть ли менее неуклюжий способ работы с данными npot.
//...КОНЕЦ РЕДАКТИРОВАНИЯ
У меня небольшие проблемы с документацией Accelerate Framework. Обычно я бы использовал FFTW3, но у меня возникли проблемы с его компиляцией на реальном устройстве IOS (см. этот вопрос). Может ли кто-нибудь указать мне супер простую реализацию с использованием Accelerate, которая делает что-то вроде следующего:
1) Превращает данные изображения в соответствующую структуру данных, которую можно передать методам БПФ Accelerate.
В FFTW3, в самом простом случае, с использованием изображения в градациях серого, это включает в себя помещение байтов без знака в массив «fftw_complex», который представляет собой просто структуру из двух чисел с плавающей запятой, один из которых содержит реальное значение, а другой — мнимое (и где мнимое инициализируется нулем для каждого пикселя).
2) Берет эту структуру данных и выполняет над ней БПФ.
3) Распечатывает амплитуду и фазу.
4) Выполняет на нем ОБПФ.
5) Восстанавливает исходное изображение из данных, полученных в результате IFFT.
Хотя это очень простой пример, у меня возникли проблемы с использованием документации с сайта Apple. Ответ SO от Pi здесь очень полезен, но я все еще немного смущен тем, как использовать Accelerate для выполнения этой базовой функции с использованием полутонового (или цветного) 2D-изображения.
В любом случае, любые указатели или особенно простой рабочий код, обрабатывающий 2D-изображение, были бы чрезвычайно полезны!
\\\ EDIT \\\
Хорошо, потратив некоторое время на изучение документации и очень полезного кода на SO, а также на репозиторий pkmital на github, у меня есть кое-что рабочий код, который я собирался опубликовать, поскольку 1) мне потребовалось некоторое время, чтобы понять его, и 2) так как у меня осталась пара оставшихся вопросов...
Инициализировать "план" БПФ. Предполагая квадратное изображение степени двойки:
#include
...
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 );
Или вы можете запустить ОБПФ для величины, чтобы получить автокорреляцию...
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 );
Наконец, вы можете поместить результаты ОБПФ обратно в массив изображений:
for ( UInt32 i = 0; i < numElements; i++ ) {
t->data[i] = (int) (out_ifft.realp[i] * 255.0);
}
Я не понял, как использовать Ускорение framework для обработки изображений, не являющихся степенью двойки. Если я выделю достаточно памяти в настройке, я могу выполнить БПФ, а затем ОБПФ, чтобы получить исходное изображение. Но если попытаться сделать автокорреляцию (с величиной БПФ), то мое изображение получит шаткие результаты. Я не уверен, как правильно разместить изображение, поэтому, надеюсь, у кого-то есть идея, как это сделать. (Или поделитесь рабочей версией метода vDSP_conv!)