Come si applica correttamente FFT nel denoising delle immagini


8

Sto scrivendo un programma (widget Qt / c ++) per rimuovere il rumore dalle immagini. Come metodo di denoising, ho selezionato un metodo non locale . Questo metodo ha un'incredibile qualità delle immagini ripristinate (ecco perché è l'unico metodo di denoising in OpenCV), ma ha un costo di calcolo enorme , quindi ho fatto molte varianti modificate di questo metodo (alcune con multithreading, altre algoritmiche). Ma ho un problema con quello che coinvolge FFT

Ho seguito tutti i passaggi di questo articolo (solo una pagina, 1430) e tutto funziona perfettamente, tranne per la parte FFT, ci sono solo 2 righe su di esso nel documento e non riesco a capire, COME si dovrebbe usare fft

Questo problema mi ha infastidito per mesi, qualsiasi aiuto o intuizione sarebbe molto apprezzato.

Versione abbreviata della domanda: come posso ottenere rapidamente la differenza quadrata sommata di due array sull'immagine (uno in alto e uno al centro, i valori sono colori) rapidamente? (O (n ^ 2) ha un costo enorme, ci sono molte operazioni di questo tipo, afferma la carta sopra, che può essere fatto tramite FFT con O (n * log n) (dice che queste 2 matrici formano in qualche modo una convoluzione circolare) )

inserisci qui la descrizione dell'immagine


Che cosa hai fatto alla fine per il calcolo della FFT? Anche se FFT è precompilato, la moltiplicazione puntuale e l'aggiunta di tutti gli elementi della patch impiegano il tempo doveè la dimensione della patch. Come hai superato questo? O(|P|)|P|
curryage

Risposte:


5

Il trucco all'interno del foglio è il seguente:

  1. Che cosa si vuole calcolare IS , dove è un'immagine, e due pixel rumorosi e è compensato un 2D usato per definire una patch.iW|I(x+i)I(y+i)|2Ixyi
  2. L'espansione dell'espressione produce: .iI2(x+i)+iI2(y+i)2iI(x+i)I(y+i)=A+B2C
  3. A e sono calcolati usando un'immagine integrale quadrata, cioè un'immagine integrale dall'immagine originale quadrata.B
  4. C è la convoluzione tra i due patch centrate su e . Pertanto, può essere calcolato nel dominio di Fourier, dove diventa una moltiplicazione. Ottieni il valore di calcolando la trasformata di Fourier della patch attorno a , la patch intorno a , moltiplicando puntualmente questi risultati e prendendo la trasformata inversa di Fourier del risultato della moltiplicazione.xyCxy

La trasformata di Fourier è ovviamente una trasformazione 2D poiché si lavora con dati 2D. Quello che ottieni per una determinata patch è un array 2D di valori complessi.

Note aggiuntive

A mio avviso, questo articolo non è la migliore strategia di speed-up NL. Gli esperimenti che ho fatto nel 2007/2008 mostrano che la preselezione delle patch è migliore (sia in termini di velocità che di qualità dei risultati). Ho iniziato a bloggare su questi qui , ma sfortunatamente sto cercando il tempo per finire i post.

I documenti originali sulla BN menzionano implementazioni a blocchi che possono essere interessanti. Esistono fondamentalmente 2 modi per implementare i mezzi NL:

  1. scrivere un ciclo di denoising per ogni pixel nell'immagine
  2. scrivere un loop di denoising per ogni patch, quindi proiettare indietro le patch per formare un'immagine.

La prima impolementazione è l'approccio originale, perché nel 2005 la memoria e le CPU multicore erano costose. Ho scelto invece il numero 2 sull'hardware recente negli ultimi 2 anni. Dipende dalle dimensioni tipiche dell'immagine e se si desidera essere in grado di calcolare trasformazioni di dominio come DFT / DCT (come nel documento proposto e in BM3D).


Grazie mille per la tua risposta, è esattamente quello di cui avevo bisogno, tutto era pronto e funzionava molto tempo fa, tranne per il 4 ° elemento in quella lista, ma ora è molto più chiaro. Però un'altra domanda, se non ti dispiace: cosa restituirà la trasformata di Fourier della patch x o y? Matrice, vettore o valore singolo? E cosa è necessario per utilizzare la trasformazione inversa? Perché sto pensando di pre-calcolare fft per ogni pixel (patch centrate attorno ad esso) e scrivere i risultati in array 2d prima di eseguire il denoising e quindi usare solo quella matrice per ottenere fft inverso, ma non so se questo sarà sufficiente per fft inverso
Shf,

oh, e dovrei usare 2d fft o tradurre la patch in 1d array? a proposito, stavo pianificando di scrivere dopo questa implementazione patchwise, grazie per un consiglio :) qualcosa di simile a questo anche molto tempo fa- ipol.im/pub/art/2011/bcm_nlm
Shf

Ho aggiornato la risposta.
sansuiso,

ok, quindi posso pre-calcolare FFT per patch, centrato su ogni pixel prima di donare sebbene ci vorrà molta memoria (m n size_of_patch size_of_patch sizeof (double)), ma quando conterò i pesi, dovrei comunque moltiplicare in modo puntuale 2 array complessi e successivamente inverse fft sull'array 2d ricevuto, è anche più di O (n ^ 2) se non sbaglio
Shf

2
Buona risposta, ma come la stai ricavando Cè una convoluzione? Il modo in cui è scritto è un prodotto saggio elemento per elemento. Dov'è la convoluzione?
TheGrapeBeyond
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.