Java Verzerrtes Foto einer Buchseite entzerren

CPU

Lieutenant
Registriert
Jan. 2006
Beiträge
704
Hallo,

ich wollte mir einen kleinen Scanner mit meiner Digitalkamera bauen. Dazu habe ich mir überlegt, dass die Kamera einfach über der A4-Seite platziert wird. Da das Bild verzerrt ist, muss ich diese Verzerrung noch herausrechnen (ähnlich einem Buchscanner). Der aktuelle Stand wird von diesem Bild gut ausgedrückt:

result.jpg

Ich kann jetzt die Eckpunkte der A4-Seite automatisch identifizieren (grüne Pünktchen). Nun dachte ich, dass der schwierige Teil beendet ist. Denn ich kann mir ja die Breite und Höhe des fertigen, "flachen" Bildes ausrechnen (einfach die Distanz) ein neues Bild erzeugen mit diesen Maßen und jeden grünen Eckpunkt einfach in die entsprechende Ecke des erzeugten Bildes transformieren. Dann müsste ich laut Theorie ja die flache Seite haben. Allerdings scheint das nicht zu funktionieren. Ich habe jetzt den gesamten Nachmittag mit PerspectiveFilter von JHLabs herumgespielt - aber ohne Erfolg. Da muss man angeben, wohin die alten Bildecken transformiert werden (also die Ecken von dem angehangenen Bild) und das bekomme ich nicht hin, weil ich ja nur die Positionen der grünen Ecken kenne.

Für Linux gibt's auch kein Kommandozeilentool, das das kann und die grafische Software (unpaper, scantailor) löst mein Problem auch nicht. Und eine einfache Rotation hilft auch nicht weiter ...

Hat jemand eine Idee, wie ich ansonsten die A4-Seite korrekt transformiert bekomme? Eigentlich müssen die Eckpunkte nur in die Ecken der Grafik verschoben werden. Wenn die Grafik dann das richtige Seitenverhältnis hat bin ich fertig. Aber das bekomme ich nicht hin ...

Viele Grüße,
CPU
 
Habe zwar wenig Ahnung von Java, kann also nicht mit Code behilflich sein, habe aber eine Vermutung:
Falls die Kamera deckungsgleich zur Tischoberfläche ist könntest du die Winkel zwischen den Kanten ausrechnen und, falls sie nicht 90° betragen, auf 90° "zurückverzerren", in der Annahme, dass du verzerrte Bilder in korrektes rechteckiges Format bringen willst.
Dann, nennen wir die Eckpunkte mal A,B,C und D, wobei A oben links ist im Uhrzeigersinn nummeriert wird, könntest du den Winkel zw. der Strecke AB und der Oberkante des gesamten Bildes berechnen. Ist dieser 0°, so ist das Blatt hochkant, ist der Winkel a°, so ist das Blatt a° nach rechts verdreht, du müsstest das Bild also um -a° verdrehen um es wieder hochkant zu haben.
Danach muss Punkt A auf Koordinatenpunkt 0/0 verschoben werden um das Blatt in der linken oberen Ecke zu haben, danach alles was rechts von B und unter C und D ist entfernen.
Keine Ahnung ob das schon völlig klar war oder ich damit etwas helfen konnte.
 
Zuletzt bearbeitet:
Hallo,

promashup schrieb:
Habe zwar wenig Ahnung von Java, kann also nicht mit Code behilflich sein, habe aber eine Vermutung:
macht nichts, es geht ja nur um die Mathematik :-)

promashup schrieb:
[...] du müsstest das Bild also um -a° verdrehen um es wieder hochkant zu haben.
Danach muss Punkt A auf Koordinatenpunkt 0/0 verschoben werden um das Blatt in der linken oberen Ecke zu haben, danach alles was rechts von B und unter C und D ist entfernen./QUOTE]
Habe ich gemacht:

neu.jpg

Allerdings ist das Foto verzerrt, so dass es nicht ausreichend ist, nur zu rotieren und zu verschieben. Ich stelle mir das eher so vor:

neu1.jpg

Und das Ergebnis kann sich sehen lassen. Hier ist es zwar kaum lesbar, das liegt aber daran, dass ich das (a) per Hand gefummelt habe, (b) ungenaue Zwischenformate gewählt habe, (c) Java nicht im feinsten Modus gerendert hat. Trotzdem finde ich das Ergebnis sehr gut. Mein Problem ist jetzt nur noch, wie ich Schritt 2 in Java nachbilden kann. Das ist mir noch unklar. Kann mir da jemand helfen?

Viele Grüße,
CPU
Ergänzung ()

So, ich habe diesen SO-Beitrag gefunden, wo jemand genau das versucht, was ich machen will. Ich habe das mal durchgerechnet (auf Papier) und finde das verständlich.

Nur noch eine Java-spezifische Frage: wie kann ich ein BufferedImage mit einer 3x3-Matrix transformieren, wo ich die Elemente frei vergeben kann?

Viele Grüße,
CPU
 
Du kannst Dir mal opencv anschauen. Das ist eine freie Bildverarbeitungsbibliothek die auch in Java verwendet werden kann. Damit sollte sowas machbar sein.

Hier hab ich noch eine ähnliche Anwendung gefunden *klick*
 
Zurück
Oben