Bitmap Pixel Koordinaten ändern

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
ErnstVolker
Beiträge: 327
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Bitmap Pixel Koordinaten ändern

Beitrag von ErnstVolker »

Hallo fliegermichel,

mit kubischen Splines hab' ich mich noch nicht wirklich beschäftigt. Hier: https://www.arndt-bruenner.de/mathe/scr ... spline.htm habe ich eine grundsätzliche Erklärung dafür gefunden. Dein Spezialfall ist wohl, dass Du über eine Tangente am Anfang die Steigung der kubischen Parabel vorgeben willst. Eine Tangente ist für mich zunächst mal eine "Gerade", salopp eine Linie. Pakt man die Linie in ein x-y-Koordinatensystem, dann folgt sie der Funktion y = m * x + b Das "m" entspricht der Steigung. Die willst Du dem Spline am Anfang mit auf den Weg geben.

Das Gleichungssystem brauchst Du um hierfür

Code: Alles auswählen

y = aix³ + bix² + cix + di
(das habe ich der oben genannten Webseite entnommen) die "a", "b", "c" und "d" zu berechnen.

Um sich grundlegend damit auseinander zu setzen würde ich versuchen die Beispiele der Webseite mit Excel nachzuvollzienen. Mit Excel kann man schon recht übersichtlich Matrizenrechnung veranstalten. Wichtig bei den Matrixformeln in Excel ist, dass man sie nicht einfach mit "Enter" zum rechnen abschickt sondern mit "Shift" + "Strg" + "Enter". Zum Lösen eines Gleichungssystems in Excel braucht man die Befehle "MMULT" mit "MINV" Also: =MMULT(MINV(Matrix);Vektor)

Das war jetzt alles immer noch ziemlich grob und allgemein gehalten. Hhhmm ... Ich bin da halt auch nicht wirklich der Didakt vor dem Herrn. Selber nur froh es irgendwann mal einigermaßen verstanden zu haben.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Bitmap Pixel Koordinaten ändern

Beitrag von fliegermichl »

Hallo Ernst Volker,

danke für die Antwort. Diese Seite kannte ich auch schon. Er setzt aber meines Erachtens zuviel Mathekenntnisse voraus als das man es verstehen könnte.

ErnstVolker
Beiträge: 327
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Bitmap Pixel Koordinaten ändern

Beitrag von ErnstVolker »

Hallo,

ich hab bei meinem Pixelproblem mal was versucht, was zu Division durch Null führt. Das habe ich rausbekommen indem ich mir mal den Nenner in eine Textdatei geschrieben habe. Excel scheint da weniger "empfindlich" zu sein. Da war es mir nicht aufgefallen.

Code: Alles auswählen

  AssignFile(Datei,'Ausgabe.txt');
  rewrite(Datei);
  try
  for i:=0 to High(uBild) do
   for j:=0 to High(vBild) do begin
     writeln(Datei,'Wert[',i,'][',j,']= ',(c[6] * i + c[7] * j + 1):10:20); ------>> Hier den Nenner in die Datei ausgegeben.
     //uBild[i]:= (c[0] * i + c[1] * j + c[2]) / (c[6] * i + c[7] * j + 1); ----->> Einfach mal stillgelegt, damit die Nulldivision nicht auftritt
     //vBild[j]:= (c[3] * i + c[4] * j + c[5]) / (c[6] * i + c[7] * j + 1);
   end;
  except
    on e: Exception do
    begin
      ShowMessage('Fehler: ' + e.Message);
    end;
  end;
  CloseFile(Datei);


In der Datei mit Notepad mal gesucht und es kommt 13 mal Null vor.

Code: Alles auswählen

 
Wert[0][1120]= 0.00000000000000000000
Wert[114][956]= 0.00000000000000000000
Wert[171][874]= 0.00000000000000000000
Wert[228][792]= 0.00000000000000000000
Wert[285][710]= 0.00000000000000000000
Wert[342][628]= 0.00000000000000000000
Wert[399][546]= 0.00000000000000000000
Wert[456][464]= 0.00000000000000000000
Wert[513][382]= 0.00000000000000000000
Wert[570][300]= 0.00000000000000000000
Wert[627][218]= 0.00000000000000000000
Wert[684][136]= 0.00000000000000000000
Wert[741][54]= 0.00000000000000000000
 


