2012-01-10 19 views
7

Sono uno studente e sono stato incaricato di ottimizzare l'interpolazione bilineare delle immagini invocando il parallelismo da CUDA.Interpolazione bilineare per ingrandire le immagini bitmap

L'immagine viene fornita in formato .bmp a 24 bit. Ho già un lettore per il file .bmp e ho memorizzato i pixel in un array.

Ora ho bisogno di eseguire l'interpolazione bilineare sulla matrice. Non capisco la matematica che c'è dietro (anche dopo aver esaminato lo wiki article e altri risultati di Google). Per questo motivo non riesco a trovare un algoritmo.

C'è qualcuno che può aiutarmi con un collegamento a un algoritmo di interpolazione bilineare esistente su un array 1-D? O forse il collegamento a una libreria di elaborazione di immagini open source che utilizza l'interpolazione bilineare e bicubica per ridimensionare le immagini?

+2

Sei stato incaricato di scrivere il tuo, però? –

+4

L'interpolazione bilineare non è definita per definizione per gli array 2D? – Phonon

+0

Il mio obiettivo principale è di ottimizzarlo tramite CUDA. Quindi, come il ridimensionamento dell'immagine viene fatto tramite bilineare è solo un passaggio intermedio. Dovresti modificare il mio post. Il professore vuole i risultati di ottimizzazione, quindi il resto spetta a me. Con l'algoritmo, posso quindi passare a invocare CUDA per eseguirlo con il parallelismo accelerandolo.:) – f0rfun

risposta

37

Il modo più semplice per comprendere l'interpolazione bilineare è comprendere l'interpolazione lineare in 1D.

Questa prima figura dovrebbe darti dei flashback alla matematica della scuola media. Dato un po 'di posizione a a cui vogliamo sapere f (a), prendiamo i valori "noti" vicini e inseriamo una linea tra di essi.

Linear interpolation in 1D.

Così abbiamo usato solo le vecchie equazioni della scuola media y = mx + B e Y-Y1 = m (x-x1). Nulla di bello.

Fondamentalmente questo concetto viene portato in 2D per ottenere l'interpolazione bilineare. Possiamo attaccare il problema di trovare f (a, b) per qualsiasi a, b facendo tre interpolazioni. Studia attentamente la prossima figura. Non farti intimidire da tutte le etichette. In realtà è piuttosto semplice.

Bilinear interpolation as three 1D interpolations.

Per un'interpolazione bilineare, abbiamo ancora una volta utilizzando i punti vicini. Ora ce ne sono quattro, visto che siamo in 2D. Il trucco è attaccare il problema una dimensione alla volta.

Proiettiamo i nostri (a, b) ai lati e prima calcoliamo due righe (una dimensione!) Interpolanti.

  • f (a, y j) dove y j viene mantenuta costante
  • f (a, y j + 1) dove y j + 1 è tenuto costante.

Ora c'è solo un ultimo passaggio. Si prende i due punti si è calcolato, f (a, y j) e f (a, y j + 1), e montare una linea tra di loro. Quello è quello blu che va da sinistra a destra nel diagramma, passando attraverso f (a, b). Interpolando lungo quest'ultima linea ti dà la risposta finale.

Lascerò la matematica per il caso 2-D per te. Non è difficile se lavori dal diagramma. E affrontarlo tu stesso ti aiuterà davvero a capire cosa sta succedendo.

Un'ultima piccola nota, non importa quali lati si scelgono per le prime due interpolazioni. Avresti potuto scegliere la parte superiore e quella inferiore, e poi hai fatto la terza linea di interpolazione tra quelle due. La risposta sarebbe stata la stessa.

+0

Ottime foto e ben spiegato – pezcode

+0

Grazie! Questo, e la risposta di @ Alex insieme sono stati davvero istruttivi su come funziona l'interpolazione bilineare. – blahman

9

Quando si ingrandisce un'immagine ridimensionando i lati di un fattore integrale, è possibile considerare il risultato come l'immagine originale con pixel aggiuntivi inseriti tra i pixel originali.

Vedere le immagini in IMAGE RESIZE EXAMPLE.

Il f(x,y)=... formula nella this article in Wikipedia ti dà un metodo per calcolare il colore f di un pixel inserita:

enter image description here

Per ogni pixel inserita si combinano i colori dei 4 pixel originali (Q11, Q12, Q21, Q22) che lo circonda. La combinazione dipende dalla distanza tra il pixel e inserito circostanti pixel originali, più è vicino a uno di essi, più loro colori sono:

enter image description here

I pixel originali sono mostrati in rosso. Il pixel inserito è mostrato in verde.

Questa è l'idea.

Se si scalano i lati di un fattore non integrale, le formule sono ancora valide, ma ora è necessario ricalcolare tutti i colori dei pixel in quanto non si possono semplicemente prendere i pixel originali e semplicemente inserire altri pixel tra loro.

3

Non rimanere impigliati dal fatto che gli array 2D in C sono in realtà array 1D. È un dettaglio di implementazione. Matematicamente, dovrai ancora pensare in termini di array 2D.

Pensate all'interpolazione lineare su un array 1D. Si conosce il valore 0, 1, 2, 3, ... Supponiamo ora di chiedere il valore allo 1.4. Mi daresti un mix ponderato dei valori a 1 e 2: (1 - 0.4)*A[1] + 0.4*A[2]. Semplice, vero?

Ora è necessario estendere a 2D. Nessun problema. L'interpolazione 2D può essere scomposta in due interpolazioni 1D, nell'asse xe quindi nell'asse y. Supponiamo che tu voglia (1.4, 2.8). Ottieni gli interpolanti 1D tra (1, 2)<->(2,2) e (1,3)<->(2,3). Questo è il tuo passo sull'asse x. Ora 1D interpola tra di loro con i pesi appropriati per y = 2.8.

Questo dovrebbe essere semplice da fare in modo massivo parallelo. Basta calcolare separatamente ciascun pixel interpolato. Con la memoria condivisa accedi all'immagine originale, farai solo letture, quindi nessun problema di sincronizzazione.