Grafische Buchstaben erkennen

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Tommy
Spassvogel
Beiträge: 319
Registriert: 17.10.2013 14:36

Grafische Buchstaben erkennen

Beitrag von Tommy »

Guten Tag liebe Community,
ich habe ein Bild mit einem Schriftzug und möchte in PB so machen dass mein Tool in der Lage ist den Text zu erkennen und zu entziffern.
Wie stelle ich das am besten an? Muss ich Pixel für Pixel gehen und den Farbunterschied auswerten und erraten ob es ein Teil des Hintergrunds ist
oder der Textrand ist?

STARGÅTE, du kennst dich doch super mit Grafikzeugz aus oder? :) Kannst du mir Tips oder ein Beispielcode geben? Ich weiß leider nicht wie ich anfangen soll
und ob meine Vorgehensweise richtig ist also Pixel für Pixel und den Farbunterschied auswerten und so. Aber mein Tool muss bestimmt wissen wie die Buchstaben
aussehen. Oder muss man das Bild so verformen oder verzerren so dass man die Buchstaben systematisch besser auseinander halten kann? Nur wie?

Oder bin ich auf dem Holzweg? :|
PB 5.41 x64
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: Grafische Buchstaben erkennen

Beitrag von Kurzer »

Das ist ein sehr komplexes Thema, was vermutlich nicht so einfach in ein paar Zeilen erklärt ist. Es wird sicherlich auch viele verschiedene Herangehensweisen geben, die alle ihre Vor- und Nachteile haben.

Wenn ich (übrigens ohne Grundlagenwissen zu diesem Thema) so etwas angehen müsste (freiwillig würde ich mir das nicht antun), dann gäbe es mehrere Bearbeitungsschritte, die das Bild mit dem Text durchlaufen müsste.

Zuerst sollte man dafür sorgen, dass sich der Text sehr gut vom eigentlichen Hintergrund abhebt. Also quasi als Grundvoraussetzung. Selbst heutige Hochleistungsalgorithmen zur Texterkennung werden jämmerlich versagen, wenn Text und Hintergrund irgend ein kontrastloses Gemansche darstellen.

So nicht:
Bild

Wenn man den Text dann durch Kontrast- oder Gammakorrektur oder anderweitige Maskierung dann mehr oder weniger sauber freigestellt hat, dann sollte man die Farbinformationen eliminieren und den Text als schwarz/weiß Grafik vorliegen haben.

Danach sollte man erkennen in welchem Bereich sich der Text befindet und, ob die Vorlage korrekt horizontal ausgerichtet ist. Falls nötig muss das gesamte Bild dann um den entsprechenden Betrag gedreht werden, damit die einzelnen Sätze des Textes exakt horizontal ausgerichtet sind, weil die nachfolgende Erkennung sonst nicht funktioniert.

Bild

Im nächsten Schritt würde ich versuchen den Raum zu erkennen, den die einzelnen Sätze einnehmen. Also so, dass man später mehrere rechteckige Bereiche untereinander definiert hat, von denen man weiß, dass sich darin jeweils genau ein Satz mit mehreren Wörtern befindet (siehe unten rot).

Der nächste Schritt müsste dann in jedem dieser Rechtecke (= Sätze) versuchen die einzelnen Wörter voneinander zu trennen, so dass das Programm genau weiß von welcher X1 Position bis zu welcher X2 Position innerhalb des Rechtecks sich ein Wort befindet (siehe unten blau). Die genauen Algorithmen hierfür kann ich nicht aus der Hand schütteln. Das ist wie gesagt sicherlich nicht ganz trivial. In dem Fall hier kann man versuchen die Lücken ohne Pixel zwischen den Worten zu erkennen und dann mit einer gewissen Toleranz festlegen was das Ende eines Wortes ist.

Danach geht man weiter ins Detail und isoliert auf die gleiche Weise die einzelnen Buchstaben voneinander, so dass das Programm weiß welchen Raum ein einzelner Buchstabe in einem Wort einnimmt (siehe unten grün).

Ungefähr so:
Bild

Jetzt weiß das Programm wo welcher Buchstabe liegt und welche Dimension dieser einnimmt.

Zur Erkennung eines Buchstabens brauchst Du dann ein System, das Muster unabhängig von der Größe der Buchstaben erkennen kann. Es nütz Dir ja nichts, wenn Du einfach nur ein festes Bitmuster erkennen kannst, bei dem jeder Buchstabe z.B. genau 20 x 40 Pixel groß sein muss.

Ohne es jemals versucht zu haben, würde ich es so angehen:
Das Rechteck eines Buchstaben würde ich z.B. in 25 Reihen und 25 Spalten einteilen

Hier mal angedeutet:
Bild

Dann geht man das Raster durch und "markiert" jedes Feld, das Teil des Buchstabens ist. Hier mit den Kreisen angedeutet. Dein Programm muss für jeden zu erkennenden Buchstaben eine Art "Vergleichstabelle" haben, die alle Felder enthält, die für den jeweiligen Buchstaben gesetzt sind (also Teil des Buchstabens sind).

Für jede Zeile muss man also anhand der markierten Felder vergleichen mit welchen Buchstaben aus der Vergleichstabelle diese Zeile am ehesten übereinstimmt. Die x besten Übereinstimmungen notiert man sich dann pro Zeile.

