코드 39 바코드 스캐너


10

1974 년에 개발 된 Code 39 는 소매 판매에서 가장 많이 볼 수있는 UPC / EAN 시스템이지만 가장 일반적으로 사용되는 기호 또는 바코드 유형 중 하나입니다. Code 39 바코드는 대문자, 숫자 및 일부 기호를 인코딩 할 수 있으며 특수 글꼴을 사용하여 컴퓨터 소프트웨어에서 인쇄하기가 쉽지 않습니다. 이로 인해 상업 및 산업용으로 널리 사용되었습니다 (예 : 회사 ID 배지, 자산 추적, 공장 자동화).

512x512 픽셀 회색조 이미지에서 어떤 방향 으로든 Code 39 바코드를 읽는 가장 짧은 프로그램 또는 기능을 만듭니다. 바코드가 가로 또는 세로로 정렬되지 않았을 수 있습니다.

  • 프로그램은 표준 이미지 파일 형식을 허용하고 바코드에 인코딩 된 데이터를 표준 출력 또는 반환 값 (시작 / 정지 문자 제외)으로 생성해야합니다.
  • 이미지에 유효한 Code 39 바코드가 둘 이상 포함되어 있지 않으며 공백 문자를 인코딩하는 바코드가 없습니다 (ASCII 32).
  • 이미지에 유효한 Code 39 바코드가 표시되지 않으면 프로그램은 단일 물음표 ( ?)를 출력해야합니다 .

유효한 바코드를 사용하거나 사용하지 않고 PNG 형식으로 JavaScript 참조 구현 및 테스트 이미지 스위트 를 준비했습니다 . 가장 최근의 웹 브라우저에서 46 개의 테스트 사례 중 3 개만 실패한 참조 구현은 위의 사양을 엄격하게 준수하지 않는 한 가지 가능한 디코딩 알고리즘을 보여주기위한 것입니다.

유효한 제출은 이러한 테스트의 최소 80 % (37/46)를 통과하며 상당히 빠른 CPU (예 : 2.6GHz 쿼드 코어)의 각 이미지에 대해 1 분 이상 걸리지 않습니다. 내 참조 구현은 테스트의 93 %를 통과하고 10 초 내에 각 이미지를 처리합니다 (Chrome을 실행하는 데스크톱 PC에서).

(이 질문은 2011 년 5 월 28 일 메타 에서 제안되었습니다 .)


바코드 생성기에 버그가있는 것 같습니다. 좁은 문자 대신 문자 사이에 넓은 간격을 둡니다.
Keith Randall

@Keith : 문자 간 간격 (I)은 좁은 막대 (X)의 너비와 같을 필요는 없지만 종종 있습니다. 유효한 제출물은 I ≤ 3X 인 바코드를 읽을 수 있어야합니다. 내 테스트 케이스 생성기는 의도적으로 문자 간 격차를 무작위 화합니다. adams1.com/39code.html
PleaseStand

1X에서 3X 사이의 문자 간격이있는 Code 39 바코드는 대부분의 일반적인 스캐너에서 읽을 수 있습니까? 나는 그것을 간증하고 그것이 이런 식으로 작동하는지 볼 것이다 . 그건 그렇고, 내 눈에 intergap은 Code 39 인쇄물 크기 만 확대 할 수 있으므로 왜 intercharacter gap을 확장해야합니까?

답변:


5

파이썬, 899 자

import sys,random
raw_input()
X,Y=map(int,raw_input().split())
input()
I=[' x'[v<'~']for v in sys.stdin.read()]
M={196:' ',168:'$',148:'*',388:'.',52:'0',97:'2',49:'4',112:'6',292:'8',73:'B',25:'D',88:'F',268:'H',28:'J',67:'L',19:'N',82:'P',262:'R',22:'T',193:'V',145:'X',208:\
'Z',42:'%',138:'+',133:'-',162:'/',289:'1',352:'3',304:'5',37:'7',100:'9',265:'A',328:'C',280:'E',13:'G',76:'I',259:'K',322:'M',274:'O',7:'Q',70:'S',385:'U',448:'W'\
,400:'Y'}
N=500
for w in' '*30000:
 a,b,c,d=eval('random.random(),'*4);A=''.join(I[int((a+(c-a)*i/N)*X)+X*int((b+(d-b)*i/N)*Y)]for i in range(N)).lstrip();T=A.count(' x')+1;K=A.count('x')/T;L=A.count\
(' ')/T;s='';z=c=0
 while A:
  z*=2;y=A.find(' ')
  if y<0:y=len(A)
  z+=y>K;A=A[y:]
  z*=2;y=A.find('x')
  if y<0:y=len(A)
  z+=y>L;A=A[y:];c+=2
  if c>9:
   if z/2in M:s+=M[z/2];z=c=0
   else:break
 if s and'*'==s[0]and'*'==s[-1]and'*'!=s:print s[1:-1];break

이 코드는 pnm 형식 이미지를 입력으로 사용하므로 일반적으로 다음과 같이 실행합니다.

pngtopnm s01.png | ./barcode.py

코드 자체는 많은 무작위 스캔 라인을 선택하고 해당 스캔 라인의 흑백 실행을 코드 39 패턴과 일치 시키려고 시도합니다. 무작위로 분류되어 경우에 따라 바코드를 찾지 못할 수도 있습니다. (테스트 이미지에서 약 20 %의 잘못된 음의 실패율을 얻습니다.) 실패하면 실행하는 데 약 1 분이 걸리고 성공하면 종종 그보다 훨씬 빠릅니다. 나는 거짓 긍정을 본 적이 없다.


M=dict(zip('UK.-RQA+HGYXON*TEDJ1/87$%540WVML SCBIZPF3296',[385,259,...]))
ugoren
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.