Meine Frage ist wie man "sinnvoll" mit einer Nulldivision umgeht. Manche Programme geben NaN für "Not a Number" oder Inf für Infinity für unendlich aus. Kann das Lazarus auch bzw. Wie rechnet man damit weiter?
Einfach nur mit Exception aus der Rechnung aussteigen ist auch blöd.

Sucht man den Nullwert und seine Benachbarten Werte also Stelle "i" und dann "i-1" sowie "i+1" und mittelt einach zwischen den Werten und schreibt den Mittelwert anstelle der Null an die Position "i" ?

Was ist in solchen Fällen mathematisch/technisch richtig?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Bitmap Pixel Koordinaten ändern

Beitrag von af0815 »

Ich würde einen fixen Wert ausserhalb der Signifikation einfach addieren bzw. verwenden wenn der Wert unter die Signifikationschwelle sinkt.Damit ist der Wert ungleich null sichergestellt.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Bitmap Pixel Koordinaten ändern

Beitrag von six1 »

Teilung durch Null ist in der Mathematik nicht erlaubt.
Du solltest vor der Berechnung den Nenner auf Null prüfen, dann "kracht" es auch nicht :-)

NaN ist noch OK, Unendlich ist aber bereits falsch, da es bestimmt wurde.
1/0 ist in der Mathematik aber nicht bestimmbar, damit nicht zulässig.
https://de.wikipedia.org/wiki/Division_(Mathematik)#Division_durch_null
Gruß, Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Bitmap Pixel Koordinaten ändern

Beitrag von wp_xyz »

ErnstVolker hat geschrieben:Meine Frage ist wie man "sinnvoll" mit einer Nulldivision umgeht. Manche Programme geben NaN für "Not a Number" oder Inf für Infinity für unendlich aus. Kann das Lazarus auch bzw. Wie rechnet man damit weiter?
Einfach nur mit Exception aus der Rechnung aussteigen ist auch blöd.

Sucht man den Nullwert und seine Benachbarten Werte also Stelle "i" und dann "i-1" sowie "i+1" und mittelt einach zwischen den Werten und schreibt den Mittelwert anstelle der Null an die Position "i" ?

Was ist in solchen Fällen mathematisch/technisch richtig?

Kommt drauf an...

Zunächst musst du dir das Problem nochmals ansehen. Bei dir werden die Koeffizienten einer Transformation bestimmt. Normalerweise funktioniert das, aber wenn die Referenzpunkte schlecht/falsch gewählt sind, könnte ich mir vorstellen, dass das zugehörige Gleichungssystem nicht lösbar ist. Die NumLib-Routinen geben im lezten Parameter "term" einen Fehlercode aus. Wenn "term" <> 1 ist, brauchst du gar nicht weiterzurechnen. Wenn du's doch tust, passiert vielleicht gar nichts, schlimmstenfalls gibt es vielleicht nur etwas seltsam aussehende Bilder. Oder aber halt doch einen Gleitkomma-Absturz, oder eine Division durch null. Letzteres darfst du auf keinen Fall dadurch lösen, indem du eine kleine Zahl zum Nenner addierst und so die Division durch Null vermeidest. Dadurch wird das Problem verschleiert, das Programm läuft, enthält aber einen verborgenen Fehler, der später, mit Sicherheit beim Kunden, auftreten wird. Ohne die Exception ist es viel schwerer, den Fehler zu finden.

Es sollte auch noch erwähnt werden, dass die Division durch Null oft behoben werden kann, wenn auch der Zähler Null ist. Also: 0/0 kann durchaus einen sinnvollen Wert haben. Bekanntes Beispiel: sin(x)/x hat für x=0 den Wert 1 (weil sin(x) für ganz kleine x ungefähr gleich x ist, wodurch sich das x herauskürzt). Eine Funktion, die sin(x)/x berechnet, muss daher x auf Null prüfen und in diesem fall den Funktionswert 1 übergeben.

Wenn bei allgemein gelagerten Problemen eine Division durch Null durchaus möglich ist (z.B. bei einem Funktionsparser, bei dem der User einen Funktionsausdruck eingeben und berechnen kann), dann kannst du das ganze in einen try-except Block packen, die Exception abfangen und einen "schönen" Fehlermeldungstext anzeigen - genau dafür sind die Dinger gemacht.

