Bilinear billedinterpolation/skalering – Et beregningseksempel

Jeg vil gerne henvise til denne meget indsigtsfulde grafik fra Wikipedia, der illustrerer, hvordan man laver bilinear interpolation for et punkt:

Kilde: Wikipedia

Som du kan se, er de fire røde punkter det, man kender. Disse punkter kender du i forvejen, og P er det punkt, som vi ønsker at interpolere. Som sådan er vi nødt til at foretage to trin (som du har angivet i dit indlæg). For at håndtere x-koordinaten (vandret) skal vi beregne, hvad den interpolerede værdi er rækkevis for den øverste række af røde punkter og den nederste række af røde punkter. Dette resulterer i de to blå punkter R1 og R2. For at håndtere y-koordinaten (lodret) bruger vi de to blå punkter og interpolerer lodret for at få det endelige P-punkt.

Når du ændrer størrelsen på et billede, selv om vi ikke visuelt kan se det, jeg vil sige, men forestil dig, at dette billede er et 3D-signal f. Hvert punkt i matrixen er faktisk en 3D-koordinat, hvor kolonneplaceringen er x-værdien, rækkeplaceringen er y-værdien og z-værdien er selve matrixens mængde/gråskala-værdi. Derfor er gør z = f(x,y) værdien af matricen på placering (x,y) i matricen. I vores tilfælde, fordi du har med billeder at gøre, er hver værdi af (x,y) hele tal, der går fra 1 op til så mange rækker/kolonner, som vi har, afhængigt af hvilken dimension du kigger på.

Derfor, givet den koordinat, du ønsker at interpolere ved (x,y), og givet de røde koordinater i billedet ovenfor, som vi kalder dem x1,y1,x2,y2 som pr diagrammet – specifikt at gå med konventionen i diagrammet og henvise til, hvordan billeder er tilgængelige: x1 = 1, x2 = 2, y1 = 2, y2 = 1, beregnes de blå koordinater R1 og R2 via 1D-interpolation kolonnevis ved hjælp af den samme række, som begge punkter falder sammen på:

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

Det er vigtigt at bemærke, at (x - x1) / (x2 - x1) er en vægt/andel af, hvor meget af en blanding output består af mellem de to værdier, der ses ved f(x1,y1) og f(x2,y1) for R1 eller f(x1,y2) og f(x2,y2) for R2. Konkret er x1 udgangspunktet, og (x2 - x1) er forskellen på x-værdierne. Du kan verificere, at hvis du erstatter x1 med x, får vi 0, mens x2 som x giver os 1. Denne vægt svinger mellem , hvilket er nødvendigt for at beregningerne kan fungere.

Det skal bemærkes, at billedets oprindelse er i øverste venstre hjørne, og derfor er (1,1) i øverste venstre hjørne. Når man har fundet R1 og R2, kan vi finde P ved at interpolere rækkevis:

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

Og (y - y2) / (y2 - y1) angiver andelen/blandingen af, hvor meget R1 og R2 bidrager til det endelige output P. Som sådan har du beregnet f5 korrekt, fordi du har brugt fire kendte punkter: Øverst til venstre er 100, øverst til højre er 50, nederst til venstre er 70 og nederst til højre er 20. Konkret betyder det, hvis du vil beregne f5, at (x,y) = (1.5,1.5), fordi vi befinder os halvvejs mellem 100 og 50 på grund af, at du skalerer billedet med to. Hvis du sætter disse værdier ind i ovenstående beregning, får du værdien 60, som du forventede. Vægtene for begge beregninger vil også resultere i 0.5, hvilket er det, du fik i dine beregninger, og det er det, vi forventer.

Hvis du beregner f1, svarer dette til (x,y) = (1.5,1), og hvis du indsætter dette i ovenstående ligning, vil du se, at (y - y2)/(y2 - y1) giver dig 0 eller vægten er 0, og det, der beregnes, er således blot R2, hvilket kun svarer til den lineære interpolation langs den øverste række. På samme måde, hvis vi beregnede f7, betyder det, at vi ønsker at interpolere ved (x,y) = (1.5,2). I dette tilfælde vil du se, at (y - y2) / (y2 - y1) er 1 eller vægten er 1 og dermed P = R2 + (R1 - R2), hvilket forenkles til R1 og svarer kun til den lineære interpolation langs den nederste række.

Nu er der tilfældet med f3 og f5. Disse svarer begge til henholdsvis (x,y) = (1,1.5) og (x,y) = (2,1.5). Hvis man erstatter disse værdier med R1 og R2 og P for begge tilfælde, får man:

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

Så hvad fortæller det os? Det betyder, at du kun interpolerer langs y-retningen. Dette fremgår tydeligt, når vi kigger på P. Hvis man undersøger beregningerne mere grundigt af P for hver af f3 og f5, kan man se, at vi kun overvejer værdier langs den lodrette retning.

Som sådan, hvis man vil have et endeligt svar, findes f1 og f7 ved at interpolere langs x / kolonne-retningen kun langs den samme række. f3 og f5 findes ved at interpolere y / række-retningen langs den samme kolonne. f4 bruger en blanding af f1 og f7 til at beregne den endelige værdi, som du allerede har set.

For at besvare dit sidste spørgsmål er f2, f6 og f8 udfyldt ud fra personlige præferencer. Disse værdier anses for at være uden for grænserne, idet værdierne x og y begge er 2.5, og det er uden for vores gitter for (x,y). I MATLAB er standardimplementeringen af dette at udfylde alle værdier uden for de definerede grænser til ikke at være et tal (NaN), men nogle gange ekstrapolerer folk ved hjælp af lineær interpolation, kopierer grænseværdierne eller udfører en udførlig udfyldning som symmetrisk eller cirkulær udfyldning. Det afhænger af, hvilken situation du står i, men der findes ikke noget korrekt og endegyldigt svar på, hvordan f2, f6 og f8 skal udfyldes – det hele afhænger af din applikation, og hvad der giver mest mening for dig.

Som en bonus kan vi verificere, at mine beregninger er korrekte i MATLAB. Vi definerer først et gitter af (x,y) punkter i området og tilpasser derefter størrelsen på billedet, så det er dobbelt så stort, hvor vi angiver en opløsning på 0,5 pr. punkt i stedet for 1. Jeg kalder din definerede matrix 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

Det oprindelige (x,y) gitter af punkter ser ud som:

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

Det udvidede gitter for at udvide størrelsen af matricen med dobbelt så meget ser ud som:

>> 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 er resultatet med X og Y som det oprindelige gitter af punkter og X2 og Y2 er de punkter, vi ønsker at interpolere ved.

Vi får:

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

Skriv en kommentar