QR Codes und Datamatrix
« | 22 May 2021 | »Bald kommen QR-Codes, die uns einen Impfstatus oder eine Testung bestätigen sollen.
Das ist doch der perfekte Zeitpunkt um diese beiden Bild-Kodierungen ins GATE Projekt aufzunehmen und mit ihnen zu experimentieren.
Neben den alt bekannten Artikel-Barcodes (Strichcodes), sind mir folgende optischen Datencodes in der Öffentlichkeit bekannt:
- QR-Codes sind diese Punkte-Quadrate, die an 3 Ecken ein umrandetes Quadrat
beinhalten.
Sie sind auf Plakaten und überall dort vertreten, wo man sie mit dem Smartphone abscannen kann und beinhalten häufig URLs für weitere Infos zu einem Produkt. - Data-Matrix-Codes sind wie
QR-Codes quadratisch und zeichnen sich durch durchgehende Linien an zwei
Achsen an den Rändern aus.
Sie sind als Bar-Code Ersatz gedacht und man findet sie (etwas versteckt) auf Geräten, wo sie häufig Seriennummern oder Adressen kodieren.
Beide Techniken können allerlei mögliche Formen von Bytes kodieren, auch Binärdaten. Und mit folgenden hilfreichen Bibliotheken kann man aus Pixel-Rastergrafiken (z.B. Bitmaps) Codes erkennen lassen:
libdmtx
Mit Data-Matrix-Codes (auch als 2D-Barcodes bekannt), habe ich schon vor ein
paar Jahren “experimentiert”. Die Bibliothek libdmtx
soll mir daher auch diesmal einen guten Dienst leisten, wenn es um das
Auslesen von Datamatrix Codes in Bildern geht.
Die Bibliothek ist für den Anwender recht einfach gestrickt und kann mit jedem möglichen Rasterbild-Format (RGB, RGBA, usw.) gefüttert werden.
DmtxImage* dmtx_image = dmtx_image = dmtxImageCreate(pixelptr, width, height, DmtxPack32bppRGBX);
Erzeugt ein Bildobjekt basierend auf den Eingabedaten, wobei es ein paar Optionen für Formate gibt.DmtxDecode* decoder = dmtxDecodeCreate(dmtx_image, 1);
Dann wird die Dekodierung für das Bild eingeleitet.DmtxRegion* region = dmtxRegionFindNext(decoder, NULL);
Nun sucht man eine gefundene Datamatrix-Region.DmtxMessage* message = dmtxDecodeMatrixRegion(decoder, region, DmtxUndefined);
Und dann liest man die Nachricht aus der Region heraus.message->output, message->outputSize
Auf die dekodierten Daten zeigt dann deroutput
Pointer und die Größe. steht inoutputSize
dmtxMessageDestroy(&message);
Freigeben des Message Objektes.dmtxRegionDestroy(®ion);
Freigeben des Region Objektes.dmtxDecodeDestroy(&decoder);
Freigeben des Dekoders.dmtxImageDestroy(&dmtx_image);
Freigeben der Bilddaten.
Viel einfacher geht es ja kaum und libdmtx
kann auch verdrehte Bilder
so lange herumtransformieren, bis eine Matrix entdeckt wurde. Man kann auch
ein Timeout angeben um zu lange Suchoperationen dann abbrechen zu lassen.
libquirc
Mit der quirc
Lib
haben wir eine C Bibliothek mit BSD Lizenz, die QR Codes dekodieren kann
und keine zusätzlichen Abhängigkeiten hat.
Bilddaten muss man für quirc
als Graustufen-Bytes übergeben.
struct quirc* qr = quirc_new();
Eine neue Dekoder-Sitzung wird gestartet.quirc_resize(qr, width, height);
Die Dimensionen des zu ladenden Bildes werden übergeben.gray_image = quirc_begin(qr, &width, &height);
Wir erhalten einen Pointer auf die internen Bild-Pixel.for(pixel : pixels) gray_image[offset] = gray(pixel);
Nun müssen alle Bild-Pixel befüllt werden.quirc_end(qr);
Das Aufnehmen der Bilddaten ist fertig und die Dekodierung startet.int num_codes = quirc_count(qr);
Die Anzahl der gefundenen QR-Codes wird abgefragt.for(int index = 0; index < num_codes; index++)
Wir gehen nun durch alle gefundenen QR-Bereiche durch:struct quirc_code code
;quirc_extract(qr, index, &code);
Es wird versucht einen QR-Code zu extrahieren.struct quirc_data data;
quirc_decode(&code, &data);
Die extrahierten Daten werden in Bytes dekodiert.data.payload, data.payload_len
Und durch einen Pointer zu den Daten und die Anzahl der Bytes kann der QR-Code Inhalt weiterverarbeitet werden
quirc_destroy(qr);
Am Ende wird die quirc-Sitzung beendet und alle Ressourcen werden freigegeben.
Auch hier ist das Ergebnis mit nur wenigen Zeilen Code zu erhalten.
Und es sind nur ein paar if
Statements erforderlich um nicht-erkennbare
Codes zu überspringen.
Fazit
Also ich bin echt beeindruckt.
Die Komplexität der Bildverarbeitung ist in einer Hand voll von Funktionen abgebildet, die nahezu selbstbeschreibend sind.
Mein Respekt geht an die Macher und ich habe die beiden Bibliotheken mit Freude ins GATE Projekt aufgenommen.
Nun kann ich in Verbindung mit meinen Video-Source-Routinen Bilder auf Webcams und anderen Kameras auf QR- und Datamatrix-Codes durchsuchen lassen. Und das klappt wirklich gut.
Das schwierigste ist meist, die Schärfeeinstellung der Webcams so hinzubekommen, dass ein gut lesbares Bild dabei herauskommt.
Daumen hoch für diese geniale Codebase.