Perspektivisches Entzerren eines Bildes [gelöst]

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Perspektivisches Entzerren eines Bildes [gelöst]

Beitrag von corpsman »

Servus miteinander.

Ich habe durch Berücksichtigung des Fluchtpunktes dieses Bild
original.jpeg
original.jpeg (64.19 KiB) 3588 mal betrachtet
in x Richtung Entzerrt, dann kommt das hier raus:
entzerrt.jpeg
entzerrt.jpeg (160.43 KiB) 3588 mal betrachtet
Das Problem ist natürlich das das Bild in y-Richtung immer noch verzerrt ist und irgendwie stehe ich auf dem Schlauch, das muss doch auch gehen, das Bild in y- Richtung zu entzerren.

Könnt ihr mir da grad weiter helfen ;)
Zuletzt geändert von corpsman am Di 26. Jan 2021, 16:13, insgesamt 1-mal geändert.
--
Just try it

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Perspektifisches Entzerren eines Bildes

Beitrag von sstvmaster »

Hier gabs mal was ähnliches, vielleicht hilfts: viewtopic.php?f=25&t=12696
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

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: Perspektifisches Entzerren eines Bildes

Beitrag von Winni »

Hallo!

Wo ist das Problem?

Du hast es doch für die X-Achse gelöst.
Nun must Du nur x und y vertauschen, um das auf die Y-Achse anzuwenden!

Winni

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Perspektifisches Entzerren eines Bildes

Beitrag von corpsman »

Evtl hab ich bei der 1. Version auch einfach nur "Gut genug" Beschummelt.
Skizze.jpg
Skizze.jpg (22.77 KiB) 3479 mal betrachtet
Der Bisherige Algorithmus nimmt die 2 Grünen Geraden und Berechnet deren Schnittpunkt = Fluchtpunkt.

Von Diesem Punkt aus werden dann geraden durch die beiden oberen Ecken des Bildes gezogen und mit einer Waagrechten am unteren Bildrand geschnitten (Rosa).
Dann wird das so entstandene Trapez (Blau) mittels Biliniarer Interpolation auf das Original Rechteck gestaucht da die Schnittpunkte Außerhalb des Sichtbereiches waren entstehen die schwarzen Flächen.

Im sich so ergebenden Bild laufen die Waagrechten aber nicht auf einen Punkt zu, viel mehr wird deren Abstand nach oben immer kleiner je näher ich an den oberen Bildrand komme.

Evtl ist mein gesammter Ansatz murks und ich muss noch mal von Vorne anfangen, kann auch sein.

in dem Beitrag den sstvmaster verlinkt hat gabs ein paper das ich noch versuche zu verstehen, bin mir aber noch nicht so recht sicher ob ich das kapiere bzw anwenden kann ..
--
Just try it

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Perspektifisches Entzerren eines Bildes

Beitrag von kupferstecher »

Hallo corpsman,

für die Bestimmung der Entzerrung ist m.E. die Kenntnis der Blattneigung in jedem Punkt ggü. der Kamera/Linse erforderlich. Zum Fluchtpunkt hin wird der Blickwinkel immer steiler (lim= 90° im Fluchtpunkt) und damit die Verzerrung größer. Ich denke, wenn du die Koordinaten hättest, wo man genau senkrecht auf das Blatt schaut (bei deinem Beispiel unten außerhalb des Bildes), könntest du den Winkelverlauf zumindest grob rekonstruieren, der Blattabstand dürfte auch noch mit reinspielen.

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: Perspektifisches Entzerren eines Bildes

Beitrag von Winni »

Hi!

Man kann sich den Kopf zerbrechen.
Man kann das aber auch einfach machen.

Siehe Anhang:

Man nimmt sich die größtmögliche Anzahl von ganzen Karos am Fuß.
Dann nimmt man die zugehörigen Karos am Kopf.
Ausmessen der Strecken unten und oben in Pixeln.
Z.B mit einem Bildbearbeiter, der einem die Koordinaten anzeigt wie der GIMP.

Nun kann man Strecke_oben und Strecke_unten ins Verhältnis setzen.
Dadurch weiss man, wie groß die Streckung oben sein muss.
Oder die Stauchung unten.
Und also auch bei jeder Linie dazwischen:
Geht alles ganz linear.

Wenn hier keine Mathe-Akrobatik veranstaltet werden soll,
sondern nur das Problem gelöst werden soll, dann hat die BGRAbitmap
schon die Lösung:

Code: Alles auswählen

MyBGRAbitmap.FillQuadPerspectiveMappingAntialias(
     //destination
     D1, D2, D3, D4,
     SourceBGRAbitmap,
     //source
    S1,S2,S3,S4,
     );     
wobei D1..D4 und S1..S4 Punkte mit Fließkomma-Koordinaten sind (TPointF).

Winni
Dateianhänge
perspektive2.png
perspektive2.png (138.43 KiB) 3385 mal betrachtet

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Perspektifisches Entzerren eines Bildes

