EAN-Strichcodes mit LabVIEW lesen

In diesem Beitrag erkläre ich die Funktionsweise von Strichcodes nach dem EAN-13 Standard und beschreibe einen Algorithmus, um diese mit LabVIEW zu lesen.

Strichcodes, oder englisch Barcodes, begegnen uns im Alltag ständig auf Produkten oder Verpackungen. Genauso alltäglich ist der Piepton an der Kasse, mit dem der Scanner einen erfolgreichen Lesevorgang quittiert. Einen solchen Scanner kann man sich mit einer Webcam und LabVIEW selbst herstellen.

Aufbau des EAN Codes

Es gibt verschiedene Barcode Standards, die festlegen, was die Strichkombination bedeutet. In Deutschland ist auf den meisten Produkten im Einzelhandel ein GTIN Code zu finden – den meisten Menschen jedoch unter seiner alten Bezeichnung EAN Code bekannt. EAN steht für European Article Number.

EAN-13 codiert eine dreizehnstellige Zahlenfolge in ein Strichmuster. Die Zahlenfolge ist meist unter dem Code angegeben, um sie bei Unleserlichkeit des Strichmusters manuell eingeben zu können.

 

2 Bereiche, getrennt durch Sonderzeichen

Ein EAN-Strichcode besteht aus einem Startzeichen (C1), dem linken Bereich, dem Trennzeichen (C2) in der Mitte des Codes, dem rechten Bereich und dem Endzeichen (C3). In jedem Bereich sind 6 Zahlen codiert.

Aufbau des EAN-Strichcodes

Ein Barcode besteht aus dem linken und rechten Bereich, getrennt vom Trennzeichen C2. Der Code ist eingerahmt von den Start- und Endzeichen C1 und C3.

4 Striche pro Zahl

Eine Zahl im EAN Code ist immer mit zwei schwarzen und zwei weißen Balken codiert. Im linken Bereich fängt eine Kombination immer weiß an, die Zahl ist also eine Weiß-Schwarz-Weiß-Schwarz (WSWS) Folge. Im rechten Bereich fängt jede Zahl mit einem schwarzen Strich an, was eine SWSW-Folge ergibt.

Die Information, um welche Zahl es sich handelt, liegt in der Breite der Striche. Der breiteste Strich ist viermal so breit wie der dünnste Strich – der sozusagen die Grundbreite definiert. Ein Strich im Code kann die Breiten 1, 2, 3 und 4 haben – bezogen auf die Grundbreite.

Damit jede Zahl im Barcode gleich breit ist, müssen die 4 Striche zusammen die Breite 7 haben.

Jeder Zahl von 0 bis 9 ist eine Breiten-Kombination zugeordnet. Die 1 hat zum Beispiel die Kombination 2221. Der erste, zweite und dritte Strich ist jeweils 2 breit, der vierte Strich hat die Breite 1 (also die Grundbreite). Eine Tabelle mit der Codierung der Zahlen entnehmen Sie bitte dem Wikipedia-Artikel zum EAN Code.

Wo steckt die 13. Zahl?

Um die Erklärung einfach zu halten, wurde oben geschrieben, dass linker und rechter Bereich des EAN Codes jeweils 6 Zahlen enthalten. Der Code enthält aber 13 Zahlen.

Für den linken Bereich des Codes gibt es für jede Zahl von 0 bis 9 zwei gültige Breite-Kombinationen. Also eine A-Kombination und eine B-Kombination. Meistens werden die beiden möglichen Kombinationen jedoch gerade und ungerade genannt.
Die Zahl 1 ist entweder als Breitefolge 2221 (ungerade) oder als 1222 (gerade) codiert. Die gerade Kombination ist immer die ungerade Version rückwärts gelesen.

Aus der Gerade/Ungerade-Verwendung der Zahlen des linken Bereichs läßt sich die 13. Zahl lesen. Jede Zahl ungerade codiert (uuuuuu) steht zum Beispiel für 0 und uguugg ist die Zahl 4.

Für den rechten Bereich im EAN-Code gibt es nur eine gültige – gerade genannte – Breite-Kombination pro Zahl. Diese entspricht der ungerade-Version der linken Seite.

Sonderzeichen C1, C2, C3

Die Sonderzeichen sind immer gleich. Die Code-Endmarkierungen C1 und C3 sind Schwarz-Weiß-Schwarz in den Breiten 111.
Das Bereichstrennzeichen C2 ist Weiß-Schwarz-Weiß-Schwarz-Weiß in den Breiten 11111.