Mal ein vereinfachtes Beispiel für das "A":
Rechts neben den Zeilen stehen die Buchstaben, bei denen die Zeile ähnlich aussieht. Von links nach Rechts mit abnehmender Trefferquote.

Code: Alles auswählen

.###.    A, T, C
#...#    H, A, B
#####    H, A, B, S
#...#    H, A, B
#...#    H, A, B
Dann geht man hin und ermittelt für jede Zeile die x besten Treffer und zieht daraus dann den Gewinner.
Wenn wir die 3 besten Treffer nehmen, dann haben wir hier also:

A = 5x (ist nämlich in jeder Zeile vorhanden)
H = 4x (ist in der ersten Zeile nicht vorhanden)
B = 4x (ist in der ersten Zeile nicht vorhanden)

Der Buchstabe mit der höchsten Trefferquote ist also das A.

Das ist natürlich alles nur sehr stark vereinfacht und das Prinzip, das ich hier beschrieben habe wird bei unterschiedlichen Ausführungen von gleichen Buchstaben jämmerlich versagen (Z.B. Serif und Sans Serif Schriften)...

Bild

...aber ich wollte es nur grob verdeutlichen, dass da ein bisschen mehr dran hängt, als man evtl. gedacht hat.

Man kann die Buchstaben sicherlich auch vertorisieren und dann die Ähnlichkeit der Vectorpfade vergleichen (Winkel, Steigungen, Längenverhältnisse etc.), aber das ist nichts worin ich mich auskenne.

Im nächsten Schritt, wenn dann also die Buchstaben und die Worte "erkannt" worden sind, kommen am besten noch Abgleiche mit einem Wörterbuch dran, um ein oder zwei falsch erkannte Buchstaben in einem Wort auf diese Weise korrigieren zu können.

Möglicherweise wurde durch ein paar unsaubere Pixel im Bild aus einem O ein Ö und es wurde "Sönne" statt "Sonne" erkannt. Das kann mit einem Wörterbuch und Ähnlichkeitsvergleich korrigiert werden.

Wer es drauf hat, kann dann noch eine Inhaltsprüfung programmieren, die erkennt, ob bestimmte Satzzusammenstellungen überhaupt gültig sind. Beispiel: "Des Ball springt". Alle Worte sind korrekt, aber der Satz ist falsch, weil statt des Wortes "Der" das Wort "Des" erkannt wurde.

Na ja, das nur mal als Gedankenanstoss von mir. Ich würde es nicht programmieren wollen. :-)
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2024: 56 Jahre.
Benutzeravatar
Tommy
Spassvogel
Beiträge: 319
Registriert: 17.10.2013 14:36

Re: Grafische Buchstaben erkennen

Beitrag von Tommy »

Wow hammer geil, danke Kurzer für den sehr ausführlichen und informativen Beitrag.
Scheint wirklich komplexer zu sein als ich dachte. Danke für die nützlichen Tips!!! :)
PB 5.41 x64
Derren
Beiträge: 557
Registriert: 23.07.2011 02:08

Re: Grafische Buchstaben erkennen

Beitrag von Derren »

Das mit den verschiedenen Schriftarten bringt mich auf eine andere Idee.
Mal davon ausgehend, dass der Text unifont ist, also nicht zwischendrin die Schriftart wechselt und kein riesiges Initial hat.
Des weiteren gehe ich davon aus, dass die Grafik bereits korrigiert wurde. Also Schwarz/Weiß und horizontal, wie Kurzer es bereits erwähnt hat.

Jetzt würde könnte man sich den ersten Buchstaben raussuchen (zB. mit der Abstands-Bewertung, wie von Kurzer beschrieben).
Diesen Buchstaben messe ich ab. Also maximale Höhe und Breite in Pixel.
Ideal wäre es, wenn man dn Buchstaben auch schon kennt, z.B. mit der von Kurzer beschriebenen Methode.

Dann würde ich Schriftarten des Systems laden und diesen Buchstaben schreiben, in der korrekten Größe (ich brauche also eine Art Korrespondenztabelle vorher. z.B. "A" in Arial 8 ist h Pixel hoch und b Pixel breit).
Diesen Buchstaben schreibe ich in einer Grafik und überlagere die gescannte Grafik mit der erstellten. Wenn ich den Buchstaben noch nicht kenne, kann ich mit einer Standardschrift (z.B. Arial und Times) erstmal alle Buchstaben durchlaufen, überlagern und den ähnlichsten auswählen.

Nach diesem relativ großen Aufwand sollte ich also eine passende Schrift und Schriftgröße herausgefunden haben. z.B. eben Arial, 8.
Dann wähle ich den nächsten Buchstaben aus. Anhand der Höhe und Breite (hauptsächlich Höhe kann ich einige Buchstaben schonmal ausschließen. z.B. brauche ich bei einer Höhe von 0.5 Max, keine Großbuchstaben ausprobieren etc...

Also Text von einem Screenshot, z.B. einer Anwendung sollte man so, mit relativ geringen Zusatzkenntnissen meistern können, da z.B. das Windows-eigene Antialising nahezu identische Buchstaben erzeugen sollte.
Signatur und so
Antworten