2012-05-22 14 views
13

// 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!)

+0

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.? –

+0

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. –

Odpowiedz

3

Powiedziałbym, że aby wykonać pracę na dowolnych rozmiarach obrazu, wystarczy tylko odpowiednio dopasować tablicę wartości wejściowych do następnej potęgi 2.

Najtrudniej jest umieścić oryginalne dane obrazu i wypełnić je. To, co naprawdę próbujesz zrobić z kopią obrazu lub danych z obrazu, ma kluczowe znaczenie.

w połączonej PDF poniżej, należy zwrócić szczególną uwagę na pkt tuż nad 12.4.2 http://www.mathcs.org/java/programs/FFT/FFTInfo/c12-4.pdf

Chociaż powyższy mówi o manipulacji wzdłuż 2 osi, możemy potentialy wykonać podobny pomysł przed drugim wymiarze i podążanie za drugim wymiarem. Jeśli jestem poprawny, to ten przykład może mieć zastosowanie (a to wcale nie jest dokładny algorytm):

mówią, że mamy obraz 900 na 900: najpierw możemy podzielić obraz na pionowe paski 512, 256, 128 i 4. Następnie przetwarzamy 4 FD 1D dla każdego wiersza, jeden dla pierwszych 512 pikseli, następny dla kolejnych 256 pikseli, następny dla następnych 128, a następnie dla pozostałych 4. wyjście FFT jest w zasadzie popularnością częstotliwości, wtedy można je po prostu dodać (z perspektywy częstotliwości TYLKO, a nie z przesunięcia kątowego). Możemy wtedy użyć tej samej techniki w kierunku 2. wymiaru. W tym momencie wzięlibyśmy pod uwagę każdy piksel wejściowy bez faktycznego padania.

To jest po prostu pożywienie dla myśli, sam tego nie próbowałem, a nawet sam powinienem to zbadać. Jeśli naprawdę wykonujesz tego rodzaju pracę właśnie teraz, możesz mieć więcej czasu niż ja w tym momencie.

+0

hmm, ciekawy pomysł ... –

+0

To nie jest jak przetwarzanie 20-sekundowego sygnału audio na 5-sekundowe porcje. To bardziej przypomina przetwarzanie sygnału audio przez podział na 0-10 kHz i 10 kHz - 20 kHz. Z każdego dostajesz różne zespoły, więc dodajesz 2 khz z 12 kHz lub coś podobnego do tego ... –

Powiązane problemy