Eine genauere Behandlung der Theorie des EAN-Barcodes würde den Umfang dieses Artikels sprengen. Daher möchte ich für eine detailliertere Darstellung auf den Wikipedia-Artikel European Article Number verweisen.

Bildaufbereitung

Technisch gesehen bestehen digitale Bilder aus einer Tabelle von Helligkeitswerten für die einzelnen Bildpunkte, den Pixeln. Um einen Barcode zu lesen, reicht eine einzige Zeile dieser Helligkeitswerttabelle. Welchen Wertebereich die Helligkeitswerte haben, hängt von der Definition des Bildformats ab.

Bild 2: Die Abbildung zeigt die Zusammensetzung eines Bilds mit 5 mal 5 Pixeln. In jedem Pixel ist der Helligkeitswert eingetragen, der zwischen 0 (Schwarz) und 255 (Weiß) liegen kann. Es ist ein Beispiel für ein 8bit Graustufenbild

LabVIEW stellt VIs bereit, um diverse Bildformate zu lesen. „PNG-Datei lesen“ gibt ein Cluster aus, dass unter anderem die Helligkeitswerte der Pixel enthält.

Für einen Menschen sind in Bild 2 zwei senkrechte dunkle Striche zu erkennen. Die Erkennung von Objekten, auch solchen, die man selbst im Bild deutlich sieht, in einem Algorithmus zu formulieren, ist nicht immer ganz einfach. Mangelhafte Kontraste, die Skalierung des Objekts und andere wechselnde Bedingungen müssen berücksichtigt werden.

Aus diesem Grund wird zunächst eine Bildaufbereitung durchgeführt, bevor mit dem Auswerten des Barcodes begonnen wird. Für das Lesen eines Schwarz-Weiß Strichmusters ist die Bildaufbereitung vergleichsweise simpel. Es reicht, eine Zeile aus der Bildmitte zu nehmen und diese in weiße und schwarze Abschnitte einzuteilen. Ein Bild mit nur 2 Farb- oder Helligkeitswerten ist ein binäres Bild. Das Ergebnis der Bildaufbereitung ist eine binäre Bildzeile mit den Werten 1 für Weiß und 0 für Schwarz.

Bild 3: Die Bildaufbereitung überführt die Bildzeile zu binären Werten.

Ein naheliegender Ansatz ist, eine Schwelle zu definieren, unterhalb derer alle Helligkeitswerte zu weißen Pixeln werden und darüber zu schwarzen. Unter gleichbleibenden Beleuchtungsbedingungen ist diese Vorgehensweise praktikabel. Variiert die Gesamthelligkeit im Bild, ist ein Teilbereich des Bilds beschattet oder ändert sich der Bereich der gültigen Helligkeitswerte, weil ein Bild  mit 16bit statt 8bit Farbtiefe verwendet wird, muss die Schwelle neu justiert werden.

Bild 4: Die Helligkeitswerte einer Bildzeile eines Barcodes als Graph dargestellt.

In Bild 4 ist gut zu erkennen, dass das Festlegen einer Schwelle für die Einteilung in Schwarz und Weiß Probleme bereiten würde, sobald sich die Werte geringfügig ändern.

Eine robustere Lösung ist, mit Helligkeitsdifferenzen benachbarter Pixel zu arbeiten. Die Differenzen der obigen Bildzeile sind 154, -187, 230, -217. Ein positiver Differenzwert ist offensichtlich ein Hell-Dunkel-Übergang und eine negative Differenz ein Dunkel-Hell-Übergang. Ist die Differenz klein, haben die benachbarten Pixel einen ähnlichen Helligkeitswert.

Bild 5 zeigt die Differenzen der Pixelwerte der gleichen Barcode-Zeile, die in Bild 4 als Helligkeitswerteverlauf zu sehen ist. In Bild 4 steigen die absoulten Helligkeitswerte im rechten Bereich an, in den Differenzen in Bild 5 ist dieser ungewollte Anstieg weggefallen. Weiterverarbeitet werden die lokalen Maxima und Minima der Differenzen. Steigt oder fällt der Helligkeitswert treppenförmig, entscheidet sich der Algorithmus also für die höchste Stufe.

Die Anzahl der Striche eines Barcodes ist bekannt und damit auch die Anzahl der Hell-Dunkel und Dunkel-Hell Übergänge. Der Algorithmus nimmt die jeweils 30 stärksten lokalen Maxima und Minima für die Bestimmung der Hell- und Dunkel-Bereiche. Ein Dunkelbereich, also ein Strich des Barcodes, liegt zwischen einem positiven lokalen Maximum und dem nächsten lokalen Minimum.

Bild 5: Der schwarze Graph zeigt die Differenz der Helligkeit von Pixel zu Pixel. Die roten Punkte zeigen die lokalen Differenz-Maxima und –Minima.

