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

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

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


person Angus Forbes    schedule 22.05.2012    source источник
comment
Похоже, вы просто делаете здесь автокорреляцию? Я думал, что в Accelerate/vDSP уже есть функции автокорреляции, поэтому вам не нужно было создавать свои собственные с помощью FFT/IFFT и т. д.?   -  person Paul R    schedule 23.05.2012
comment
Привет, vDSP_acor, похоже, на самом деле не существует в библиотеке Accelerate. vDSP_conv существует, но дает странные результаты... возможно, я неправильно использую его для автокорреляции изображений. Если у вас (или у кого-либо) есть рабочий пример использования vDSP_conv для автокорреляции, было бы здорово его увидеть. Часть проблемы заключается только в том, что это сбивает с толку, какие данные ожидают и выводят и т. д.   -  person Angus Forbes    schedule 23.05.2012


Ответы (1)


Я бы сказал, что для выполнения работы с произвольными размерами изображения все, что вам нужно сделать, это размер массива входных значений в соответствии со следующей степенью числа 2.

Сложность заключается в том, куда поместить исходные данные изображения и что заполнить. То, что вы на самом деле пытаетесь сделать с изображением или получить данные из изображения, имеет решающее значение.

В приведенном ниже PDF-файле обратите особое внимание на абзац чуть выше 12.4.2 http://www.mathcs.org/java/programs/FFT/FFTInfo/c12-4.pdf

Хотя вышеизложенное говорит о манипулировании по двум осям, потенциально мы могли бы реализовать аналогичную идею до второго измерения и после него. Если я прав, то этот пример может быть применим (и это еще ни в коем случае не точный алгоритм):

скажем, у нас есть изображение 900 на 900: сначала мы можем разделить изображение на вертикальные полосы 512, 256, 128 и 4. Затем мы обработаем 4 одномерных БПФ для каждой строки, одно для первых 512 пикселей, следующее для следующих 256 пикселей, следующий для следующих 128, затем последний для оставшихся 4. Поскольку выход БПФ, по сути, представляет собой популярность частоты, то их можно просто добавить (ТОЛЬКО с точки зрения частоты, а не углового смещения ). Затем мы могли бы применить ту же технику во втором измерении. На этом этапе мы бы приняли во внимание каждый входной пиксель без фактического заполнения.

Это действительно просто пища для размышлений, я сам не пробовал, и действительно должен исследовать это сам. Если вы действительно делаете такую ​​работу прямо сейчас, у вас может быть больше времени, чем у меня на данный момент.

person trumpetlicks    schedule 30.05.2012
comment
Это не похоже на обработку 20-секундного аудиосигнала на 5-секундные фрагменты. Это больше похоже на обработку аудиосигнала путем разделения 0–10 кГц и 10–20 кГц. Вы получаете разные полосы от каждого, поэтому вы должны добавить 2 кГц к 12 кГц или что-то в этом роде... - person Glenn Maynard; 23.01.2015
comment
Это больше вопрос, чем что-либо еще, потому что я все еще развиваю интуицию для всего этого, но разве разделимость БПФ не позволяет делать полоски изображения 512 за раз и т. д.? Я смотрел видео о том, как кто-то выполняет 2D FFT, выполняя вложенные циклы 1D FFT по одной строке пикселей за раз. - person God of Biscuits; 28.03.2020