PythonとOpenCVを使用して画像のバーコードを認識する

翻訳者から: Enterraのコンピュータービジョンアルゴリズム非常に好きです。 ほとんどの場合、OpenCvを使用します。 時々、さまざまな開発者から質問が寄せられます。「OpenCvで作業を開始するための最良の方法は何ですか?」または「OpenCvで簡単に解決できる興味深いタスクは何ですか?」これに関連して、コンピュータビジョンに興味がある。







ブラックフライデーが来ています。



怒っている買い物客の群衆。 同じ中年の叔母の群れで、最寄りのスーパーマーケットでほとんど何でも食べることができます。主なものは75%の割引です。 彼らは真夜中の感謝祭に店のドアの前に並んでいます。 彼らは侵入し、拳と頭で鍵のかかったドアをノックし、お互いが平らになって血で手を壊し、「28日後」からゾンビのようになります。 しかし、人間の肉の代わりに、彼らは買い手の本能を満たすことを切望しています。 彼らの割引と販売に対する戦争の叫びは天国に届く。 そして、彼らの雷のような踏面は、グレートプレーンで地震を引き起こす可能性があります。



当然、メディアからの助けを期待しないでください-彼らはすべての細部を味わいます。 寒さの中でテントで寝ていた凍傷した家族から、ドアが開いた瞬間に割引のためにハンターに踏みつけられた老婦人まで。 同様のことがジュラシックパークのガリミムスでも起こりました。 そして彼女は、両親が昨年それをやるのを忘れたティミーの9歳の孫のためにHaloを購入したかっただけです。 ウォルマートで。 ブラックフライデー中。



そして、私は尋ねる必要があります:このすべての混乱と騒ぎはそれだけの価値があるのでしょうか?



くそー、いや!



このブラックフライデーで私が購入したものは、ラップトップを使用して完全に安全に行われます。 しかし、現実の世界に入り、利益のためにハンターとの戦いに参加することに決めた場合最初に元の投稿からコードをダウンロードする必要があります



Game of Thronesの最終シーズンのバーコードをスキャンした後、Targetで5ドル安く購入できることを確認するためだけに、無料のレジを待って並んで立っているあなたがどれほど愚かに見えるか想像してみてください。



実際に、後でPythonとOpenCVのみを使用して画像内のバーコードを検出する方法を示します。



PyhtonおよびOpenCvで画像ストリーマーを認識する



この投稿の目的は、バーコード認識のためのコンピュータービジョンおよび画像処理技術のシンプルなアプリケーションを示すことです。 私のアルゴリズムは、 StackOverflowを使用したこの質問のトピックのバリエーションです。 元のコードを見て、多くの更新と改善を追加しました。 このコードはすべてのバーコードで機能するわけではありませんが、いずれの場合でも、どのメソッドを使用する必要があるのか​​がわかります。



アルゴリズムはすべてのバーコードで機能するわけではないことに注意することが重要ですが、これはどのテクニックが使用されるべきかについての基本的な直感的な理解を提供します。



例として、次の画像からバーコードを定義します。







コードに移りましょう。 新しいファイルを開いて、 detect_barcode.py



というdetect_barcode.py



-に行きます:



 # import the necessary packages import numpy as np import argparse import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required = True, help = "path to the image file") args = vars(ap.parse_args())
      
      





まず、必要なパッケージをインポートする必要があります。 数値を操作するにはNumPy、コマンドライン引数を解析するにはagparse



、OpenCVと通信するにはcv2



です。



次に、コマンドライン引数を処理します。 単一の引数--image



を使用して、バーコード付きの画像へのパスを指定します。



次に、直接画像処理に進みます。



 # load the image and convert it to grayscale image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # compute the Scharr gradient magnitude representation of the images # in both the x and y direction gradX = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 1, dy = 0, ksize = -1) gradY = cv2.Sobel(gray, ddepth = cv2.cv.CV_32F, dx = 0, dy = 1, ksize = -1) # subtract the y-gradient from the x-gradient gradient = cv2.subtract(gradX, gradY) gradient = cv2.convertScaleAbs(gradient)
      
      



画像image



をロードし、そのカラーモードをグレーの濃淡に変換します。



次に、Sobel演算子( ksize = -1



)を使用して、垂直方向と水平方向のグレー画像の勾配の大きさを計算します。



その後、x勾配からSobel演算子のy勾配を引きます。 減算後、水平方向の勾配が大きく、垂直方向の値が低い画像が得られます。



これで、画像は次のようになります。







バーコード領域は勾配操作を使用して決定されていることに注意してください。 次のステップは、画像のノイズを除去し、バーコードのある領域のみに焦点を合わせることです。



 # blur and threshold the image blurred = cv2.blur(gradient, (9, 9)) (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
      
      



