使用pyzbar在Python中读取模糊条形码

5

我一直在尝试使用Python和pyzbar从图像中读取一些条形码。不幸的是,这些图像是在几英尺外以及多种限制下拍摄的,我无法将相机移动或放大。是否有可能使用任何现有的Python库读取这样模糊的条形码?

输入图像描述

到目前为止,我尝试过一些预处理方法,包括阈值处理、锐化、应用垂直闭合滤波器和维纳滤波等,但都没有起到帮助的作用。我可能在求奇迹,但如果你有任何建议,我会非常感激。

代码(注释部分是我尝试过但没有成功的预处理方法):

import numpy as np
import cv2 as cv
from pyzbar import pyzbar

barcode_img = cv.imread('barcode_example.jpg', cv.IMREAD_GRAYSCALE)

# threshold
# (_, barcode_img) = cv.threshold(barcode_img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)

# close
# barcode_img = cv.morphologyEx(barcode_img, cv.MORPH_CLOSE,
#                               cv.getStructuringElement(cv.MORPH_RECT, (1, 21)))

# sharpen
# barcode_img_blur = cv.GaussianBlur(barcode_img, (15, 1), 3)
# barcode_img = cv.addWeighted(barcode_img, 1.5, barcode_img_blur, -0.5, 0)

# wiener filter
# from skimage import img_as_float
# from skimage.restoration import wiener, unsupervised_wiener
# dim = 3
# psf = np.ones((dim, dim)) / dim ** 2
# barcode_img = wiener(barcode_img, psf, 1.0, clip=False)

barcodes = pyzbar.decode(barcode_img)
print(barcodes)

你知道这个条形码的类型吗? - WenJuan
我相信Code128。 - Mason McGough
1个回答

6
  • 这个解决方案可能不是最优的,但它某种程度上解决了问题。
  • 通过使用统计学知识,我们可以知道这是一张条形码,其中竖直的黑色像素代表每个条纹,我对每行进行求和,并基于接近求和平均值的经验值对整个图像进行了阈值处理,然后相应地重建了条纹,这就是解决方案:
#========================
# Import Libraies
#========================
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt 
from pyzbar import pyzbar

#------------------------
# Read Image
#========================
img = cv.imread('barcode_example.jpg', cv.IMREAD_GRAYSCALE)

# #------------------------
# # Morphology
# #========================
# # Closing
# #------------------------
closed = cv.morphologyEx(img, cv.MORPH_CLOSE, cv.getStructuringElement(cv.MORPH_RECT, (1, 21)))

# #------------------------
# # Statistics
# #========================
print(img.shape)
dens = np.sum(img, axis=0)
mean = np.mean(dens)
print(mean)

#------------------------
# Thresholding
#========================
thresh = closed.copy()
for idx, val in enumerate(dens):
    if val< 10800:
        thresh[:,idx] = 0

(_, thresh2) = cv.threshold(thresh, 128, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)

#------------------------
# plotting the results
#========================
plt.figure(num='barcode')

plt.subplot(221)
plt.imshow(img, cmap='gray')
plt.title('Original')
plt.axis('off')

plt.subplot(224)
plt.imshow(thresh, cmap='gray')
plt.title('Thresholded')
plt.axis('off')

plt.subplot(223)
plt.imshow(thresh2, cmap='gray')
plt.title('Result')
plt.axis('off')

plt.subplot(222)
plt.hist(dens)
plt.axvline(dens.mean(), color='k', linestyle='dashed', linewidth=1)
plt.title('dens hist')

plt.show()

#------------------------
# Printing the Output
#========================
barcodes = pyzbar.decode(thresh2)
print(barcodes)

solution

输出结果为:

[解码(数据=b'00004980072868003004',类型='CODE128',矩形=Rect(left=34, top=0, width=526, height=99),多边形=[Point(x=34, y=1), Point(x=34, y=99), Point(x=560, y=98), Point(x=560, y=0)])]


请问,在日常生活中还有哪些方法可以应用这种方法?谢谢。 - ABCDEFG user157844
@ABCDEFG用户157844,我没有明白你的问题,请你详细说明一下? - Bilal
例如,我们能否采用这种方法来改善文档中的照片或其他内容。谢谢。 - ABCDEFG user157844
1
@ABCDEFGuser157844 我不确定它是否可以用于文档,因为字母没有简单的条形形状,但也许可以提取外部文档边界并将其投影成矩形形状,使得线条可以变得直线且易于被OCR算法检测和解释,但这不是一个直接的实现,需要在方法上进行更多的工作。 - Bilal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接