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