5.29. Streckkoder och Data Matrix-koder

Ytterligare två kodfamiljer kompletterar kamerans avkodare. Endimensionella streckkoder – ränderna på sidan av en flingpaket, ett sjukhusarmband, en fraktetikett – är de äldsta maskinläsbara symbolerna som fortfarande används dagligen. Data Matrix-koder är tvådimensionella likt QR-koder, men tätare vid samma nyttolaststorlek och riktade mot industriell märkning – tillverkarmärket laseretsat på ett kretskort snarare än affischen på en vägg. Modulen image har en dedikerad avkodare för var och en, och täcker de industriella, detaljhandels- och lagerapplikationer som de tvådimensionella konsumentkoderna aldrig riktigt nådde.

5.29.1. 1D-streckkoder

En endimensionell streckkod kodar sin nyttolast som en sekvens av vertikala streck med varierande bredd, läst från vänster till höger (eller uppifrån och ned för vertikalt orienterade koder). Bredderna kvantiseras till ett av en liten uppsättning värden, och sekvensen av bredder stavar ut tecken i vilken symbologi tryckaren än valde: numerisk för en UPC-produktkod, alfanumerisk för ett lagerartikelnummer, eller godtycklig text för en Code 128-etikett.

find_barcodes() söker av bildrutan efter 1D-streckkoder i någon av de stödda symbologierna och returnerar en lista med resultatobjekt av typen BarCode:

codes = img.find_barcodes()

for c in codes:
    img.draw_rectangle(c.rect, color=(0, 255, 0))
    print(c.payload, c.type, c.quality)

Avkodaren söker av bildrutan både horisontellt och vertikalt i ett enda anrop, så en streckkod tryckt i valfri vinkel hittas i en passning utan att applikationen behöver rotera indata. roi begränsar sökningen; inga andra justeringsparametrar finns – avkodaren är fristående.

De stödda symbologierna täcker de vanliga konsument- och industrifamiljerna. Detaljhandelsuppsättningen är image.EAN2, image.EAN5, image.EAN8, image.UPCE, image.UPCA, image.EAN13 (de numeriska koderna med fast längd på de flesta konsumentförpackningar), image.ISBN10 och image.ISBN13 (samma familjer omfunktionerade för böcker). Den allmänna uppsättningen är image.I25 (Interleaved 2 of 5, vanlig på fraktetiketter), image.CODABAR (används i bibliotek och blodbanker), image.CODE39, image.CODE93 och image.CODE128 (alfanumeriska symbologier med variabel längd för godtycklig text). Hyllkantsfamiljen image.DATABAR (RSS-14) och image.DATABAR_EXP (RSS-Expanded) kompletterar listan.

Varje detektering bär med sig begränsningsrutans vokabulär – x, y, w, h, rect, corners – och den avkodade payload som en sträng. type är symbologikonstanten från listan ovan, vilken en applikation kontrollerar när den specifikt bryr sig om vilken familj som avkodades (t.ex. att endast acceptera EAN13 för en livsmedelsscannerapplikation).

De två fält som spelar roll för filtrering är rotation och quality. rotation är streckkodens vinkel i bildplanet i radianer: avkodaren klarar av godtyckliga rotationer, men efterföljande kod som vill visa detekteringen snyggt kan vilja filtrera bort koder som kommer tillbaka lutade förbi något tröskelvärde.

quality är avkodningsantalet: antalet skannlinjer som framgångsrikt avkodade samma nyttolast. Avkodaren körs över varje rad (och kolumn) i bildrutan som skär streckkoden, och ökar räknaren varje gång avkodningen lyckas. En tryckt streckkod i skarpt fokus och bra belysning ger en quality i tiotal; en delvis skymd eller utsmetad streckkod kan avkodas på bara en eller två skannlinjer och rapportera quality på 1 – 2. Att filtrera bort detekteringar under quality > 5 förkastar tillfälliga felavkodningar på enskilda skannlinjer utan kostnad för de äkta detekteringarna.

En 1D-streckkodsapplikation är liten. Fånga en bildruta, anropa find_barcodes(), iterera över den returnerade listan, filtrera på c.type och c.quality, och vidarebefordra c.payload över UART eller USB till vilket efterföljande steg som än loggar eller registrerar skanningen.

