Autor |
Beitrag |
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Di 09.01.07 23:39
Hi,
weiß jemand wie ich ein Bild, bzw Pixel Interpolieren kann?
Sagen wir, ich habe ein Bild der größe 512x512 und möchte bei dem das Pixel an der stelle 128.7x63.2 haben, sprich kein ganzes Pixel, sondern den Farbwert zwischen 4 Pixeln.
Ich bräuchte also etwas á la:
function GetInterpolatedColor(Bitmap: TBitmap; X, Y: Single): TColor;
Hat da jemand was, bzw weiß wie das geht?
Aya~
PS: Ich brauche es nicht um ein Bild zu resizen o.Ä. mir geht es wirklich nur um einige spezielle X,Y koordinaten.
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Di 09.01.07 23:47
Ich kenn mich mit Interpolation nicht so genau aus, aber hast Du schon mal versucht, einen gewichteten Durchschnitt der RGB-Komponenten der Pixel zu nehmen? Also in Deinem Beispiel in etwa so
P1 = 128x63
P2 = 128x64
P3 = 129x63
P4 = 129x64
Quelltext 1:
| Rneu = (8 x R1 + 2 x R2 + 7 x R4 + 3 x R3) / 20 |
Entsprechendes für die anderen Farbkomponenten.
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 10.01.07 00:04
Ich würde mal sagen bei der Betrachtung von nur 4 Pixeln ist eine ungewichtete Betrachtung sinnvoller. Also ein ganz normales arithmetisches Mittel.
Lediglich bei einer "echten" Interpolation würde man gewichtet vorgehen, dabei die Gewichte aber aus einer größeren Anzahl von Pixeln (ich habe wahlweise 16 oder 36 genommen) berechnen. Nur dann kann man ja versuchen Kontrastverläufe etc. mit in die Berechnung einfließen zu lassen, wofür Gewichte bspw. sinnvoll sind. Aber das ist in diesem Fall ja unwichtig...
|
|
Aya 
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mi 10.01.07 02:17
Hi,
UGrohne hat folgendes geschrieben: | Quelltext 1:
| Rneu = (8 x R1 + 2 x R2 + 7 x R4 + 3 x R3) / 20 |
Entsprechendes für die anderen Farbkomponenten. |
Ne, das geht nicht.. weil du so nur jeweils 2 pixel einbeziehst... aber du mußt ja zwischen allen 4 interpolieren.
jaenicke hat folgendes geschrieben: | Ich würde mal sagen bei der Betrachtung von nur 4 Pixeln ist eine ungewichtete Betrachtung sinnvoller. Also ein ganz normales arithmetisches Mittel. |
Wie, was? Ob sinnvoller oder nicht ist halt ne frage wofür man es brauch.. ich würde nicht fragen wie ich interpoliere wenn ich es nicht brauche
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 10.01.07 04:00
Aya hat folgendes geschrieben: | Hi,
UGrohne hat folgendes geschrieben: | Quelltext 1:
| Rneu = (8 x R1 + 2 x R2 + 7 x R4 + 3 x R3) / 20 |
Entsprechendes für die anderen Farbkomponenten. |
Ne, das geht nicht.. weil du so nur jeweils 2 pixel einbeziehst... aber du mußt ja zwischen allen 4 interpolieren. |
Mit R1 bis R4 sind doch alle vier Rotwerte der vier Pixel einbezogen. Und genauso geht es dann doch mit grün und blau.
Aya hat folgendes geschrieben: | jaenicke hat folgendes geschrieben: | Ich würde mal sagen bei der Betrachtung von nur 4 Pixeln ist eine ungewichtete Betrachtung sinnvoller. Also ein ganz normales arithmetisches Mittel. |
Wie, was? Ob sinnvoller oder nicht ist halt ne frage wofür man es brauch.. ich würde nicht fragen wie ich interpoliere wenn ich es nicht brauche  |
Ich wollte damit lediglich sagen, dass mit nur 4 Pixeln die Werte relativ ungenau sein dürften. Sorry, wenn es anders rüberkam. Da ist dann die Frage, ob etwas besseres herauskommt, wenn man die benachbarten Pixel entsprechend ihrem Anstand zum gesuchten Punkt bewertet als wenn man so tut, als wären die genauso weit vom gesuchten Punkt entfernt.
Aber bei starken Kontrasten ist das sicherlich so am besten. Bei meinen Experimenten hat es aber nur die Berechnung verlangsamt, die Ergebnisse waren bei gewichteten Werten jedoch praktisch identisch zu ungewichteten, als ich nur 4 Pixel betrachtet habe.
Egal, jedenfalls ist doch das von UGrohne genau so gemeint, wie eine solche exakte Interpolation unter Einbeziehung aller vier Pixel entsprechend ihres Abstandes zum gesuchten Punkt aussehen müsste. Es fehlt allerdings noch die genaue Berechnung der Gewichte.
Die würde ich folgendermaßen machen:
Ich nummeriere mal die Pixel von P1 bis P4 zeilenweise, P1 und P2 sind also die beiden oberen Pixel. R1 bis R4 sind die daszugehörigen Rotwerte. P ist der gesuchte Punkt. R der dazugehörige Rotwert.
Delphi-Quelltext 1:
| R := R1 + ((P.x - P1) * (R2 - R1) + ((P.x - P1) * (P.x - P1) + (P.y - P1) * (P.y - P1)) * (R4 - R1) + (P.y - P1) * (R3 - R1)) div 3; |
Das wäre eine mögliche Berechnung. Ich verrechne den linken oberen Pixel mit den anderen dreien, wobei jeweils der Abstand des gesuchten Punkts zum linken oberen das Entscheidende Kriterium für die Gewichtung ist.
Ich hoffe ich habe mich jetzt nicht vertan. Ich bin schon etwas müde.
Es gibt allerdings noch viele andere Algorithmen. Die meisten funktionieren jedoch erst mit mehr als 4 Pixeln, weil sie beispielsweise auch Bildfehler korrigieren, indem einzelne "stark abweichende" Pixel gering gewichtet werden.
|
|
Reinhard Kern
      