Andererseits stört mich bei Exceptions, dass die Arbeit in der IDE durch die Exception unterbrochen wird (gut - das kann man wiederum ausschalten, aber nur für bekannte Exception-Typen). Daher ersetze ich den Funktionswert in diesem Fall häufig durch NaN, denn das signalisiert "keine Zahl", d.h. kein Ergebnis. Außerdem kann man mit NaN nicht mehr rechnen. Also: wenn für x der Wert NaN herauskommt, dann ist ein Weiterrechnen wie x+1 nicht mehr möglich, selbst ein "if x = 1 then" geht nicht mehr - denn es wird wieder eine Exception geworfen, so dass dir weiterhin angezeigt wird, dass etwa faul ist. Nur wenn du ganz sicher bist, dass alles mit rechten Dingen zugeht, kannst du mit "if IsNaN(x) then" prüfen und ggfs wieder eine Fehlermeldung anzeigen.

Inf finde ich nicht so gut, denn es gibt zwei Fälle, +Inf oder -Inf, je nachdem ob du eine positive oder negative Zahl durch Null dividierst. Das erscheint mir zu komplex als Fehlerwert.

ErnstVolker
Beiträge: 327
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Bitmap Pixel Koordinaten ändern

Beitrag von ErnstVolker »

Hallo,

ich habe inzwischen etwas weiter gebastelt und hänge jetzt an der Interpolation zwischen den Pixeln. Das was wp_xyz schon angedeutet hat.

wp_xyz hat geschrieben:Wenn das Zielbild größer ist als das Quellbild, werden dabei immer wieder Pixel des Quellbilds mehrfach verwendet werden, wodurch sich ein stufiges Aussehen ergibt. Besser wird es, wenn man die berechneten Floatingpoint-Werte als Grundlage nimmt, um zwischen benachbarten Pixeln zu interpolieren. Angenommen die Rechnung ergibt die Werte u=6.5/v=10.5. Das bedeutet, ein "imaginäres" Pixel in der Mitte des Blocks zwischen u = 6..7 und v = 10..11 auszulesen ist. Das erhält man wenn man die Farben der Pixel (6/10), (7/10), (6/11), (7/11) ausliest und den Mittelwert der RGB-Komponenten. Wenn das berechnete Pixel näher beim einem Eckpunkt zu liegen kommt, muss die Farbe dieses Eckpunkts stärker, die der anderen Eckpunkte weniger stark gewichtet werden.


Ich bin hier https://entwickler-ecke.de/topic_Bitmap ... 2839220cfb auf eine Funktion gestoßen die mir allerdings unter "// Pixel setzen (R/G/B)" die Fehlermeldung auswirft, dass der Multiplikationsoperator (" * ") not overload sei.

Ich habe versucht mit "StretchDraw" bzw. "StretchBlt" und zuletzt mit "Resample" von BGRABitmap das entzerrte Bild zu vergrößern, aber es ist zu pixelig. Ich dachte diese Funktionen würden automatisch zwischen Pixeln interpolieren.

Die Tutorials zu BGRABitmap habe ich mir auch angesehen. Daher meine Kenntnis von "Resample". Beim überfliegen des letzten Tutorials meine ich da würde interpoliert werden...

Danke!!

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Bitmap Pixel Koordinaten ändern

Beitrag von wp_xyz »

Ich hatte da an eine bilineare Interpolation gedacht, die Formeln gibt es auf https://en.wikipedia.org/wiki/Bilinear_interpolation.

Code: Alles auswählen

// https://en.wikipedia.org/wiki/Bilinear_ ... nit_square
//          A ----- B
//          |    +  |             +: (u,v)  u,v = 0..1
//          |       |
//          C  ---- D
function BilinearInterpolation(u, v: Double; A,B,C,D: byte): Byte;
begin
  Result := trunc(A*(1-u)*(1-v) + B*u*(1-v) + C*(1-u)*v + D*u*v);
end;
 
function BilinearColorInterpolation(x,y: Double; ClrA,ClrB,ClrC,ClrD: TColor): TColor;
var
  u, v: Double;
  r,g,b: Byte;
begin
  u := frac(x);
  v := frac(y);
  r := BilinearInterpolation(u, v, Red(ClrA), Red(ClrB), Red(ClrC), Red(ClrD));
  g := BilinearInterpolation(u, v, Green(ClrA), Green(ClrB), Green(ClrC), Green(ClrD));
  b := BilinearInterpolation(u, v, Blue(ClrA), Blue(ClrB), Blue(ClrC), Blue(ClrD));
  Result := RGBToColor(r, g, b);
