Interpolazione bilineare dell’immagine / scalatura – Un esempio di calcolo

Vorrei segnalarvi questo grafico molto perspicace da Wikipedia che illustra come fare l’interpolazione bilineare per un punto:

Fonte: Wikipedia

Come potete vedere, i quattro punti rossi sono quelli noti. Questi punti si conoscono in anticipo e P è il punto che vogliamo interpolare. Come tale, dobbiamo fare due passi (come hai indicato nel tuo post). Per gestire la coordinata x (orizzontale), dobbiamo calcolare qual è il valore interpolato in base alla fila di punti rossi in alto e alla fila di punti rossi in basso. Questo risulta nei due punti blu R1 e R2. Per gestire la coordinata y (verticale), usiamo i due punti blu e interpoliamo verticalmente per ottenere il punto finale P.

Quando ridimensionate un’immagine, anche se non vediamo visivamente quello che sto per dire, ma immaginate che questa immagine sia un segnale 3D f. Ogni punto della matrice è infatti una coordinata 3D dove la posizione della colonna è il valore x, la posizione della riga è il valore y e il valore z è la quantità / valore della scala di grigi della matrice stessa. Quindi, fare z = f(x,y) è il valore della matrice alla posizione (x,y) nella matrice. Nel nostro caso, dato che si tratta di immagini, ogni valore di (x,y) sono numeri interi che vanno da 1 fino a tante righe/colonne quante ne abbiamo a seconda di quale dimensione stai guardando.

Pertanto, data la coordinata che vuoi interpolare a (x,y), e date le coordinate rosse nell’immagine sopra, che chiamiamo x1,y1,x2,y2 come da schema – in particolare andando con la convenzione dello schema e facendo riferimento a come si accede alle immagini: x1 = 1, x2 = 2, y1 = 2, y2 = 1, le coordinate blu R1 e R2 sono calcolate tramite interpolazione 1D in colonna utilizzando la stessa riga su cui entrambi i punti coincidono:

R1 = f(x1,y1) + (x - x1)/(x2 - x1)*(f(x2,y1) - f(x1,y1))R2 = f(x1,y2) + (x - x1)/(x2 - x1)*(f(x2,y2) - f(x1,y2))

È importante notare che (x - x1) / (x2 - x1) è un peso / proporzione di quanto l’output consiste in un mix tra i due valori visti a f(x1,y1) e f(x2,y1) per R1 o f(x1,y2) e f(x2,y2) per R2. In particolare, x1 è il punto di partenza e (x2 - x1) è la differenza dei valori x. Si può verificare che sostituendo x1 con x si ottiene 0 mentre x2 con x si ottiene 1. Questo peso oscilla tra che è necessario per far funzionare i calcoli.

Si noti che l’origine dell’immagine è in alto a sinistra, e quindi (1,1) è in alto a sinistra. Una volta trovati R1 e R2, possiamo trovare P interpolando per righe:

P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)

Anche (y - y2) / (y2 - y1) denota la proporzione/miscela di quanto R1 e R2 contribuiscono all’output finale P. Come tale, hai calcolato f5 correttamente perché hai usato quattro punti noti: In alto a sinistra è 100, in alto a destra è 50, in basso a sinistra è 70 e in basso a destra è 20. In particolare, se vuoi calcolare f5, questo significa che (x,y) = (1.5,1.5) perché siamo a metà strada tra 100 e 50 a causa del fatto che stai scalando l’immagine di due. Se inserite questi valori nel calcolo di cui sopra, otterrete il valore di 60 come vi aspettavate. I pesi per entrambi i calcoli risulteranno anche in 0.5, che è quello che hai ottenuto nei tuoi calcoli ed è quello che ci aspettiamo.

Se calcolate f1, questo corrisponde a (x,y) = (1.5,1) e se lo sostituite nell’equazione precedente, vedrete che (y - y2)/(y2 - y1) vi dà 0 o il peso è 0, e quindi ciò che viene calcolato è solo R2, corrispondente all’interpolazione lineare solo lungo la riga superiore. Allo stesso modo, se abbiamo calcolato f7, ciò significa che vogliamo interpolare a (x,y) = (1.5,2). In questo caso, vedrete che (y - y2) / (y2 - y1) è 1 o il peso è 1 e quindi P = R2 + (R1 - R2), che si semplifica in R1 ed è l’interpolazione lineare solo lungo la fila inferiore.

