5.29. Codes-barres et codes Data Matrix¶
Deux autres familles de codes complètent les décodeurs de la caméra. Les codes-barres unidimensionnels – les rayures sur le côté d’une boîte de céréales, un bracelet d’hôpital, une étiquette d’expédition – sont les plus anciens symboles lisibles par machine encore utilisés au quotidien. Les codes Data Matrix sont bidimensionnels comme les codes QR, mais plus denses à charge utile équivalente et destinés au marquage industriel – la marque de fabrication gravée au laser sur un circuit imprimé plutôt que l’affiche sur un mur. Le module image dispose d’un décodeur dédié pour chacun, couvrant les applications industrielles, de vente au détail et d’inventaire que les codes 2D grand public n’ont jamais vraiment atteintes.
5.29.1. Codes-barres 1D¶
Un code-barres unidimensionnel encode sa charge utile sous la forme d’une séquence de barres verticales de largeurs variables, lues de gauche à droite (ou de haut en bas pour les codes orientés verticalement). Les largeurs se quantifient en l’une d’un petit ensemble de valeurs, et la séquence des largeurs épelle des caractères selon la symbologie choisie par l’imprimeur : numérique pour un code produit UPC, alphanumérique pour un numéro de pièce d’entrepôt, ou texte arbitraire pour une étiquette Code 128.
find_barcodes() analyse la trame à la recherche de codes-barres 1D dans n’importe laquelle des symbologies prises en charge et renvoie une liste d’objets résultat 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)
Le décodeur analyse la trame à la fois horizontalement et verticalement en un seul appel, de sorte qu’un code-barres imprimé sous n’importe quel angle est trouvé en un seul passage sans que l’application ait à faire pivoter l’entrée. roi restreint la recherche ; aucun autre paramètre de réglage n’existe – le décodeur est autonome.
Les symbologies prises en charge couvrent les familles grand public et industrielles courantes. L’ensemble vente au détail comprend image.EAN2, image.EAN5, image.EAN8, image.UPCE, image.UPCA, image.EAN13 (les codes numériques de longueur fixe sur la plupart des emballages grand public), image.ISBN10 et image.ISBN13 (les mêmes familles réaffectées aux livres). L’ensemble polyvalent comprend image.I25 (Interleaved 2 of 5, courant sur les étiquettes d’expédition), image.CODABAR (utilisé dans les bibliothèques et les banques de sang), image.CODE39, image.CODE93 et image.CODE128 (symbologies alphanumériques de longueur variable pour du texte arbitraire). La famille de bord de rayonnage image.DATABAR (RSS-14) et image.DATABAR_EXP (RSS-Expanded) complète la liste.
Chaque détection porte le vocabulaire de la boîte englobante – x, y, w, h, rect, corners – ainsi que la charge utile décodée payload sous forme de chaîne. type est la constante de symbologie de la liste ci-dessus, qu’une application vérifie lorsqu’elle se soucie spécifiquement de la famille décodée (par exemple, n’accepter que EAN13 pour une application de scanner d’épicerie).
Les deux champs qui importent pour le filtrage sont rotation et quality. rotation est l’angle du code-barres dans le plan de l’image, en radians : le décodeur gère les rotations arbitraires, mais le code en aval qui souhaite afficher la détection proprement peut vouloir filtrer les codes qui reviennent inclinés au-delà d’un certain seuil.
quality est le nombre de décodages : le nombre de lignes de balayage qui ont décodé avec succès la même charge utile. Le décodeur parcourt chaque ligne (et colonne) de la trame qui croise le code-barres, et incrémente le compteur à chaque décodage réussi. Un code-barres imprimé bien net et bien éclairé donne une quality de l’ordre de la dizaine ; un code-barres partiellement occulté ou taché peut ne décoder que sur une ou deux lignes de balayage et signaler une quality de 1 – 2. Le filtrage des détections en dessous de quality > 5 écarte les mauvais décodages transitoires sur une seule ligne de balayage sans coût pour les détections authentiques.
Une application de code-barres 1D est compacte. Capturez une trame, appelez find_barcodes(), parcourez la liste renvoyée, filtrez sur c.type et c.quality, et transmettez c.payload via UART ou USB à l’étage en aval qui journalise ou enregistre le scan.
5.29.2. Data Matrix¶
Un code Data Matrix est un symbole 2D qui encode sa charge utile sous la forme d’une grille de cellules noires et blanches, à la manière d’un code QR. Il diffère d’un code QR sur deux points pratiques : il est plus petit à charge utile équivalente (l’encodage est plus dense) et il est destiné à un usage industriel plutôt que grand public (où les codes QR dominent). Les motifs gravés au laser dans des pièces métalliques sur une chaîne de production, les étiquettes imprimées sur les boîtiers de circuits intégrés, les marques apposées sur les seringues médicales – tous ceux-là sont généralement des Data Matrix, et non des codes QR.
find_datamatrices() analyse la trame à la recherche de codes Data Matrix et renvoie une liste d’objets résultat 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 restreint la recherche de la manière habituelle. Le seul réglage spécifique au décodeur est effort, un entier qui contrôle l’intensité du travail du décodeur pour trouver une correspondance. Des valeurs plus élevées améliorent la détection des codes faibles, endommagés ou obliques au prix de la cadence d’images ; des valeurs plus faibles s’exécutent plus rapidement mais peuvent manquer des codes qu’un effort plus élevé aurait trouvés. Les valeurs inférieures à environ 160 échouent en pratique à détecter ; les valeurs supérieures à environ 240 donnent des rendements décroissants. La valeur par défaut de 200 est un équilibre raisonnable pour une image nette, et le bon point de départ pour une nouvelle application est la valeur par défaut plus ou moins 20 selon que les cibles sont propres (plus bas) ou détériorées (plus haut).
Chaque détection porte le vocabulaire de la boîte englobante et les quatre coins détectés, la charge utile décodée payload, et la rotation dans le plan de l’image, en radians. Les métadonnées de disposition décrivent la taille et la densité du symbole lu par le décodeur : rows et columns sont les nombres de cellules de la grille de données ; capacity est le nombre maximal de caractères de charge utile que le symbole pourrait contenir à cette taille ; padding est le nombre de ces emplacements restés inutilisés (capacity - len(payload)).
Les champs de disposition sont utiles aux applications qui doivent valider le format d’une marque gravée plutôt que son contenu. Un système de suivi de pièces pourrait exiger que toutes les marques soient des codes 12 par 12 avec au plus deux caractères de remplissage ; une détection revenue en 8 par 8 (un symbole plus petit que ce que la spécification exige) ou avec 10 caractères de remplissage (majoritairement vide) est signalée pour un nouveau marquage.
5.29.3. Lequel choisir¶
Là où le choix entre QR et AprilTag se résumait au type de charge utile (données arbitraires contre petit identifiant), le choix entre codes-barres et codes Data Matrix se résume à la densité physique et à l”industrie.
Lorsque l’application est destinée au grand public et que les codes existent déjà sur le terrain – produits d’épicerie, livres, étiquettes d’expédition, ouvrages de bibliothèque – le bon détecteur est find_barcodes(). Les codes que l’application lit ont été imprimés pour être lus par un autre système, et les symbologies de vente au détail normalisées sont ce que ce système attendait.
Lorsque l’application est industrielle et que les codes sont imprimés pour l’application – suivi d’inventaire sur une chaîne de production, codes de lot gravés sur des pièces, marques de traçabilité sur des dispositifs médicaux – le bon détecteur est find_datamatrices() ou find_qrcodes(), selon que l’application a besoin de la densité supérieure du Data Matrix ou du support outillage plus large du QR.
Une poignée d’applications combinent les quatre détecteurs dans un même pipeline. Une caméra d’inspection de colis pourrait exécuter un passage find_barcodes() pour l’UPC imprimé, un passage find_qrcodes() pour un code QR d’expédition sur la même boîte, et un passage find_datamatrices() pour un code de pièce gravé, le tout sur la même trame capturée ; les trois listes de résultats sont corrélées par position de boîte englobante et signalées comme un unique enregistrement de détection. Le coût de chaque détecteur s’additionne, de sorte que les applications qui procèdent ainsi restreignent généralement chaque passage avec un roi approprié plutôt que de chercher tout type de code dans la trame entière.