Code 39バーコードスキャナー


10

1974 年に開発されたCode 39は、バーコードの最も一般的に使用される記号またはタイプの1つですが、小売販売で最も頻繁に見られるのはUPC / EANシステムです。Code 39バーコードは、大文字、数字、および一部の記号をエンコードでき、特別なフォントを使用してコンピューターソフトウェアから印刷するのは簡単です。これにより、商業および産業での幅広い利用が可能になりました(会社IDバッジ、資産追跡、ファクトリオートメーションなど)。

512x512ピクセルのグレースケール画像からあらゆる方向のCode 39バーコードを読み取るための最短のプログラムまたは関数を作成します。バーコードが水平または垂直に配置されていない可能性があります。

  • プログラムは、標準のイメージファイル形式を受け入れ、バーコードでエンコードされたデータを標準出力または戻り値(開始/停止文字を含まない)として生成する必要があります。
  • 有効なCode 39バーコードを複数含む画像はなく、スペース文字(ASCII 32)をエンコードするバーコードはありません。
  • 画像に有効なCode 39バーコードが表示されない場合、プログラムは単一の疑問符(?)を出力する必要があります。

有効なバーコードを使用した場合と使用しない場合の両方で、JavaScriptリファレンス実装と画像のテストスイートをPNG形式で準備しました。最新のWebブラウザーでは46のテストケースのうち3つだけが失敗するリファレンス実装は、上記の仕様に厳密に準拠するのではなく、1つの可能なデコードアルゴリズムを示すことを目的としています。

有効な送信は、これらのテストの少なくとも80%(37/46)に合格し、適度に高速なCPU(例:2.6 GHzクアッドコア)の各イメージで1分以内に完了します。私のリファレンス実装はテストの93%に合格し、各イメージを10秒以内に処理します(Google Chromeを実行しているデスクトップPCで)。

(この質問は2011年5月28日にメタで提案されました。)


バーコードジェネレーターにバグがあるようです-文字の間隔が狭いのではなく、文字の間隔が広くなっています。
— キースランダル

@キース:文字間ギャップ(I)は、狭いバー(X)の幅と同じである必要はありませんが、同じであることがよくあります。有効な提出では、I≤3Xのバーコードを読み取ることができる必要があります。テストケースジェネレーターは、キャラクター間のギャップを意図的にランダム化します。adams1.com/39code.html
— PleaseStand

1Xと3Xの間の文字間隔のあるCode 39バーコードは、最も一般的なスキャナーで読み取ることができますか?私はそれを証明し、それがこのように機能するかどうかを確認します。ちなみに私の目では、インターギャップはCode 39の印刷出力サイズしか拡大できないので、なぜ文字間ギャップを拡大する必要があるのでしょうか。

回答:


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%の偽陰性の失敗率が得られます。)失敗した場合、実行に約1分かかり、成功した場合は、それよりもはるかに速く実行されます。誤検知は見たことがありません。


M=dict(zip('UK.-RQA+HGYXON*TEDJ1/87$%540WVML SCBIZPF3296',[385,259,...]))
— ugoren 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.