5.29. バーコードとData Matrixコード

さらに2つのコード系統がカメラのデコーダーを完成させます。一次元バーコード(シリアル箱の側面の縞模様、病院のリストバンド、配送ラベル)は、今なお日常的に使われる中で最も古い機械可読シンボルです。Data Matrix コードはQRコードと同様に二次元ですが、同じペイロードサイズでより高密度であり、産業用マーキングを狙ったものです。壁に貼られたポスターというより、回路基板にレーザーエッチングされたメーカーマークのようなものです。imageモジュールにはそれぞれ専用のデコーダーがあり、コンシューマー向け2Dコードが決して十分に到達しなかった産業、小売、在庫管理のアプリケーションをカバーします。

5.29.1. 1Dバーコード

一次元 バーコードは、そのペイロードを幅の異なる垂直バーの並びとしてエンコードし、左から右へ(垂直方向のコードでは上から下へ)読み取ります。バーの幅は少数の値の集合のいずれかに量子化され、その幅の並びが、印刷者が選んだシンボル体系で文字を綴ります。UPC製品コードの数字、倉庫の部品番号の英数字、あるいはCode 128ラベルの任意のテキストです。

find_barcodes() は、サポートされているシンボル体系のいずれかの1Dバーコードをフレーム内で走査し、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)

デコーダーは1回の呼び出しでフレーム全体を水平方向と垂直方向の両方に走査するため、任意の角度で印刷されたバーコードも、アプリケーションが入力を回転させることなく1回のパスで見つかります。roi は検索範囲を制限します。他に調整パラメータは存在せず、デコーダーは自己完結しています。

サポートされる シンボル体系 は、一般的なコンシューマー系統と産業系統をカバーします。小売向けのセットは image.EAN2image.EAN5image.EAN8image.UPCEimage.UPCAimage.EAN13(ほとんどの消費者向けパッケージに付く数字の固定長コード)、image.ISBN10image.ISBN13(書籍向けに転用された同じ系統)です。汎用のセットは image.I25(Interleaved 2 of 5、配送ラベルで一般的)、image.CODABAR(図書館や血液銀行で使用)、image.CODE39image.CODE93image.CODE128(任意のテキスト向けの可変長英数字シンボル体系)です。棚札系統の image.DATABAR(RSS-14)と image.DATABAR_EXP(RSS-Expanded)がリストを締めくくります。

各検出はバウンディングボックスの語彙(xywhrectcorners)と、デコードされた payload を文字列として持ちます。type は上記リストのシンボル体系定数で、どの系統がデコードされたかを特に気にするアプリケーション(例えば食料品スキャナーアプリケーションで EAN13 のみを受け入れる場合)がチェックするものです。

フィルタリングにおいて重要な2つのフィールドは rotationquality です。rotation はバーコードの画像面内の角度をラジアンで表したものです。デコーダーは任意の回転に対応しますが、検出をきれいに表示したい後段のコードは、あるしきい値を超えて傾いて返ってきたコードを除外したい場合があります。

quality はデコード回数です。同じペイロードのデコードに成功した走査線の数です。デコーダーはバーコードと交差するフレームのすべての行(および列)にわたって走行し、デコードが成功するたびにカウンターをインクリメントします。鮮明なフォーカスと良好な照明で印刷されたバーコードは数十の quality を生みます。部分的に隠れたり汚れたりしたバーコードは、わずか1、2本の走査線でしかデコードされず、quality が 1 -- 2 と報告されることがあります。quality > 5 を下回る検出を除外することで、本物の検出を損なうことなく、一時的な単一走査線の誤デコードを破棄できます。

1Dバーコードのアプリケーションは小さなものです。フレームを撮影し、find_barcodes() を呼び出し、返されたリストを反復し、c.typec.quality でフィルタリングし、c.payload をUARTまたはUSB経由で、スキャンを記録したり計上したりする後段のステージへ転送します。

5.29.2. Data Matrix

Data Matrix コードは、QRコードと同じように、ペイロードを黒と白のセルの格子としてエンコードする2Dシンボルです。QRコードとは2つの実用的な点で異なります。同じペイロードサイズで より小さく(エンコードがより高密度)、コンシューマー用途(QRコードが優勢)ではなく 産業 用途を対象としていることです。工場のフロアで金属部品にレーザーエッチングされたパターン、集積回路パッケージに印刷されたラベル、医療用注射器に付けられたマーク、これらはすべて典型的にはQRコードではなくData Matrixです。

find_datamatrices() はフレーム内のData Matrixコードを走査し、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 は通常どおり検索範囲を制限します。唯一のデコーダー固有の調整つまみは effort で、デコーダーが一致を見つけるためにどれほど懸命に働くかを制御する整数です。値を高くすると、薄い、損傷した、または斜めのコードの検出が向上しますが、フレームレートが犠牲になります。値を低くすると高速に動作しますが、より高いeffortなら見つかったはずのコードを見逃すことがあります。約160を下回る値では実質的に検出に失敗し、約240を上回る値では効果が頭打ちになります。デフォルトの200は鮮明な画像にとって妥当なバランスであり、新しいアプリケーションの正しい出発点は、対象がclean(より低く)か劣化している(より高く)かに応じて、デフォルトに±20した値です。

各検出はバウンディングボックスの語彙と検出された4つのコーナー、デコードされた payload、そして画像面内の rotation をラジアンで持ちます。レイアウトメタデータ は、デコーダーが読み取ったシンボルのサイズと密度を記述します。rowscolumns はデータ格子のセル数です。capacity はそのサイズでシンボルが運べるペイロード文字の最大数です。padding はそれらのスロットのうち未使用のままだった数(capacity - len(payload))です。

レイアウトフィールドは、エッチングされたマークの内容ではなく フォーマット を検証する必要があるアプリケーションに役立ちます。部品追跡システムは、すべてのマークが最大2つのパディング文字を持つ12×12のコードであることを要求するかもしれません。8×8(仕様が求めるより小さなシンボル)で返ってきた検出や、10個のパディング文字を持つ(ほとんど空の)検出は、再マーキングのためにフラグが立てられます。

5.29.3. どちらを選ぶか

QR対AprilTagが ペイロードの種類(任意のデータ対小さなID)に帰着したのに対し、バーコード対Data Matrixコードは 物理的密度業界 に帰着します。

アプリケーションがコンシューマー向けで、コードがすでに現場に存在する場合(食料品、書籍、配送ラベル、図書館の本)、正しい検出器は find_barcodes() です。アプリケーションが読み取っているコードは別のシステムが読むために印刷されたものであり、標準化された小売のシンボル体系はそのシステムが期待していたものです。

アプリケーションが産業向けで、コードが アプリケーションのために印刷されている 場合(工場フロアでの在庫追跡、部品にエッチングされたロットコード、医療機器のトレーサビリティマーク)、正しい検出器は、アプリケーションがData Matrixのより高い密度を必要とするか、QRのより広範なツールサポートを必要とするかに応じて、find_datamatrices() または find_qrcodes() です。

少数のアプリケーションは、1つのパイプラインで4つの検出器すべてを混在させます。パッケージ検査用カメラは、印刷されたUPCのために find_barcodes() のパスを、同じ箱の配送用QRコードのために find_qrcodes() のパスを、エッチングされた部品コードのために find_datamatrices() のパスを、すべて同じ撮影フレームに対して実行するかもしれません。3つの結果リストはバウンディングボックスの位置で相関付けられ、単一の検出レコードとして報告されます。各検出器のコストは加算されるため、これを行うアプリケーションは通常、あらゆる種類のコードについてフレーム全体を検索するのではなく、各パスを適切な roi で絞り込みます。