2016年7月15日金曜日

EAN(JAN)コード

EANコードをデコードする方法について。あんまり詳しく調べてなくて、ノリと勢いだけで書いてるので間違ってたらごめんなさい。

EAN/JAN/UPC等ではいろいろな規格がありますが、(調べるのが)面倒なので12桁/13桁に限って説明しています。


画像1


画像2


EANコードでは白(高反射率)の背景に黒(低反射率)の棒を書いてバーコードとしている。低反射率の背景に高反射率の棒でもいいみたいだけど、とりあえずコントラストが充分に確保できればよろしい。
棒(Bar)の幅は4種類あり、一番細い棒をナローバー(Narrow Bar)と呼ぶ。ナローバーの幅は標準が0.33mmで、0.8倍から2.0倍までが許されている。4種類はナローバーに対して1倍、2倍、3倍、4倍の比率を持っている。
数字1桁を表すにはナローバー6本分の空間を使用し、隣との間にはナローバー1本分の白が追加される。他にガードバー(レフトガードバー、ライトガードバー)とセンターバーがあり、これは黒1本、白1本、黒1本の繰り返しパターンとなる。

画像1は幅の組み合わせを示しているが、ナローバーn本分という書き方になっている。例えば左Oddの0は白2本、黒2本、白1本、黒1本、白0本となっているが、これは6本分のスペースに、左から白2本、黒2本、白1本、黒1本というパターンを示している(画像2のOdd0パターン参照)。

数字の表し方は3種類あり、左側が奇数(Odd)と偶数(Even)、それと右側が偶数のみで計3種類となる。

EANコードではバーを30本使用し、そのうち6本はGB/CBとなり、残りの24本を数字として使用する。数字1桁当たり2本を使用するので、24本では12桁となる。つまりEAN(正確には元になったUPC)コードでは12桁しか表すことができない。
ではEANコードではどうやって1桁増やしているかというと、左側の数字6桁を表すコードをOdd/Evenの組み合わせで表記し、その組み合わせから1桁目を推定している。
ISBNで使われる9はOEEOEOの組み合わせになり、JANコードで使われる4はOEOOEEとなる。棒を正確に読み取れていればOdd/Evenを一意に判別できるから、先頭6桁を読んだ時点で最上位1桁を求めることができる。

今のところ右側はEvenのみを使用しているらしく、テーブルは1つしか無い。

チェックデジットの計算だが、これは奇数桁が1倍、偶数桁が3倍の重みを持ち、12桁を加算した下位1桁を10から引いた数がチェックデジットとなる。

#追記:2016/07/15 14:45

手元にあった海外製のパッケージ(Surefireの電池)を読んでみた。これはアメリカ製で、UPCの12桁表記となっている。読み方はEANと同様だが、左側は奇数のみを使用している。チェックデジットの重みは奇数と偶数が逆になっている。
EANとUPCを同じように計算したい場合は、チェックデジットの重みを下位から奇数桁は1倍、のようにすると良いはず。この時の下位にはチェックデジットの桁は含まない。

#追記ここまで



Webカメラから画像認識でやる場合、手っ取り早い方法は画像の画像の幅x高さ10ピクセルくらいの帯を切り出して、それを二値化して幅を計測、という感じだと思う。この方法だと簡単に実装できるが、外乱光に弱かったり、向きを正しく合わせないと読み取れないという問題が有る。
せっかくカメラで読み取るなら様々な向きでも読めたほうが便利なので、そのあたりは画像処理とかで頑張るしか無いかも。
カメラで読む場合、ナローバーの幅が10ピクセル以上あれば処理しやすいはず。バーコードの端から端までが800ピクセルくらいになる。
複数の商品を並べて一気に読み込む場合、解像度は数kピクセル四方から数十kピクセルくらい必要だと思う。Webカメラでは非現実的な気がする。HDMIで4kを受けれるキャプチャカードを使うとかそういう方向になるのかな。


自分でバーコードを読んだところで、実用性は皆無だが、暇で暇でしょうがないという人は、自前でバーコードを読む処理を書いてみてはいかが?
動作確認のサンプルは身の回りにたくさんあるので、そのあたりの心配をしなくていいというのは気楽かも。例えばペットボトルやお菓子にはJANコードが書いてあるし、本の裏にはISBNが書いてある。

0 件のコメント:

コメントを投稿