end;
...
      for y := 0 to bmp.Height - 1 do
        for x := 0 to bmp.Width - 1 do
        begin
          u := (c[0] * x + c[1] * y + c[2]) / (c[6] * x + c[7] * y + 1);
          v := (c[3] * x + c[4] * y + c[5]) / (c[6] * x + c[7] * y + 1);
          clrA := Image1.Picture.Bitmap.Canvas.Pixels[trunc(u), trunc(v)];
          clrB := Image1.Picture.Bitmap.Canvas.Pixels[trunc(u)+1, trunc(v)];
          clrC := Image1.Picture.Bitmap.Canvas.Pixels[trunc(u), trunc(v+1)];
          clrD := Image1.Picture.Bitmap.Canvas.Pixels[trunc(u+1), trunc(v+1)];
          bmp.Canvas.Pixels[x, y] := BilinearColorInterpolation(u, v, clrA, clrB, clrC, clrd);
        end;

Im beigefügten Demoprojekt, basierend auf dem schon früher geposteten Projekt, sieht man, dass nun die Linien deutlich glatter wiedergegeben werden. Allerdings auf Kosten der Rechenzeit - das liegt an dem langsamen Auslesen/Setzen der Pixel über die Pixels[]-Eigenschaft; mit Hilfe eines LazIntfImage ginge das deutlich schneller.
Dateianhänge
entzerrung-2.zip
(677.79 KiB) 164-mal heruntergeladen

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Bitmap Pixel Koordinaten ändern

Beitrag von Winni »

Hi!

Als schnelle interne Graphik kann ich die BGRAbitmap sehr empfehlen.

* Setpixel / getpixel ist schnell
* Größenanderung geht stufenlos mit resample und sehr gutem Ergebnis.
* 2D perspektivisches mappen, und viele, viele andere Features sind eingebaut.

Zum Schluss wird die gesamte Arbeit auf ein Image oder einen anderen Canvas übertragen.

Installation über den Online Package Manager.

Internationales Forum ist hier: [url]https://forum.lazarus.freepascal.org/index.php/board,46.0.html
[/url]

Winni

PS: 2D Splines gibt's auch

ErnstVolker
Beiträge: 327
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Bitmap Pixel Koordinaten ändern

Beitrag von ErnstVolker »

Hallo,

vielen Dank für Hilfe und Hinweise auf BGRABitmap. Das ließ sich relativ schnell einbauen. Aber ich bekomme damit das Bild nicht "vernünftig" vergrößert.
Codeausschnitt:

Code: Alles auswählen

  EntzBMP:= TBGRABitmap.Create;
  EntzSkal:= TBGRABitmap.Create;
  EntzBMP.SetSize(round(8 * SkalF * PkteWK[2].X), round(8 * PkteWK[2].Y));
  for y := 0 to EntzBMP.Height - 1 do begin
    for x := 0 to EntzBMP.Width - 1 do begin
      u := (c[0] * x + c[1] * y + c[2]) / (c[6] * x + c[7] * y + 1);
      v := (c[3] * x + c[4] * y + c[5]) / (c[6] * x + c[7] * y + 1);
      clrA := FrmBild.Image1.Picture.Bitmap.Canvas.Pixels[trunc(u), trunc(v)];
      clrB := FrmBild.Image1.Picture.Bitmap.Canvas.Pixels[trunc(u)+1, trunc(v)];
      clrC := FrmBild.Image1.Picture.Bitmap.Canvas.Pixels[trunc(u), trunc(v+1)];
      clrD := FrmBild.Image1.Picture.Bitmap.Canvas.Pixels[trunc(u+1), trunc(v+1)];
      EntzBMP.CanvasBGRA.Pixels[x, y] := BilinearColorInterpolation(u, v, clrA, clrB, clrC, clrd);