Beiträge: 591
Erhaltene Danke: 14
|
Verfasst: Mi 10.01.07 07:02
jaenicke hat folgendes geschrieben: | [
...
Es gibt allerdings noch viele andere Algorithmen. Die meisten funktionieren jedoch erst mit mehr als 4 Pixeln, weil sie beispielsweise auch Bildfehler korrigieren, indem einzelne "stark abweichende" Pixel gering gewichtet werden. |
Hallo,
korrekt ist meiner Meinung nach, die Pixel als Quadrate zu betrachten und den gesuchten Pixel über die vorhandenen zu legen nach folgender Skizze. Die Gewichtung ergibt sich dann aus dem Flächenanteil des gesuchten Quadrats, der auf jedes der 4 überdeckten Quadrate fällt. Das ist auch ganz einfach zu berechnen, mit den Zahlen in der Skizze sind die Koeffizienten
0,06 0,14
0,24 0,56
was automatisch 1,0 ergibt.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| | | | -------------------------------------- | 100/100 | 101/100 | | | | | | | | | | | | | | .....|............ | | . | . | | . | . | ------------.------------------------- | . | . | | . | # <<<<<<<<<<<<<<< gesuchter Pixel | . | . | 101,7 / 101,8 | . | . | | . | . | | .....|............ | | | | | 100/101 | 101/101 | -------------------------------------- | | | | | | |
Bitte um Verzeihung wegen der Vergewaltigung des Delphi-Tags.
Gruss Reinhard
|
|
Phantom1
      
Beiträge: 390
|
Verfasst: Mi 10.01.07 12:38
Ich stimme "Reinhard Kern" zu, die flächenmäßige Gewichtung ist gut, hab mal versucht das ganze in delphi umzusetzen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| function GetInterpolatedColor(Bitmap: TBitmap; X, Y: Single): TColor; type PRGBArray = ^TRGBArray; TRGBArray = array[0..0] of TRGBQuad; var p: PRGBArray; TruncX, TruncY: Integer; FracX, FracY: Single; TopLeft, TopRight, BottomLeft, BottomRight: Single; r, g, b: Single; begin if x<0 then x:=0 else if x>Bitmap.Width-2 then x:=Bitmap.Width-2; if y<0 then y:=0 else if y>Bitmap.Height-2 then y:=Bitmap.Height-2; Bitmap.PixelFormat:=pf32bit; TruncX:=Trunc(X); TruncY:=Trunc(Y); FracX:=X-TruncX; FracY:=Y-TruncY; TopLeft := (1-FracX) * (1-FracY); TopRight := (FracX) * (1-FracY); BottomLeft := (1-FracX) * (FracY); BottomRight:= (FracX) * (FracY); p:=Bitmap.ScanLine[TruncY]; r:=p^[TruncX].rgbRed * TopLeft + p^[TruncX+1].rgbRed * TopRight; g:=p^[TruncX].rgbGreen * TopLeft + p^[TruncX+1].rgbGreen * TopRight; b:=p^[TruncX].rgbBlue * TopLeft + p^[TruncX+1].rgbBlue * TopRight; p:=Bitmap.ScanLine[TruncY+1]; r:=r + p^[TruncX].rgbRed * BottomLeft + p^[TruncX+1].rgbRed * BottomRight; g:=g + p^[TruncX].rgbGreen * BottomLeft + p^[TruncX+1].rgbGreen * BottomRight; b:=b + p^[TruncX].rgbBlue * BottomLeft + p^[TruncX+1].rgbBlue * BottomRight; Result:=RGB(Round(r), Round(g), Round(b)); end; |
mfg
|
|
Aya 
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mi 10.01.07 20:41
Hi,
danke für die antworten
Der Code von Phantom1 sieht in etwa so aus wie das was ich mir zusammengebastelt hatte, aber ich hab im netz dashier gefunden:
Interpolating Bitmap Resampler v.1.2
das ist zwar für nen komplettes Bild zum resamplen, aber ich hab mir einfach das was ich brauchte rausgesucht.. dadurch ist das ganze jetzt nur ~10 zeilen lang und ich hab die möglichkeit zwischen allen möglichen Filtern auszuwählen für's resampling
Aber tausend dank trotzdem~
Aya~
_________________ Aya
I aim for my endless dreams and I know they will come true!
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 10.01.07 21:02
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
|