5.29. 바코드와 Data Matrix 코드¶
두 가지 코드 계열이 카메라의 디코더를 마무리합니다. 1차원 바코드(시리얼 상자 옆면의 줄무늬, 병원 손목 밴드, 배송 라벨)는 오늘날까지도 일상적으로 사용되는 가장 오래된 기계 판독형 심볼입니다. Data Matrix 코드는 QR 코드처럼 2차원이지만, 같은 페이로드 크기에서 더 조밀하고 산업용 마킹을 겨냥합니다. 벽에 붙은 포스터가 아니라 회로 기판에 레이저 식각된 제조사 마크 같은 것입니다. image 모듈에는 각각을 위한 전용 디코더가 있어, 소비자용 2D 코드가 미처 도달하지 못한 산업, 소매, 재고 관리 애플리케이션을 포괄합니다.
5.29.1. 1D 바코드¶
1차원 바코드는 폭이 다양한 수직 막대의 시퀀스로 페이로드를 인코딩하며, 왼쪽에서 오른쪽으로(또는 세로 방향 코드의 경우 위에서 아래로) 읽습니다. 폭은 작은 값 집합 중 하나로 양자화되고, 폭의 시퀀스는 프린터가 선택한 심볼로지에 따라 문자를 나타냅니다. 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)
디코더는 한 번의 호출로 프레임을 가로 및 세로 양방향으로 스캔하므로, 어떤 각도로 인쇄된 바코드든 애플리케이션이 입력을 회전시킬 필요 없이 한 번의 패스로 찾아냅니다. roi는 검색을 제한합니다. 다른 튜닝 매개변수는 없으며, 디코더는 자체 완결적입니다.
지원되는 심볼로지(symbology) 는 일반 소비자용 및 산업용 계열을 포괄합니다. 소매용 세트는 image.EAN2, image.EAN5, image.EAN8, image.UPCE, image.UPCA, image.EAN13 (대부분의 소비자 제품 포장에 사용되는 고정 길이 숫자 코드), image.ISBN10, image.ISBN13 (도서용으로 재활용된 동일 계열)입니다. 범용 세트는 image.I25 (Interleaved 2 of 5, 배송 라벨에서 흔히 사용됨), image.CODABAR (도서관 및 혈액은행에서 사용됨), image.CODE39, image.CODE93, image.CODE128 (임의의 텍스트를 위한 가변 길이 영숫자 심볼로지)입니다. 선반 가장자리 계열인 image.DATABAR (RSS-14)와 image.DATABAR_EXP (RSS-Expanded)가 목록을 마무리합니다.
각 검출은 경계 상자 어휘인 x, y, w, h, rect, corners와 디코딩된 payload를 문자열로 담고 있습니다. type은 위 목록에 있는 심볼로지 상수이며, 애플리케이션이 어떤 계열이 디코딩되었는지에 구체적으로 관심이 있을 때(예: 식료품 스캐너 애플리케이션에서 EAN13만 허용) 확인합니다.
필터링에 중요한 두 필드는 rotation과 quality입니다. rotation은 바코드의 이미지 평면 내 각도를 라디안으로 나타냅니다. 디코더는 임의의 회전을 처리하지만, 검출을 깔끔하게 표시하려는 다운스트림 코드는 어떤 임계값을 넘어 기울어진 채로 돌아온 코드를 걸러내고 싶을 수 있습니다.
quality는 디코드 횟수입니다. 동일한 페이로드를 성공적으로 디코딩한 스캔라인의 수입니다. 디코더는 바코드와 교차하는 프레임의 모든 행(과 열)을 가로질러 실행되며, 디코드가 성공할 때마다 카운터를 증가시킵니다. 선명한 초점과 좋은 조명에서 인쇄된 바코드는 수십에 이르는 quality를 산출합니다. 부분적으로 가려지거나 번진 바코드는 한두 개의 스캔라인에서만 디코드되어 1 – 2의 quality를 보고할 수 있습니다. quality > 5 미만의 검출을 걸러내면 진짜 검출에는 아무런 손해 없이 일시적인 단일 스캔라인 오디코드를 버립니다.
1D 바코드 애플리케이션은 작습니다. 프레임을 캡처하고, find_barcodes()를 호출하고, 반환된 리스트를 순회하고, c.type과 c.quality로 필터링한 다음, c.payload를 UART 또는 USB를 통해 스캔을 기록하거나 계산하는 다운스트림 단계로 전달합니다.
5.29.2. Data Matrix¶
Data Matrix 코드는 QR 코드가 하는 방식대로 페이로드를 흑백 셀의 격자로 인코딩하는 2D 심볼입니다. QR 코드와는 두 가지 실용적인 측면에서 다릅니다. 같은 페이로드 크기에서 더 작고(인코딩이 더 조밀함) 소비자용보다는 산업용을 겨냥합니다(소비자용에서는 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은 선명한 이미지에 합리적인 균형이며, 새 애플리케이션의 올바른 출발점은 대상이 깨끗한지(더 낮게) 또는 손상되었는지(더 높게)에 따라 기본값에서 20을 더하거나 뺀 값입니다.
각 검출은 경계 상자 어휘와 검출된 네 모서리, 디코딩된 payload, 그리고 이미지 평면 내 rotation을 라디안으로 담고 있습니다. 레이아웃 메타데이터는 디코더가 읽은 심볼의 크기와 밀도를 설명합니다. rows와 columns는 데이터 격자의 셀 수입니다. capacity는 그 크기에서 심볼이 담을 수 있는 최대 페이로드 문자 수입니다. padding은 그 슬롯 중 몇 개가 사용되지 않았는지입니다(capacity - len(payload)).
레이아웃 필드는 식각된 마크의 내용이 아니라 형식을 검증해야 하는 애플리케이션에 유용합니다. 부품 추적 시스템은 모든 마크가 패딩 문자 최대 두 개의 12x12 코드일 것을 요구할 수 있습니다. 8x8로 돌아온 검출(사양이 요구하는 것보다 작은 심볼)이나 패딩 문자가 10개인(대부분 비어 있는) 검출은 재마킹 대상으로 표시됩니다.
5.29.3. 어느 것을 선택할지¶
QR 대 AprilTag가 페이로드 종류(임의 데이터 대 작은 ID)로 귀결되는 반면, 바코드 대 Data Matrix 코드는 물리적 밀도와 산업 분야로 귀결됩니다.
애플리케이션이 소비자 대상이고 코드가 이미 현장에 존재할 때(식료품, 책, 배송 라벨, 도서관 책) 올바른 검출기는 find_barcodes()입니다. 애플리케이션이 읽고 있는 코드는 다른 시스템이 읽도록 인쇄된 것이며, 표준화된 소매 심볼로지가 바로 그 시스템이 기대한 것입니다.
애플리케이션이 산업용이고 코드가 애플리케이션을 위해 인쇄되고 있을 때(공장 바닥의 재고 추적, 부품에 식각된 로트 코드, 의료 기기의 추적성 마크), 올바른 검출기는 애플리케이션이 Data Matrix의 더 높은 밀도가 필요한지 아니면 QR의 더 넓은 도구 지원이 필요한지에 따라 find_datamatrices() 또는 find_qrcodes()입니다.
소수의 애플리케이션은 하나의 파이프라인에서 네 가지 검출기를 모두 혼합합니다. 패키지 검사 카메라는 인쇄된 UPC를 위한 find_barcodes() 패스, 같은 상자의 배송 QR 코드를 위한 find_qrcodes() 패스, 식각된 부품 코드를 위한 find_datamatrices() 패스를 모두 같은 캡처된 프레임에서 실행할 수 있습니다. 세 개의 결과 리스트는 경계 상자 위치로 상관되어 단일 검출 레코드로 보고됩니다. 각 검출기의 비용이 누적되므로, 이를 수행하는 애플리케이션은 일반적으로 모든 종류의 코드에 대해 전체 프레임을 검색하기보다는 적절한 roi로 각 패스를 좁힙니다.