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