5.29.2. Data Matrix

En Data Matrix-kod är en 2D-symbol som kodar sin nyttolast som ett rutnät av svarta och vita celler, på samma sätt som en QR-kod gör. Den skiljer sig från en QR-kod i två praktiska avseenden: den är mindre vid samma nyttolaststorlek (kodningen är tätare) och den är riktad mot industriell användning snarare än konsumentanvändning (där QR-koder dominerar). Mönstren laseretsade i metalldelar på en fabriksgolv, etiketterna tryckta på kretskretskapslar, märkena placerade på medicinska sprutor – alla dessa är typiskt Data Matrix-koder, inte QR-koder.

find_datamatrices() söker av bildrutan efter Data Matrix-koder och returnerar en lista med resultatobjekt av typen DataMatrix:

codes = img.find_datamatrices()

for c in codes:
    img.draw_rectangle(c.rect, color=(0, 255, 0))
    print(c.payload, c.rows, c.columns)

roi begränsar sökningen på vanligt sätt. Den enda avkodarspecifika justeringsratten är effort, ett heltal som styr hur hårt avkodaren arbetar för att hitta en matchning. Högre värden förbättrar detekteringen av svaga, skadade eller sneda koder till priset av bildfrekvens; lägre värden körs snabbare men kan missa koder som den högre ansträngningen skulle ha hittat. Värden under cirka 160 misslyckas i praktiken med att detektera; värden över cirka 240 ger avtagande utbyte. Standardvärdet 200 är en rimlig balans för en tydlig bild, och rätt utgångspunkt för en ny applikation är standardvärdet plus eller minus 20 beroende på om målen är rena (lägre) eller slitna (högre).

Varje detektering bär med sig begränsningsrutans vokabulär och de fyra detekterade hörnen, den avkodade payload och rotation i bildplanet i radianer. Layoutmetadatan beskriver storleken och tätheten på den symbol avkodaren läste: rows och columns är cellantalen i datarutnätet; capacity är det maximala antalet nyttolasttecken symbolen kunde bära vid den storleken; padding är hur många av dessa platser som blev oanvända (capacity - len(payload)).

Layoutfälten är användbara för applikationer som behöver validera formatet på ett etsat märke snarare än dess innehåll. Ett spårningssystem för delar kan kräva att alla märken ska vara 12-gånger-12-koder med högst två utfyllnadstecken; en detektering som kom tillbaka som 8-gånger-8 (en mindre symbol än specifikationen kräver) eller med 10 utfyllnadstecken (mestadels tom) flaggas för ommärkning.

5.29.3. När man ska välja vilken

Där QR kontra AprilTag handlade om typen av nyttolast (godtyckliga data kontra litet ID), handlar streckkoder kontra Data Matrix-koder om fysisk täthet och bransch.

När applikationen är konsumentinriktad och koderna redan finns ute i fält – livsmedel, böcker, fraktetiketter, biblioteksböcker – är rätt detektor find_barcodes(). Koderna applikationen läser trycktes för att ett annat system skulle läsa dem, och de standardiserade detaljhandelssymbologierna är vad det systemet förväntade sig.

När applikationen är industriell och koderna trycks för applikationen – lagerspårning på ett fabriksgolv, partikoder etsade på delar, spårbarhetsmärken på medicinteknisk utrustning – är rätt detektor find_datamatrices() eller find_qrcodes(), beroende på om applikationen behöver Data Matrix högre täthet eller QR bredare verktygsstöd.

En handfull applikationer blandar alla fyra detektorer i en pipeline. En kamera för paketinspektion kan köra en passning med find_barcodes() för den tryckta UPC-koden, en passning med find_qrcodes() för en frakt-QR-kod på samma kartong, och en passning med find_datamatrices() för en etsad delkod, allt på samma infångade bildruta; de tre resultatlistorna korreleras efter begränsningsrutans position och rapporteras som en enda detekteringspost. Varje detektors kostnad adderas, så applikationer som gör detta begränsar typiskt varje passning med en lämplig roi snarare än att söka i hela bildrutan efter varje typ av kod.