Beitrag von corpsman »

*g*

Danke ich werde es mir ansehen, hab mir auch ein neues Buch zum Thema bestellt, das kommt anfang nächste Woche. Bin mal gespannt was sich daraus ergibt ;).
--
Just try it

sstvmaster
Beiträge: 575
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Perspektifisches Entzerren eines Bildes

Beitrag von sstvmaster »

LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Perspektifisches Entzerren eines Bildes

Beitrag von corpsman »

So ich hab das nun mal Getestet..

Zur Auswahl standen:
1. meine Version im not Crush mode
2. Der Link von sstvmaster
3. BGRA von Winni

und hier die Ergebnisse:
1. Meins:
Corpsman_crush.png
Corpsman_crush.png (445.26 KiB) 3261 mal betrachtet
2. die Delphipraxis version
showarea.png
showarea.png (440.17 KiB) 3261 mal betrachtet
3. BGRA
BGRA.png
BGRA.png (436.29 KiB) 3261 mal betrachtet
Mann kann schön sehen, Variante 1 und 2 nutzen im Prinzip einfach nur ein Stretchdraw das ein beliebiges 4-eck auf ein wieder beliebiges 4-eck mappt.

Variante 3 hingegen tut hier anscheinend mehr, denn hier wird bleibt der Abstand der Waagrechten über das gesammte Bild "fast" gleich => mit einem nachfolgenden Stretch könnte man so also die gewünschten Bildeigenschaften tatsächlich herstellen.
Wenn hier keine Mathe-Akrobatik veranstaltet werden soll,
Das stimmt so nicht, am liebsten würde ich die Mathematik dahinter Verstehen und den Algorithmus selbst nach programmieren.
=> ich werde nun also versuchen zu verstehen was BGRA da macht, freue mich aber auch über weitere Erläuterungen von hier.

Mein Buch ist mitlerweile auch da, dort schreiben die auch viel zu dem Thema, das muss ich nun also auch nur noch verstehen ;)
--
Just try it

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: Perspektifisches Entzerren eines Bildes

Beitrag von Winni »

Hallo!

Bevor Du dich in die Tiefen von BGRA versenkst:

Dort wird die affine Abbildung mit Hilfe von Matrizen benutzt.
Zum Einstieg:

https://de.wikipedia.org/wiki/Affine_Abbildung

Viel Spaß!

Winni

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Perspektifisches Entzerren eines Bildes

Beitrag von corpsman »

Das das über matrizen geht weis ich schon und freue mich drauf ;)

Procedure MulImage(Const Bitmap: TBitmap; Matrix: TMatrix3x3; Mode: TInterpolationMode = imBilinear);

hab ich schon und funktioniert 1a.

Für mich besteht die Aufgabe eigentlich nur noch aus den 8 Punkten die Matrix zu bestimmen. Laut diversen Papers geht das durch lösen eines GL's (und zum Glück habe ich auch einen Solver ;))

Das soll angeblich die Zielmatrix sein, ka warum a33 = 1, das muss ich auch noch raus finden. Und wie man das Gleichungssystem aufstellt, klar ist nur das das eine 9x8 matrix wird *g*

Code: Alles auswählen

//      (a11, a21, a31)
// m := (a12, a22, a32)
//      (a13, a23,   1)
--
Just try it

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

Re: Perspektifisches Entzerren eines Bildes

Beitrag von wp_xyz »

Mal ganz von vorne. Du bist im Ursprung des Koordinatensystems. In diesem Koordinatensystem zeigt x nach rechts, y ist die Blickrichtung, z ist die Vertikale nach oben. Vor dir liegt ein Blatt kariertes Papier, das sauber zum Koordinatensystem ausgerichtet ist. Das Blatt liegt im Abstand h unter dir (z=-h). Die Mitte des Blatts hat den Abstand y=dp von dir, und die horizontale Blattmitte liegt auf der y-Achse.

Ein Punkt auf dem Blatt soll durch ein eigenes Koordinatensystem (xp, yp) beschrieben werden; der Ursprung ist in Blatt-Mitte, xp zeigt nach rechts, so wie "dein" x, yp zeigt auf dem Blatt nach oben (so wie "dein" y, wenn das Blatt vor dir auf dem Tisch liegt).

Dann hat ein beliebiger Blatt-Punkt (xp, yp) in deinem Koordinatensystem (x,y,z) die Koordinaten x=xp, y = dp+yp, z=-h.

Nun zur Abbildung. Zwischen dir und dem Blatt steht ein senkrechter Projektionsschirm, entlang deiner x-z Ebene ausgerichtet. Die Koordinaten auf dem Projektionsschirm lauten (u, v), wobei u waagrecht und v senkrecht verlaufen. Der Abstand des Projektionsschirms zu dir ist ds.

