2012-05-22 8 views
13

// MODIFICA ...Utilizzo di IOS Accelerate Framework per l'elaborazione di segnali 2D su immagini non-Power-Of-Two?

Sto modificando leggermente la mia domanda per risolvere il problema di lavorare in modo specifico con immagini non di potenza di due. Ho una struttura di base che funziona con immagini quadrate in scala di grigi con dimensioni come 256x256 o 1024x1024, ma non riesco a vedere come generalizzare le immagini con dimensioni arbitrarie. Le funzioni di fft sembrano voler includere il log2 della larghezza e dell'altezza, ma non è chiaro come decomprimere i dati risultanti, o se i dati non vengono semplicemente confusi. Suppongo che la cosa ovvia da fare sarebbe centrare l'immagine npot all'interno di un'immagine più grande, tutta nera e quindi ignorare qualsiasi valore in quelle posizioni quando si guardano i dati. Ma chiedendosi se c'è un modo meno imbarazzante per lavorare con i dati npot.

//...END EDIT

Sto avendo un po 'di problemi con la documentazione Framework Accelerate. Normalmente userò FFTW3, ma ho difficoltà a farlo per compilare un dispositivo IOS reale (vedi questo question). Qualcuno può indicarmi un'implementazione super semplice usando Accelerate che fa qualcosa di simile al seguente:

1) Trasforma i dati di immagine in una struttura dati appropriata che può essere passata ai metodi FFT di Accelerate.
In FFTW3, nel modo più semplice, utilizzando un'immagine in scala di grigi, ciò comporta il posizionamento dei byte senza segno in un array "fftw_complex", che è semplicemente una struttura di due float, uno che contiene il valore reale e l'altro l'immaginario (e dove l'immaginario è inizializzato a zero per ogni pixel).

2) Prende questa struttura dati ed esegue una FFT su di esso.

3) Stampa la grandezza e la fase.

4) Esegue un IFFT su di esso.

5) Ricrea l'immagine originale dai dati risultanti dall'IFFT.

Sebbene si tratti di un esempio molto semplice, sto riscontrando problemi nell'utilizzo della documentazione dal sito Apple. Il SO answer by Pi here è molto utile, ma sono ancora un po 'confuso su come utilizzare Accelerate per eseguire questa funzionalità di base utilizzando un'immagine 2D in scala di grigi (o colore).

In ogni caso, qualsiasi puntatore o soprattutto un semplice codice di lavoro che elabora un'immagine 2D sarebbe estremamente utile!

\\\ EDIT \\\

Ok, dopo aver preso un po 'di tempo per immergersi nella documentazione e del codice molto utile su SO e sulle pkmital's github repo, ho un po' di codice di lavoro che ho pensato io 'd post dal 1) mi ci è voluto un po' per capire e 2) poiché ho un paio di domande rimanenti ...

Inizializzare FFT "piano".Supponendo immagine un quadrato potenze di due:

#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); 

Passo in un array di byte per un'immagine quadrata potenze di due scala di grigi e trasformarlo in un 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; 
    } 
} 

Eseguire la FFT i dati di immagine trasformata, poi prendete l'ampiezza e la fase:

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]); 
} 

Ora è possibile eseguire un IFFT sui dati out_fft per ottenere l'immagine originale ...

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); 

Oppure è possibile eseguire un IFFT sulla magnitudo per ottenere un autocorrelazione ...

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); 

Infine, è possibile inserire i risultati IFFT di nuovo in un array immagine:

for (UInt32 i = 0; i < numElements; i++) { 
    t->data[i] = (int) (out_ifft.realp[i] * 255.0); 
}  

I non ho capito come usare il framework Accelerate per gestire immagini non power-of-two. Se alloco memoria sufficiente nel setup, allora posso fare un FFT, seguito da un IFFT per ottenere la mia immagine originale. Ma se provi a fare un autocorrelazione (con la grandezza della FFT), allora la mia immagine ottiene risultati stupefacenti. Non sono sicuro del modo migliore per applicare l'immagine in modo appropriato, quindi spero che qualcuno abbia un'idea di come farlo. (Oppure condividi una versione funzionante del metodo vDSP_conv!)

+0

Sembra che tu stia facendo autocorrelazione qui? Pensavo che Accelerate/vDSP avesse già delle funzioni di autocorrelazione in modo tale da non dover eseguire il rollover con FFT/IFFT ecc. –

+0

Salve, il file vDSP_acor non sembra esistere realmente nella libreria Accelerate.vDSP_conv esiste, ma mi sta dando strani risultati ... forse lo sto usando in modo errato per fare una autocorrelazione dell'immagine. Se tu (o qualcuno) hai un esempio funzionante per l'utilizzo di vDSP_conv per l'autocorrelazione, sarebbe bello vederlo. Parte del problema è che confonde i dati in attesa e in uscita, ecc. –

risposta

3

Direi che per eseguire lavori su dimensioni di immagine arbitrarie, tutto ciò che devi fare è dimensionare in modo appropriato la matrice del valore di input alla potenza successiva di 2.

La parte difficile è dove inserire i dati dell'immagine originale e cosa riempire. Quello che stai davvero cercando di fare per l'immagine o i dati dall'immagine è cruciale.

Nel PDF link sottostante, prestare particolare attenzione al punto appena al di sopra 12.4.2 http://www.mathcs.org/java/programs/FFT/FFTInfo/c12-4.pdf

Mentre il sopra parla di manipolazione lungo 2 assi, potremmo potentialy eseguire una simile idea prima della seconda dimensione e seguendo la seconda dimensione. Se Im è corretto, questo esempio potrebbe applicarsi (e questo non è ancora un algoritmo esatto):

dire che abbiamo un'immagine che è 900 per 900: prima potremmo dividere l'immagine in strisce verticali di 512, 256, 128 e 4. Elaboreremo quindi 4 FFT 1D per ogni riga, una per i primi 512 pixel, la successiva per i seguenti 256 pixel, la successiva per i seguenti 128, quindi l'ultima per i rimanenti 4. Da l'output della FFT è essenzialmente la popolarità della frequenza, quindi potrebbero semplicemente essere aggiunti (dalla prospettiva SOLO alla frequenza, non all'offset angolare). Potremmo quindi spingere questa stessa tecnica verso la seconda dimensione. A questo punto avremmo preso in considerazione ogni pixel di input senza dover effettivamente eseguire il rilievo.

Questo è davvero solo uno spunto di riflessione, non l'ho provato io stesso, e in effetti dovrei farlo da solo. Se stai veramente facendo questo tipo di lavoro in questo momento, potresti avere più tempo di me a questo punto.

+0

hmm, idea interessante ... –

+0

Non è come elaborare un segnale audio di 20 secondi in blocchi di 5 secondi. È più come l'elaborazione di un segnale audio dividendo a parte 0-10khz e 10khz-20khz. Otterrai diverse band da ciascuna, quindi aggiungerai 2khz con 12khz o qualcosa del genere ... –

Problemi correlati