Ora c’è il caso di f3 e f5. Entrambi corrispondono rispettivamente a (x,y) = (1,1.5) e (x,y) = (2,1.5). Sostituendo questi valori per R1 e R2 e P per entrambi i casi si ottiene:

f3

R1 = f(1,2) + (1 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(1,2)R2 = f(1,1) + (1 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,1)P = R1 + (1.5 - 1)*(R1 - R2) = f(1,2) + 0.5*(f(1,2) - f(1,1))P = 70 + 0.5*(100 - 70) = 85

f5

R1 = f(1,2) + (2 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(2,2)R2 = f(1,1) + (2 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,2)P = R1 + (1.5 - 1)*(R1 - R2) = f(2,2) + 0.5*(f(2,2) - f(1,2))P = 20 + 0.5*(50 - 20) = 35

Quindi cosa ci dice questo? Significa che si sta interpolando solo lungo la direzione y. Questo è evidente quando diamo un’occhiata a P. Esaminando più a fondo i calcoli di P per ciascuno di f3 e f5, si vede che stiamo considerando i valori solo lungo la direzione verticale.

Così, se vuoi una risposta definitiva, f1 e f7 si trovano interpolando lungo la direzione x / colonna solo lungo la stessa riga. f3 e f5 si trovano interpolando y / direzione della riga lungo la stessa colonna. f4 usa una miscela di f1 e f7 per calcolare il valore finale come hai già visto.

Per rispondere alla tua domanda finale, f2, f6 e f8 sono compilati in base alle preferenze personali. Questi valori sono considerati fuori dai limiti, con i valori x e y che sono entrambi 2.5 e che sono fuori dalla nostra griglia per (x,y). In MATLAB, l’implementazione predefinita di questo è di riempire qualsiasi valore al di fuori dei confini definiti per non essere un numero (NaN), ma a volte, le persone estrapolano usando l’interpolazione lineare, copiano i valori di confine, o eseguono qualche imbottitura elaborata come l’imbottitura simmetrica o circolare. Dipende dalla situazione in cui ti trovi, ma non c’è una risposta corretta e definitiva su come riempire f2, f6 e f8 – tutto dipende dalla tua applicazione e da ciò che ha più senso per te.

Come bonus, possiamo verificare che i miei calcoli sono corretti in MATLAB. Definiamo prima una griglia di (x,y) punti nell’intervallo , poi ridimensioniamo l’immagine in modo che sia due volte più grande dove specifichiamo una risoluzione di 0,5 per punto invece di 1. Chiamerò la tua matrice definita A:

A = ; %// Define original matrix = meshgrid(1:2,1:2); %// Define original grid of points = meshgrid(1:0.5:2.5,1:0.5:2.5) %// Define expanded grid of pointsB = interp2(X,Y,A,X2,Y2,'linear'); %// Perform bilinear interpolation

La griglia originale (x,y) di punti assomiglia a:

>> XX = 1 2 1 2>> YY = 1 1 2 2

La griglia espansa per espandere la dimensione della matrice del doppio assomiglia a:

>> X2X2 = 1.0000 1.5000 2.0000 2.5000 1.0000 1.5000 2.0000 2.5000 1.0000 1.5000 2.0000 2.5000 1.0000 1.5000 2.0000 2.5000>> Y2Y2 = 1.0000 1.0000 1.0000 1.0000 1.5000 1.5000 1.5000 1.5000 2.0000 2.0000 2.0000 2.0000 2.5000 2.5000 2.5000 2.5000

B è l’output usando X e Y come griglia originale di punti e X2 e Y2 sono i punti che vogliamo interpolare.

otteniamo:

>> BB = 100 75 50 NaN 85 60 35 NaN 70 45 20 NaN NaN NaN NaN NaN

Lascia un commento