Bilineáris képinterpoláció / méretezés – Egy számítási példa

Ezzel a Wikipédiából származó, nagyon szemléletes grafikával szeretném bemutatni, hogyan kell bilineáris interpolációt végezni egy pontra:

Forrás: Wikipedia

Amint látod, a négy piros pont az, ami ismert. Ezeket a pontokat előre tudjuk, és P az a pont, amit interpolálni szeretnénk. Mint ilyen, két lépést kell tennünk (ahogy a hozzászólásodban is jelezted). A x koordináta (vízszintes) kezeléséhez ki kell számolnunk, hogy mi az interpolált érték soronként a piros pontok felső sora és a piros pontok alsó sora esetében. Ennek eredménye a két kék pont R1 és R2. A y koordináta (függőleges) kezeléséhez a két kék pontot használjuk, és függőlegesen interpolálunk, hogy megkapjuk a végső P pontot.

A kép átméretezésekor, bár vizuálisan nem látjuk, amit mondani akarok, de képzeljük el, hogy ez a kép egy 3D jel f. A mátrix minden egyes pontja valójában egy 3D koordináta, ahol az oszlop helye a x érték, a sor helye a y érték és a z érték magának a mátrixnak a mennyisége / szürkeárnyalatos értéke. Ezért a z = f(x,y) elvégzése a mátrixnak a mátrix (x,y) helyén lévő értéke. A mi esetünkben, mivel képekkel van dolgunk, a (x,y) minden egyes értéke egész számok, amelyek 1-től annyi sorig/oszlopig terjednek, ahány sorunk/oszlopunk van, attól függően, hogy milyen dimenziót nézünk.

Ezért, adott az a koordináta, amelyet interpolálni szeretnénk a (x,y) helyen, és adottak a fenti képen látható piros koordináták, amelyeket az ábra szerint x1,y1,x2,y2-nek hívunk – kifejezetten a diagram konvencióját követve és a képek elérésének módjára hivatkozva: x1 = 1, x2 = 2, y1 = 2, y2 = 1, a kék koordinátákat R1 és R2 1D interpolációval számoljuk ki oszloponként, ugyanazt a sort használva, amelyen mindkét pont egybeesik:

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

Fontos megjegyezni, hogy a (x - x1) / (x2 - x1) egy súly / arány, hogy a kimenet mennyi keveredésből áll a f(x1,y1) és f(x2,y1)-nél látható két érték között a R1 vagy f(x1,y2) és f(x2,y2) a R2 esetében. Konkrétan x1 a kiindulási pont és (x2 - x1) a x értékek különbsége. Ellenőrizhetjük, hogy ha x1-et x-nek helyettesítjük, akkor 0-t kapunk, míg x2 x-nek helyettesítve 1-et. Ez a súly között ingadozik, ami szükséges ahhoz, hogy a számítások működjenek.

Megjegyzendő, hogy a kép origója a bal felső sarokban van, így (1,1) a bal felső sarokban van. Miután megtaláltuk R1 és R2, soronkénti interpolációval megtalálhatjuk P-et:

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

Mégis (y - y2) / (y2 - y1) jelöli azt az arányt / keveréket, hogy R1 és R2 mennyivel járul hozzá a végső kimenethez P. Mint ilyen, helyesen számoltad ki a f5 értéket, mert négy ismert pontot használtál: A bal felső 100, a jobb felső 50, a bal alsó 70 és a jobb alsó 20. Konkrétan, ha ki akarod számítani f5, akkor ez azt jelenti, hogy (x,y) = (1.5,1.5), mert a 100 és az 50 között félúton vagyunk, ami annak köszönhető, hogy kettővel méretezed a képet. Ha ezeket az értékeket beillesztjük a fenti számításba, akkor a várt 60-as értéket kapjuk. Mindkét számításnál a súlyok is 0.5-t fognak eredményezni, amit a számításaidban kaptál, és ezt várjuk.

Ha kiszámítod a f1 értéket, akkor ez (x,y) = (1.5,1) értéknek felel meg, és ha ezt behelyettesíted a fenti egyenletbe, akkor látni fogod, hogy a (y - y2)/(y2 - y1) 0-t ad, vagy a súlya 0, és így amit kiszámítasz, az csak R2, ami csak a felső sor mentén végzett lineáris interpolációnak felel meg. Hasonlóképpen, ha f7-et számoltunk, ez azt jelenti, hogy (x,y) = (1.5,2)-nél akarunk interpolálni. Ebben az esetben látni fogjuk, hogy (y - y2) / (y2 - y1) 1 vagy a súlya 1, tehát P = R2 + (R1 - R2), ami egyszerűsítve R1, és csak az alsó sor mentén történő lineáris interpolációnak felel meg.

Most itt van a f3 és f5 esete. Ezek mindkettő (x,y) = (1,1.5)-nek, illetve (x,y) = (2,1.5)-nek felel meg. Ha ezeket az értékeket behelyettesítjük R1 és R2, valamint P helyett mindkét esetben megkapjuk:

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

Mit mond ez nekünk? Ez azt jelenti, hogy csak az y-irány mentén interpolál. Ez nyilvánvalóvá válik, ha vetünk egy pillantást a P-re. Ha alaposabban megvizsgáljuk a P számításait mind a f3, mind a f5 esetében, akkor láthatjuk, hogy csak a függőleges irány mentén vettük figyelembe az értékeket.

Így, ha végleges választ szeretnénk, akkor a f1 és f7 értékeket csak a x / oszlop irány mentén, ugyanazon sor mentén végzett interpolációval találjuk meg. f3 és f5 a y / sorirányú interpolációval találhatók ugyanazon oszlop mentén. A f4 a f1 és a f7 keverékét használja a végső érték kiszámításához, ahogy már láttad.

Az utolsó kérdésedre válaszolva, a f2, f6 és f8 személyes preferencia alapján van kitöltve. Ezeket az értékeket határon kívülinek tekintjük, a x és y értékek mindkettő 2.5, és ez a (x,y) rácson kívül van a (x,y) értékünkön. A MATLAB-ban ennek alapértelmezett megvalósítása az, hogy a meghatározott határokon kívül eső értékeket nem-számnak (NaN) tölti ki, de néha az emberek lineáris interpolációval extrapolálnak, másolják a határértékeket, vagy valamilyen bonyolult kitöltést végeznek, például szimmetrikus vagy körkörös kitöltést. Attól függ, milyen helyzetben vagyunk, de nincs helyes és végleges válasz arra, hogyan kell kitölteni a f2, f6 és f8 értékeket – minden az alkalmazásunktól függ, és attól, hogy mi a legértelmesebb számunkra.

Bónuszként a MATLAB-ban ellenőrizhetjük, hogy a számításaim helyesek. Először definiálunk egy (x,y) pontból álló rácsot a tartományban, majd átméretezzük a képet, hogy kétszer akkora legyen, ahol 1 helyett pontonként 0,5 felbontást adunk meg. A definiált mátrixot A-nak fogom hívni:

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

Az eredeti (x,y) pontrács így néz ki:

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

A kibővített rács, hogy a mátrix méretét kétszeresére növeljük, így néz ki:

>> 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 a kimenet, amelyben X és Y az eredeti pontrács, X2 és Y2 pedig azok a pontok, amelyeknél interpolálni szeretnénk.

Azt kapjuk:

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

Szólj hozzá!