Titelbild zum Artikel „Vom Kamerabild zum Text: wie ein Scanner dekodiert“
Technologie

Vom Kamerabild zum Text: wie ein Scanner dekodiert

6 Min. Lesezeit
QR-Code erstellen

Halten Sie in einem dämmrigen Gasthaus das Telefon über die Rechnung, schräg, mit einem Schatten quer über der halben Fläche, und der Link erscheint trotzdem in etwa einer Sekunde. Die Kamera hat kein klares Raster aus schwarzen und weißen Quadraten gesehen. Sie hat ein graues Trapez mit einem Helligkeitsverlauf und einer ordentlichen Portion Sensorrauschen gesehen.

Zwischen diesem Bild und der URL auf Ihrem Display liegen mehrere getrennte Stufen, von denen jede still scheitern kann. Die meisten Kamera-Apps führen den gesamten Dekodierversuch auf jedem Einzelbild in Videorate aus und verwerfen die, die nicht aufgehen, weshalb ein grenzwertiger Code einen Moment zu überlegen scheint, bevor er greift. Er überlegt nicht. Er scheitert wiederholt und versucht es erneut, bis ein Einzelbild zufällig gut genug ist.

Das heißt auch: Alles, was das Einzelbild verschlechtert, verschlechtert alles Nachgelagerte: Bewegungsunschärfe, eine verschmierte Linse, ein Autofokus, der pumpt. Ein unscharfer Code scheitert nicht am Ende des Vorgangs. Er scheitert, bevor der Vorgang beginnt.

Binarisierung: entscheiden, welche Pixel als dunkel gelten

Der Decoder muss jedes Pixel in einen von zwei Töpfen sortieren. Der naive Ansatz wählt einen einzigen Helligkeitswert fürs ganze Bild und trennt dort, was im Labor funktioniert und auf einem echten Tisch auseinanderfällt, wo eine Lampe links die linke Seite des Codes heller macht als das weiße Papier rechts.

Also arbeiten Decoder in der Regel mit lokalen Schwellenwerten. Das Bild wird in kleine Bereiche geteilt und jeder Bereich bekommt seine eigene Grenze, abgeleitet aus der Helligkeit ringsum. Ein Schatten über dem Symbol spielt dann keine Rolle mehr, weil die Module im Schatten immer noch dunkler sind als ihre unmittelbaren Nachbarn.

Auf dieser Stufe passieren auch die Farbfehler. Der Farbton wird hier verworfen. Was überlebt, ist die relative Helligkeit, und deshalb können zwei Farben, die für einen Menschen auffällig verschieden aussehen, im selben Topf landen und einen Code ergeben, der nie scannt.

Drei Ecken geben dem Decoder seine Orientierung

Als Nächstes kommt die Suche nach den Suchmustern, den drei verschachtelten Quadraten in den Ecken. Sie sind auffindbar, weil eine Linie durch eines von ihnen in beliebiger Richtung dunkle und helle Abschnitte im Verhältnis 1:1:3:1:1 kreuzt. Der Decoder kann Zeilen des binarisierten Bildes nach dieser Signatur abfahren, ohne zu wissen, wo der Code ist, wie groß er ist oder wie er gedreht liegt.

Drei Ecken, nicht vier. Die leere vierte Ecke ist das, was dem Decoder sagt, wo oben ist. Größere Symbole tragen zusätzlich kleinere Ausrichtungsquadrate über das Raster verteilt, die als weitere Bezugspunkte dienen, wenn die Fläche sich wölbt oder das Foto stark verzerrt ist. Die strukturelle Seite davon behandelt wie QR-Codes funktionieren.

Ein Foto zurück in ein quadratisches Raster verwandeln

Fast niemand scannt einen Code frontal. Die Suchmuster liefern bekannte Bezugspunkte, und daraus berechnet der Decoder eine perspektivische Transformation: die Abbildung, die das fotografierte Viereck zurück in ein Quadrat verwandeln würde. Wenden Sie sie an, und die Verzerrung ist weg.

Dann braucht der Decoder die Modulanzahl. Die Taktmuster, abwechselnd dunkle und helle Abschnitte zwischen den Suchmustern, lassen ihn zählen. Mit aufgelöstem Raster tastet er die Mitte jeder Zelle ab und hält endlich das, was sich alle von Anfang an vorgestellt hatten: eine Matrix aus Einsen und Nullen.

Die Formatbits beschreiben, wie der Rest zu lesen ist

Neben den Suchmustern sitzt ein kleiner Block Formatinformation. Er trägt zwei Dinge, ohne die der Decoder nicht weiterkommt: die verwendete Fehlerkorrekturstufe (L, M, Q oder H) und welches Maskenmuster bei der Erzeugung angewendet wurde.

Diesen Block zu verlieren würde das gesamte Symbol unlesbar machen, also wird er an zwei getrennten Stellen geschrieben und trägt eine eigene Fehlerkorrektur. Es ist der am stärksten verteidigte Bereich des Codes.

Entmaskieren und die Codewörter zurück in Reihenfolge bringen

Encoder schreiben Daten nicht direkt ins Raster. Zuerst wird ein Maskenmuster per XOR über den Datenbereich gelegt, ausgewählt, um große geschlossene Flächen aufzubrechen und zu vermeiden, dass zufällig etwas entsteht, das einem Suchmuster ähnelt. Gleichmäßige Mischungen aus Dunkel und Hell lassen sich zuverlässiger schwellen, Maskierung ist also ein Merkmal der Lesbarkeit und keine Verschleierung. Der Decoder rechnet dasselbe Muster per XOR wieder heraus.

