// EDYTUJ ...Korzystanie z IOS Accelerate Framework do przetwarzania sygnału 2D na obrazach bez zasilania z dwóch?
Edytuję moje pytanie, aby rozwiązać problem pracy z obrazami o braku mocy dwóch. Mam podstawową strukturę, która działa z kwadratowymi obrazami w skali szarości o rozmiarach takich jak 256x256 lub 1024x1024, ale nie widzę, jak generalizować obrazy o dowolnych rozmiarach. Wydaje się, że funkcje fft wymagają włączenia log2 o szerokości i wysokości, ale wtedy nie jest jasne, jak rozpakować dane wynikowe lub czy dane nie są po prostu pomieszane. Przypuszczam, że oczywistą rzeczą byłoby wyśrodkowanie obrazu na obrazku w większym, czarnym obrazie, a następnie zignorowanie wszelkich wartości w tych pozycjach podczas przeglądania danych. Ale zastanawiam się, czy istnieje mniej niezręczny sposób pracy z danymi na temat npot.
//...END EDIT
Mam trochę problemów z Accelerate dokumentacji ramowej. Normalnie używałbym FFTW3, ale mam problem ze skompilowaniem go na rzeczywistym urządzeniu IOS (zobacz: question). Czy ktokolwiek może wskazać mi na super prostą implementację za pomocą Accelerate, która ma coś takiego:
1) Zamienia dane obrazu w odpowiednią strukturę danych, która może zostać przekazana do metod przyspieszania FFT.
W FFTW3, w najprostszym przypadku, przy użyciu obrazu w skali szarości, polega to na umieszczeniu niepodpisanych bajtów w tablicy "fftw_complex", która jest po prostu strukturą dwóch elementów pływających, z których jedna zawiera wartość rzeczywistą, a druga - urojoną (i imaginacja jest inicjalizowana do zera dla każdego piksela).
2) Przyjmuje tę strukturę danych i wykonuje na niej FFT.
3) Drukuje jasność i fazę.
4) Wykonuje na nim IFFT.
5) Odtwarza oryginalny obraz z danych wynikających z IFFT.
Chociaż jest to bardzo prosty przykład, mam problem z używaniem dokumentacji ze strony firmy Apple. Komunikat SO answer by Pi here jest bardzo pomocny, ale nadal nie jestem pewien, jak używać Accelerate do wykonywania podstawowych funkcji przy użyciu obrazu 2D w skali szarości (lub koloru).
W każdym razie wszelkie wskazówki, a zwłaszcza prosty kod, który przetwarza obraz 2D, byłyby niezwykle pomocne!
\\\ EDIT \\\
Dobra, po zrobieniu trochę czasu, aby zanurzyć się w dokumentacji i niektórych bardzo pomocny kodu na SO, a także na pkmital's github repo, mam jakiś kod roboczy że myślałem "d post od 1) zajęło mi trochę czasu, aby to zrozumieć i 2), ponieważ mam kilka pozostałych pytań ...
Inicjalizuj FFT" plan ".Zakładając kwadratowy potęga dwójki obraz:
#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);
Pass w tablicy bajtów do kwadratu power-of-two skali szarości i przekształcić go w 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;
}
}
Uruchom FFT na przekształcona dane obrazu, a następnie chwycić wielkości i fazy:
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]);
}
teraz można uruchomić IFFT na danych out_fft dostać oryginalny obraz ...
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);
Albo można uruchomić IFFT od wielkości, aby uzyskać autokorelacji ...
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);
Wreszcie, można umieścić ifft wyników z powrotem do tablicy obrazu:
for (UInt32 i = 0; i < numElements; i++) {
t->data[i] = (int) (out_ifft.realp[i] * 255.0);
}
I nie znalazłem sposobu, w jaki użyć struktury Accelerate do obsługi obrazów bez mocy dwóch. Jeśli przydzielę wystarczającą ilość pamięci w konfiguracji, mogę wykonać FFT, a następnie IFFT, aby uzyskać oryginalny obraz. Ale jeśli spróbujesz zrobić autokorelację (z wielkością FFT), to mój obraz będzie wygórowany. Nie jestem pewien, w jaki sposób najlepiej dopracować obraz, więc mam nadzieję, że ktoś ma pomysł, jak to zrobić. (Lub podziel się działającą wersją metody vDSP_conv!)
Wygląda na to, że robisz tutaj autokorelację? Myślałem, że Accelerate/vDSP ma już funkcje autokorelacji, więc nie musieli Państwo wykonywać własnych ruchów za pomocą FFT/IFFT itp.? –
Witam, parametr vDSP_acor prawdopodobnie nie istnieje w bibliotece Accelerate.vDSP_conv istnieje, ale daje mi dziwne wyniki ... być może używam go niepoprawnie do robienia autokorelacji obrazu. Jeśli (lub ktokolwiek) ma działający przykład użycia vDSP_conv do autokorelacji, byłoby wspaniale go zobaczyć. Częścią problemu jest to, że jest mylące, co do danych w oczekiwaniach i wyjściach, itp. –