//      EntzBMP.CanvasBGRA.Pixels[x, y] := FrmBild.Image1.Picture.Bitmap.Canvas.Pixels[round(u), round(v)];
    end;
  end;
  EntzBMP.ResampleFilter:= rfSpline;
  EntzSkal:= EntzBMP.Resample(Breite, Hoehe, rmFineResample) as TBGRABitmap;
  //BGRAReplace(EntzSkal, EntzBMP.Resample(Breite, Hoehe, rmFineResample));
  FrmEntzerrt.Image1.Width := EntzSkal.Width;
  FrmEntzerrt.Image1.Height := EntzSkal.Height;
  FrmEntzerrt.Image1.Picture.Assign(EntzSkal);
  MessageDlg('Bekanntmachung', 'Entzerrtes Bild fertig', mtInformation, [mbOK], 0);
  FrmEntzerrt.Show;
  EntzBMP.Free;
  EntzSkal.Free;


Ich habe hier auch BGRABitmap Resample verwendet, aber das Bild gefällt mir nicht. Es gehen ja sogar die Linien des Kästchenmuster verloren.
Dateianhänge
VieleckPixeligLaz.jpg

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Bitmap Pixel Koordinaten ändern

Beitrag von Winni »

Hi!

Du arbeitest mit einem falschen Ansatz. Ein Fehler entsteht schon einmal, weil beim trunc der Koordination für Pixels "verhunzt" werden.

Vorgehensweise: Mach eine 1:1 Kopie Deines Images auf eine BGRABitmap:

MeineKopie := TBGRAbitmap.create (Image.picture.bitmap);

Und dann kannst Du Dir die Farbe holen mittels

TBGRAPixel := MeineKopie.getPixel (single,single);

Wobei TBGRAPIxel jetzt auch kompatibjel zu TColor ist.

Hoffe es wird so besser.

Winni

ErnstVolker
Beiträge: 327
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Bitmap Pixel Koordinaten ändern

Beitrag von ErnstVolker »

Hhhhmmm,

ich kann jetzt nicht behaupten, dass sich zwischen den Formeln großartig am Bild was ändert.