そして、最初に行うことは、9x9コアで平均ぼかしを使用することです。 これは、グラデーションを使用して画像の高周波ノイズを滑らかにするのに役立ちます。



次に、ぼやけた画像を二値化します。 値が225以下の画像の各ピクセルは、0(黒)に変わり、残りは255(白)になります。 その結果、以下が得られます。





ただし、元の画像でわかるように、バーコードの垂直バーの間にはスペースがあります。 それを閉じて、アルゴリズムがバーコード領域を決定しやすくするために、いくつかの単純な形態学的操作を実行する必要があります。



 # construct a closing kernel and apply it to the thresholded image kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
      
      



cv2.getStructuringElement



を使用して長方形を作成することから始めます。 コアの幅はその高さよりも大きいため、バーコードの垂直ストライプ間のスペースを重ねることができます。



次に、形態学的操作を実行し、コアを2値化画像に適用し、ストリップ間のスペースをカバーします。 また、上記の画像と比較して、「スペース」がほぼ完全に閉じていることがわかります。







もちろん、バーコードとは関係なく、その輪郭を正確に判断するのを妨げる可能性のある明るいスポットが写真上に残っていました。



これらのスポットを取り除きましょう:



 # perform a series of erosions and dilations closed = cv2.erode(closed, None, iterations = 4) closed = cv2.dilate(closed, None, iterations = 4)
      
      





ここでは、侵食を4回繰り返し、その後に膨張を4回繰り返します。 侵食は画像から白いピクセルを除去し、小さな塊を除去し、膨張は大きな白い領域を減少させません。 ストレッチ中のぼかし中に削除された小さなスポットは再表示されません。



一連の侵食と膨張の後、小さなスポットが正常に削除され、バーコード領域のみが残っていることがわかります。







最後に、画像内のバーコード領域の輪郭を見つけましょう。



 # find the contours in the thresholded image, then sort the contours # by their area, keeping only the largest one (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) c = sorted(cnts, key = cv2.contourArea, reverse = True)[0] # compute the rotated bounding box of the largest contour rect = cv2.minAreaRect(c) box = np.int0(cv2.cv.BoxPoints(rect)) # draw a bounding box arounded the detected barcode and display the # image cv2.drawContours(image, [box], -1, (0, 255, 0), 3) cv2.imshow("Image", image) cv2.waitKey(0)
      
      





幸いなことに、これは非常に簡単です。 cv2.findContours



を使用して画像内で最大の輪郭を見つけます。これは(処理が正しく行われた場合)バーコードの領域と正確に一致します。



次に、この最大の輪郭を囲む最小境界長方形を定義し、最後に見つかったバーコードを表示します。



ご覧のとおり、バーコードが正常に見つかりました。





さらにいくつかの画像でこれを試してみましょうか?



成功したバーコード検出



同様の結果を得るには、私のコード(完全にポストオリジナルページからダウンロードできます)とここに示す画像を使用します。 コードと画像を入手したら、ターミナルを開いて次のコマンドを実行します。



 1 $ python detect_barcode.py --image images/barcode_02.jpg
      
      





バーコードココナッツオイルは問題なく見つかりました。 再試行します。



 1 $ python detect_barcode.py --image images/barcode_03.jpg
      
      



そして、この画像でバーコードを発見しました! しかし、私たちは食べ物について何ですか、本に移りましょう。



 1 $ python detect_barcode.py --image images/barcode_04.jpg
      
      



そして再び-問題ありません! 追跡番号を確認できますか?



 1 $ python detect_barcode.py --image images/barcode_05.jpg
      
      







ここでも、アルゴリズムがバーコードを正常に検出しました。



おわりに



この投稿では、コンピュータービジョンテクノロジーを使用して画像上のバーコードを検出するために必要な手順を検討しました。 Pythonプログラミング言語とOpenCVライブラリを使用するアルゴリズムを使用しました。



このアルゴリズムは、次のアクションに基づいています。
  1. x軸とy軸に沿ってグラデーションのサイズを計算します。
  2. バーコード領域を表示するには、垂直方向のグラデーションを水平方向のグラデーションから分離します。
  3. ぼかしと二値化を適用します。
  4. 二値化された画像にカーネルを適用して、ストリップ間の「スペース」を削除します。
  5. 一連の浸食と膨張を実行します。
  6. 画像内で最大の輪郭を見つけます。これがバーコードの領域になります。
このメソッドはグラデーションの形式での画像の表示に基づいているため、水平バーコードに対してのみ正しく機能することに注意してください。



より信頼性の高いバーコード検出アルゴリズムを使用する場合は、画像の向きを考慮し、さらに良いことに、HaarカスケードやHOG + Linear SVMなどの自己学習システムを使用して、バーコードのある領域の画像を「スキャン」する必要があります。



All Articles