Code 39条码扫描器


10

1974年开发的Code 39是条形码中最常用的符号或类型之一,尽管零售中最常见的是UPC / EAN系统。Code 39条形码可以对大写字母,数字和一些符号进行编码,使用特殊字体从计算机软件进行打印很容易。这导致了它们在商业和工业上的广泛使用(例如,公司ID徽章,资产跟踪,工厂自动化)。

创建最短的程序或函数,以从512x512像素灰度图像的任何方向读取Code 39条码;条形码可能未水平或垂直对齐。

  • 您的程序必须接受标准的图像文件格式,并产生以条形码编码的数据作为其标准输出或返回值(不包括任何开始/停止字符)。
  • 没有图像包含多个有效的Code 39条形码,并且没有条形码对空格字符(ASCII 32)进行编码。
  • 如果图像中未显示有效的Code 39条码,则程序必须输出一个问号(?)。

我已经准备了JavaScript参考实现和 PNG格式的图像测试套件,包括有效条形码和无条形码。该参考实现在最新的Web浏览器中仅使46个测试案例中的3个失败,该参考实现旨在显示一种可能的解码算法,而不严格符合上述规范。

有效提交至少通过了这些测试的80%(37/46),并且在相当快的CPU(例如2.6 GHz四核)上为每个图像花费的时间不超过一分钟。我的参考实现通过了93%的测试,并在10秒内(在运行Google Chrome的台式机上)处理了每个图像。

(此问题是2011年5月28日在Meta提出的。)


您的条形码生成器中似乎存在一个错误-它在字符之间放置了很大的空间,而不是狭窄的空间。
基思·兰德尔

@基思:字符间距(I)不必等于窄条(X)的宽度,尽管通常是这样。有效提交应能够读取I≤3X的条形码。我的测试用例生成器有意使字符间的间距随机化。adams1.com/39code.html
PleaseStand 2011年

大多数常见的扫描仪都可以读取字符间距介于1X和3X之间的Code 39条码?我将作证,看看它是否可以这种方式工作顺便说一句,在我看来,间隙只能扩大Code 39的打印输出尺寸,那么为什么我们要扩大其字符间距呢?

Answers:


5

Python,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

代码本身只是选择了许多随机的扫描线,并试图将扫描线上的黑白线条与code39模式进行匹配。它是随机的,因此有时可能找不到条形码。(我在测试图像上得到约20%的假阴性失败率。)当它失败时,大约需要一分钟才能运行,而当它成功时,它通常要比那快得多。我从未见过假阳性。


M=dict(zip('UK.-RQA+HGYXON*TEDJ1/87$%540WVML SCBIZPF3296',[385,259,...]))
ugoren
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.