Использование IOS Accelerate Framework для обработки 2D-сигналов на изображениях, отличных от степени двойки?

//РЕДАКТИРОВАТЬ...

Я немного редактирую свой вопрос, чтобы решить проблему работы конкретно с нестепенными -два изображения. У меня есть базовая структура, которая работает с квадратными изображениями в градациях серого размером 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!)

13
задан Community 23 May 2017 в 10:29
поделиться