Das Ergebnis der Aufbereitung ist eine binäre Bildzeile, die in LabVIEW am einfachsten mit einem Boolschen-Array repräsentiert werden kann. Die erkannten Hell- und Dunkelbereiche können zur Veranschaulichung über das aufgenommen Bild gelegt werden, wie in Bild 6 zu sehen. Die binäre Bildzeile wird im Bild unten in verbreiterter Form in den Farben rot und grün dargestellt.

Bild 6: Bild eines Barcodes mit den vom Algorithmus erkannten Hell- und Dunkel-Bereichen, die rot und grün dargestellt werden. Darüberliegend alternierend in braun und türkis die jeweils eine Zahl bildendenden Striche.

Auswerten der Strichfolge mit LabVIEW

Die Auswertung der binären Bildzeile mit LabVIEW orientiert sich an der Definition des Barcodes. Sie soll unabhängig von der Pixelzahl der Zeile sein. Die Auswertung setzt folgende Bedingungen voraus:

  • Links und rechts neben dem Strichcode befinden sich Hellbereiche
  • Die binäre Bildzeile gibt den Barcode bis auf kleine Abweichungen korrekt wieder

Die wichtigste Information zur Auswertung des Strichmusters ist die Breite in Pixeln des dünnsten Striches, oben Grundbreite genannt. Zu Beginn und am Ende eine Barcodes befinden sich jeweils eine Schwarz-Weiß-Schwarz (SWS) Kombination mit Strichen mit der Grundbreite in den Zeichen C1 und C3. Außerdem befinden sich fünf Grundbreitenstriche als WSWSW Kombination in der Mitte des Codes im Trennzeichen C2.

Programmtechnisch leistet bei der Umsetzung die Funktion „1D-Array durchsuchen“ große Dienste. Sie durchsucht ein Array nach einem bestimmten Wert und gibt den Index der ersten Fundstelle aus. Um den Beginn des Barcodes zu bestimmen durchsucht man das Boolsche-Array aus der Bildaufbereitung  nach dem ersten True (True steht für ein schwarzes Pixel) und bekommt den Startindex des Barcodes. Dann sucht man ab dem gefundenen Startindex nach dem ersten False. Das Ergebnis dieser zweiten Suche ist der Endindex des ersten Striches. Zieht man den Startindex vom Endindex ab, erhält man die Strichbreite.

Zur sicheren Bestimmung der Grundbreite verlässt man sich nicht nur auf die Breite des ersten Strichs sondern bestimmt die breite aller oben genannten Bereiche mit der Grundbreite und verwendet deren Mittelwert.

Nachdem die Grundbreite bestimmt ist, berechnet man ab Ende des C1 Zeichens die Breite der folgenden WSWS Kombination. Hierfür wird wieder „1D-Array durchsuchen“ benutzt. Die gefundenen Pixelbreiten normalisiert man auf die anfangs bestimmte Grundbreite, indem durch die Grundbreite dividiert und auf die nächste Ganzzahl rundet. Die Normalisierung erlaubt es, Barcodes mit beliebiger Gesamtpixelbreite zu lesen, da sie von der absoluten Pixelzahl der Striche abstrahiert. Für den Barcode im Bild oben lauten die normalisierten Breiten der ersten WSWS Kombination von links 3-2-1-1. Das steht für die Zahl „0 ungerade“.

Dieser Vorgang wird für jede der ersten sechs Zahlen wiederholt. Aus der Gerade-Ungerade-Verteilung der ersten sechs Zahlen wird die 13. Zahl bestimmt.   Das Trennzeichen C2 in der Barcodemitte wird übersprungen. Anschließend werden wie die sechs Zahlen auf der rechten Seite des Codes auf die gleiche Art bestimmt. Einziger Unterschied auf der rechten Hälfte ist, dass es sich um SWSW Kombinationen handelt und es nur „gerade“ Zahlen gibt.

Quellcode und Beispielanwendung

Ich stelle hier eine Bibliothek mit dem VI „Barcode Reader“ zur Verfügung, das den LabVIEW Standard-Cluster „Image Data“ entgegen nimmt. Gelesen wird die Zeile genau in der Mitte des Bilds.

Barcode Reader, nur Bibliothek, für LabVIEW 2011

Alternativ kann ein LabVIEW 2011 Projekt mit der Bibliothek, einem Beispiel-VI und zwei Barcode-Bildern zum Ausprobieren geladen werden:

Barcode Reader inklusive Bibliothek, Beispiel-VI und Barcode-Bildern, für LabVIEW 2011

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.