web-dev-qa-db-ja.com

バーコードの四隅を確実に検出するにはどうすればよいですか?

私はこれを検出しようとしています Code128 バーコードPython + zbarモジュール:

(画像ダウンロードリンク ここ )。

これは機能します:

import cv2, numpy
import zbar
from PIL import Image 
import matplotlib.pyplot as plt

scanner = zbar.ImageScanner()
pil = Image.open("000.jpg").convert('L')
width, height = pil.size    
plt.imshow(pil); plt.show()
image = zbar.Image(width, height, 'Y800', pil.tobytes())
result = scanner.scan(image)

for symbol in image:
    print symbol.data, symbol.type, symbol.quality, symbol.location, symbol.count, symbol.orientation

ただし、検出されるポイントは1つだけです:(596, 210)

黒と白のしきい値を適用する場合:

pil = Image.open("000.jpg").convert('L')
pil = pil .point(lambda x: 0 if x<100 else 255, '1').convert('L')    

それはより良いです、そして私達には3つのポイントがあります:(596、210)、(482、211)、(596、212)。しかし、それはもう1つの困難を追加します(新しい画像ごとに自動的に最適なしきい値(ここでは100)を見つける)。

それでも、バーコードの四隅はありません。

質問:Pythonを使用して、画像上のバーコードの4つの角を確実に見つける方法は?(そしておそらくOpenCV、または別のライブラリ?)

ノート:

  • それは可能です、これは素晴らしい例です(しかし、コメントで述べられているように残念ながらオープンソースではありません):

    オブジェクト検出、リアルタイムアプリケーション用の非常に高速で堅牢なぼやけた1Dバーコード検出

    コーナー検出は優れており、非常に高速であるようです。バーコードが画像全体のごく一部である場合でも(これは私にとって重要です)。

  • 興味深い解決策: PythonおよびOpenCV を使用したビデオでのリアルタイムバーコード検出ただし、方法には制限があります(記事を参照:バーコードをクローズアップする必要があります、など)潜在的な使用を制限します。また、私はこのためのすぐに使用できるライブラリをもっと探しています。

  • 興味深い解決策2: PythonおよびOpenCV を使用した画像内のバーコードの検出)しかし、繰り返しになりますが、これは本番環境に対応した解決策のようには見えませんが、さらに研究が進行中です。 、私はこの画像で彼らのコードを試しましたが、検出は成功した結果をもたらしません。検出のためにバーコードの仕様を考慮していないことに注意する必要があります( 開始/停止があります)シンボル など)

    import numpy as np
    import cv2
    image = cv2.imread("000.jpg")
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gradX = cv2.Sobel(gray, ddepth = cv2.CV_32F, dx = 1, dy = 0, ksize = -1)
    gradY = cv2.Sobel(gray, ddepth = cv2.CV_32F, dx = 0, dy = 1, ksize = -1)
    gradient = cv2.subtract(gradX, gradY)
    gradient = cv2.convertScaleAbs(gradient)
    blurred = cv2.blur(gradient, (9, 9))
    (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    closed = cv2.erode(closed, None, iterations = 4)
    closed = cv2.dilate(closed, None, iterations = 4)
    (_, cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
    rect = cv2.minAreaRect(c)
    box = np.int0(cv2.boxPoints(rect))
    cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
    cv2.imshow("Image", image)
    cv2.waitKey(0)
    
6
Basj

解決策2はかなり良いです。画像で失敗した重要な要因は、しきい値処理でした。パラメータを削除した場合225まで55、はるかに良い結果が得られます。

コードを作り直して、あちこちで微調整を加えました。必要に応じて、元のコードで問題ありません。 OpenCVのドキュメントは非常に優れています そして非常に優れています Pythonチュートリアル

import numpy as np
import cv2

image = cv2.imread("barcode.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# equalize lighting
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
gray = clahe.apply(gray)

# Edge enhancement
Edge_enh = cv2.Laplacian(gray, ddepth = cv2.CV_8U, 
                         ksize = 3, scale = 1, delta = 0)
cv2.imshow("Edges", Edge_enh)
cv2.waitKey(0)
retval = cv2.imwrite("Edge_enh.jpg", Edge_enh)

# bilateral blur, which keeps edges
blurred = cv2.bilateralFilter(Edge_enh, 13, 50, 50)

# use simple thresholding. adaptive thresholding might be more robust
(_, thresh) = cv2.threshold(blurred, 55, 255, cv2.THRESH_BINARY)
cv2.imshow("Thresholded", thresh)
cv2.waitKey(0)
retval = cv2.imwrite("thresh.jpg", thresh)

# do some morphology to isolate just the barcode blob
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
closed = cv2.erode(closed, None, iterations = 4)
closed = cv2.dilate(closed, None, iterations = 4)
cv2.imshow("After morphology", closed)
cv2.waitKey(0)
retval = cv2.imwrite("closed.jpg", closed)

# find contours left in the image
(_, cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))
cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
print(box)
cv2.imshow("found barcode", image)
cv2.waitKey(0)
retval = cv2.imwrite("found.jpg", image)

Edge.jpg enter image description here

thresh.jpg enter image description here

close.jpg enter image description here

found.jpg enter image description here

コンソールからの出力:

[[596 249]
 [470 213]
 [482 172]
 [608 209]]
3
bfris