Code: Alles auswählen

 AusgBild:= TBGRABitmap.Create(FrmBild.Image1.Picture.Bitmap);
  EntzBMP:= TBGRABitmap.Create;
  EntzSkal:= TBGRABitmap.Create;
  EntzBMP.SetSize(round(8 * SkalF * PkteWK[2].X), round(8 * PkteWK[2].Y));
  for y := 0 to EntzBMP.Height - 1 do begin
    for x := 0 to EntzBMP.Width - 1 do begin
      u := (c[0] * x + c[1] * y + c[2]) / (c[6] * x + c[7] * y + 1);
      v := (c[3] * x + c[4] * y + c[5]) / (c[6] * x + c[7] * y + 1);
      clrA := AusgBild.GetPixel(trunc(u), trunc(v));
      clrB := AusgBild.GetPixel(trunc(u+1), trunc(v));
      clrC := AusgBild.GetPixel(trunc(u), trunc(v+1));
      clrD := AusgBild.GetPixel(trunc(u+1), trunc(v+1));
      //EntzBMP.SetPixel(x, y, BilinearColorInterpolation(u, v, clrA, clrB, clrC, clrd)); ----------->>> Hier die Bilineare Farbinterpolation von wp_xyz
      EntzBMP.SetPixel(x, y, AusgBild.GetPixel(u,v,rfSpline)); ------------------------>>>>> Alternativ SetPixel / GetPixel
    end;
  end;
  EntzBMP.ResampleFilter:= rfSpline;------------------------------------------------------------->>>>>>> Das Resample-Filter hat etwas Auswirkung. Bei z.B. einem "rfLanczos4" wird's etwas verschwommener
  EntzSkal:= EntzBMP.Resample(Breite, Hoehe, rmFineResample) as TBGRABitmap;
  FrmEntzerrt.Image1.Width := EntzSkal.Width;
  FrmEntzerrt.Image1.Height := EntzSkal.Height;
  FrmEntzerrt.Image1.Picture.Assign(EntzSkal);
  MessageDlg('
Bekanntmachung', 'Entzerrtes Bild fertig', mtInformation, [mbOK], 0);


BGRABitmap ist allerdings wesentlich schneller als die Pixelmanipulation über Canvas.

Aber das fertige Bild entspricht nicht meiner Vorstellung. Ich hätte es gerne genauso "scharf" wie das Ausgangsbild.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Bitmap Pixel Koordinaten ändern

Beitrag von Winni »

Hi!

Tja, wenn Du nicht ordentlich liest ....

Ich hab geschrieben, dass Du getPixel mit single/single ausführen kannst.

Also:

clrA := AusgBild.GetPixel (u, v);
clrB := AusgBild.GetPixel (u+1, v);
clrC := AusgBild.GetPixel (u,v+1);
clrD := AusgBild.GetPixel(u+1, v+1);

So bekommst Du die Farben mit single Koordinaten!

Gruß, Winni

ErnstVolker
Beiträge: 327
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Bitmap Pixel Koordinaten ändern

Beitrag von ErnstVolker »

wenn ich es so wie vorgeschlagen versuche und die Farben ohne trunc erhalte ändert sich am Bild nicht wirklich was.

bei meiner ursprünglichen Variante:

Code: Alles auswählen

 
  Breite := FrmBild.Image1.Picture.Bitmap.Width;
  Hoehe := FrmBild.Image1.Picture.Bitmap.Height;
 
  slegen(8, 8, MatA[0, 0], b[0], a[0], ca, term); // Lösen des Gleichungssystemes. Ergebnis ist Lösungsvektor "a"
 
  for j:=0 to High(HZiel) do begin
    for i:=0 to High(BZiel) do begin
      q:= ((a[0] * i + a[1] * j + a[2]) / (a[6] * i + a[7] * j + 1));
      BZiel[i]:= round(q);
      r:= ((a[3] * i + a[4] * j + a[5]) / (a[6] * i + a[7] * j + 1));
      HZiel[j]:= round(r);
    end;
  end;
  MinB:= minvalue(BZiel);
  MaxB:= maxvalue(BZiel);
  BreiteZiel:= MaxB - MinB;
 
  MinH:= minvalue(HZiel);
  MaxH:= maxvalue(HZiel);
  HoeheZiel:= MaxH - MinH;
 
  SkalB:= Breite / BreiteZiel;
  SkalH:= Hoehe / HoeheZiel;
 
  KopieBMP:= TBGRABitmap.Create(FrmBild.Image1.Picture.Bitmap);
  EntzSkal:= TBGRABitmap.Create;
  EntzBMP:= TBGRABitmap.Create(Breite, Hoehe, BGRA(255,0,0));
 
  for j:=0 to EntzBMP.Height - 1 do begin
    for i:=0 to EntzBMP.Width - 1 do begin
      q:= (a[0] * i + a[1] * j + a[2]) / (a[6] * i + a[7] * j + 1) + BreiteZiel / 2;
      r:= (a[3] * i + a[4] * j + a[5]) / (a[6] * i + a[7] * j + 1) + HoeheZiel / 2;
      EntzBMP.SetPixel(round(SkalB * q), round(SkalH * r), KopieBMP.GetPixel(i, j, rfSpline));
    end;
  end;
 
 EntzBMP.ResampleFilter:= rfBestQuality;
 EntzSkal:= EntzBMP.Resample(Breite, Hoehe, rmFineResample) as TBGRABitmap;
 MessageDlg('Bekanntmachung','Entzerrtes Bild berechnet', mtInformation, [mbOK], 0);
 FrmEntzerrt.Image1.Width:= Breite;
 FrmEntzerrt.Image1.Height:= Hoehe;
 FrmEntzerrt.Image1.Picture.Bitmap.Assign(EntzSkal);


erhalte ich das Bild fast wie ich es haben will. Alle Ecken sind drauf, die Perspektive ist raus und man kann die Maße lesen.
Allerdings sind Lücken im Bild vorhanden da kommt das Rot vom Hintergrund durch. Die Lücken müssen mit Umgebung gefüllt werden.
Dateianhänge
Vieleck_rot.jpg

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Bitmap Pixel Koordinaten ändern

Beitrag von Winni »

Hi!

Das Elend mit den Lücken kenne ich.
Design-Fehler - man muss den xy-loop nicht über das Original laufen lassen, sondern vorher die Ziel-Größe berechnen und von der Zielgrösse den xyloop laufen lassen - und dann bei getpixel allerdings ohne trunc arbeiten. Alle Transformations-Gleichungen muss man dann aber "rückwärts" machen.

Workaround: den Farbwert für x/y auch bei x+1/y und x/y+1 setzen. Falls das nicht genug ist, muss man alle 8 umrandenden Pixel mit diesem Farbwert setzen.

Buena note
Winni

Antworten