Dann läuft er die Module in der festgelegten Zickzackfolge ab, gruppiert die Bits zu Acht-Bit-Codewörtern und entflicht sie. Die Verflechtung zählt mehr, als sie klingt. In größeren Symbolen werden die Daten in Blöcke geteilt und diese Blöcke über das Raster verwoben, sodass ein Kaffeering, der eine physische Fläche auslöscht, aus jedem Block ein paar Codewörter nimmt, statt einen Block vollständig zu vernichten. Der Schaden wird absichtlich dünn verteilt.

Reed-Solomon, ohne die Algebra

Nun die Reparatur selbst. Neben den Codewörtern mit Ihren Daten hat der Encoder zusätzliche gespeichert, die daraus berechnet wurden, und das brauchbare Bild dazu ist ein Gleichungssystem. Sie haben mehr Gleichungen als Unbekannte, können also mehrere verlieren und trotzdem jeden Wert bestimmen, auch die, die nie ankamen.

Genau das tut der Decoder ungefähr. Er prüft, ob die empfangenen Codewörter mit der Redundanz zusammenpassen. Wenn ja, ist er fertig. Wenn nicht, ermittelt er, wo die Verfälschung sitzt und welche Ursprungswerte es gewesen sein müssen, damit wieder alles aufgeht. Zwei Schadensarten existieren, und sie kosten unterschiedlich: Ein Codewort, von dem der Decoder bereits weiß, dass es fehlt, ist billig zu reparieren, während ein vorhandenes, aber falsches Codewort rund doppelt so teuer ist, weil auch seine Position bestimmt werden muss.

Die vier Stufen legen fest, wie viel Redundanz vorhanden ist, ungefähr sieben, fünfzehn, fünfundzwanzig und dreißig Prozent wiederherstellbarer Codewörter bei L, M, Q und H. Das sind Obergrenzen für das gesamte Symbol, und sie werden mit jeder anderen Schadensquelle geteilt: Druckfehler, Kratzer, Blendung, ein Daumen, ein Logo. Nichts wird reserviert.

Jenseits der Korrekturgrenze gibt es kein sanftes Nachlassen. Der Decoder rekonstruiert die Daten exakt oder meldet Fehlschlag. Ein Code, der scannt, ist bitgenau korrekt, und deshalb funktioniert ein halb abgeriebener Aufkleber tadellos, bis er gar nicht mehr funktioniert. Die meisten Gründe, warum ein Code nicht mehr scannt, führen zu den früheren Stufen zurück und nicht zu dieser, denn hinter Binarisierung und Suchmustererkennung steht keine Fehlerkorrektur.

Was davon im Prüfbericht landet

Diese Schritte sind nicht nur Theorie, sie sind die Grundlage der Druckprüfung. Nach ISO/IEC 15415 wird ein gedrucktes 2D-Symbol in Einzelkriterien bewertet und erhält daraus eine Gesamtnote von A bis F. In der Zuliefererkette für Pharma, Automobil und Medizintechnik liefert der Etikettenlieferant genau diesen Prüfbericht mit, und wer eine Druckerei mit Prüfgerät beauftragt, kann die Note verlangen statt der Auskunft, es sehe gut aus.

Die Kriterien lassen sich den Schritten oben direkt zuordnen. Symbolkontrast und Modulation gehören zur Binarisierung, also zur Frage, ob sich dunkel und hell überhaupt trennen lassen. Die Bewertung der festen Muster gehört zu den drei Ecken und zur Taktlinie. Achsabweichung und Rasterunregelmäßigkeit gehören zur Rückrechnung des Trapezes in ein Quadrat. Und das nützlichste Einzelkriterium heißt unbenutzte Fehlerkorrektur: Es sagt, wie viel Reserve nach dem Lesen übrig war. Ein Symbol, das die Note A bekommt, aber fast seine gesamte Fehlerkorrektur verbraucht, ist ein Symbol kurz vor der Grenze, und im nächsten Druckdurchgang mit etwas anderem Papier ist es darüber.

Für den Alltag folgt daraus eine Frage, die viel Zeit spart. Das Dekodieren passiert im Gerät, ohne Netz. Wenn also jemand sagt, der Code gehe nicht, lautet die erste Rückfrage: Ist der Link erschienen oder nicht? Erschien er und die Seite lud nicht, ist es ein Empfangsproblem, im Funkloch oder im überfüllten Gäste-WLAN. Erschien er nicht, ist es ein Problem des Symbols oder der Umgebung. Zwei verschiedene Fehler, zwei verschiedene Zuständigkeiten.

Alles davon passiert auf dem Gerät

Jeder hier beschriebene Schritt ist Arithmetik, lokal ausgeführt auf Pixeln, die das Telefon schon hat. Kein Nachschlagen, kein Server, kein Hin und Zurück. Ein Scanner dekodiert im Flugmodus, weil es nichts abzurufen gibt: Der Text steckt im Muster, und die Rechnung, um ihn zurückzugewinnen, läuft in wenigen Millisekunden auf Hardware, die Sie in der Hand halten.

Was der Code enthält und was der Code dann tut, sind getrennte Fragen, und die zweite wird in was beim Scannen passiert behandelt.

Diesen Artikel teilen