Ein Lichtstrahl, der von einem Blatt-Punkt (x, y, z) ausgeht und dein Auge (im Ursprung) erreicht, schneidet den Projektionsschirm im Punkt (u,v). Das zeichnest du dir am besten hin, und da findest du mit Hilfe des Strahlensatz, dass

u = x * (y-ds)/y = x * (1-ds/y) = xs * (1 - ds/(dp+yp))

v = -h * (1-ds/y) = -h * (1 - ds/(dp+yp))

In Realität entspricht dem Projektionsschirm natürlich der Bildschirm mit eigenen Einheiten, Pixeln. Zur Umrechnung der "Welt-"Einheiten auf dem Projektionsschirm (mm, cm, o.ä.) nach Pixeln müssen u und v mit einem Faktor F mutlipliziert werden. Im Unterschied zum echten Bildschirm ist der Ursprung in der Bildschirmmitte anstatt links oben. Das kannst du so lassen, oder du musst noch folgende Korrekturen einbauen: zu u die halbe Bildschirmbreite addieren, zu v die halbe Bildschirmhöhe, sowie die Richtung umkehren, weil die vertikale Bildschirmkoordinaten nach unten läuft.

Insgesamt stecken in diesen Gleichungen vier Unbekannte:
h -- der vertikale Abstand zwischen Auge und Blatt Papier
dp -- der horizontale Abstand zwischen Auge und Blatt Papier
ds -- Abstand des Projektionsschirms vom Auge
F -- Skalierung zwischen Projektionsschirm und Monitor bzw. Foto.

Um diese zu bestimmen, musst du dir vier Punkte auf dem Blatt Papier aussuchen, ihre Koordinaten im "Papier-Koordinatensystem" und im Bildschirm-Koordinatensystem ablesen und in die Gleichungen einsetzen. Das Gleichungssystem umfasst vier Gleichungen und vier Unbekannte und sollte lösbar sein. Letztendlich kannst du dann damit berechnen, auf welches Pixel ein Objekt-Punkt abgebildet wird, und wenn du die Gleichungen invertierst, kannst du von Pixeln auf die Objekt-Koordinaten zurückrechnen.

Ich hoffe, dass mir oben kein Rechnen- und kein Schreibfehler unterlaufen ist. Das Grundprinzip sollte jedoch richtig sein.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Perspektifisches Entzerren eines Bildes

Beitrag von corpsman »

Also dann müsste die Skizze ungefähr so aussehen:
Skizze.png
Skizze.png (9.31 KiB) 3241 mal betrachtet
Leider hab ich heute keine Zeit mehr, aber ich schau mir das morgen noch mal genauer an, evtl. baue ich mir auch ein Modell.

Ich muss dann den Bildschirm am besten so platzieren dass 2 seiner Ecken direkt 2 Strahlen zu den Blatt Ecken berühren, oder ? ich will ja maximal viel des Blattes auf meinem Bild sehen...
--
Just try it

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

Re: Perspektifisches Entzerren eines Bildes

Beitrag von wp_xyz »

Du zeichnest die pinken Strahlen zu den Ecken des Blattes ein und das zeigt mir einen Fehler in meiner Rechnung. Ich war implizit davon ausgegangen, dass die Kamera parallel zur y-Achse gerichtet ist. So kann man das Blatt zwar auch fotografieren, aber es ist aber dann nicht mittig, und man wird in der Praxis die Kamera eher zur Blattmitte hin neigen, d.h. es kommt in die Rechnung noch ein Kamera-Koordinatensystem, das gegenüber der "Welt" um die x Achse nach unten gedreht ist. Äquivalent dazu ist wahrscheinlich eine Kippung der Projektionsfläche von der Kamera weg, so dass die Projektionsfläche senkrecht zur Blickrichtung der Kamera steht. Das macht die ganze Sache noch ein Stück komplizierter. Wahrscheinlich ist mein Ansatz im Detail zu kompliziert und zu speziell. Ich weiß nicht, was in deinem Buch steht, aber ich habe viel von den einführenden Kapiteln zu OpenGL gelernt.

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: Perspektifisches Entzerren eines Bildes

Beitrag von Winni »

Hi!

Dreidimensional kann man das natürlich auch machen.
Aber es verkompliziert dir Geschichte unnötig.

Wenn man sich auf zwei Dimensionen beschränkt und die Anordung der Punkte im Uhrzeigersinn
anordnet:

A B
D C

dann kann man die Lage der mittigen y- und x-Achse recht einfach berechnen:
My1 = Mitte von A und B
My2 = Mite von C und D
My1_My2 bilden die y-Achse

Mx1 = Mitte von Aund D
Mx2 = Mitte von B und C
Mx1_Mx2 bilden die x-Achse

Das Viereck ABCD zu einem passenden Rechteck in der Y-Richtung überführen.
Dann das Rechteck zu einem passenden Viereck (nicht: Rechteck) in der x-Rchtung überführen.

Matrizen helfen

Winni

Antworten