问题
I have been trying to read some barcodes from images uzing Python and pyzbar. Unfortunately, the images are taken from several feet away under several constraints and I cannot move or zoom the camera any closer. Is it possible to read barcodes this blurry using any existing Python libraries?
So far I've tried some preprocessing including thresholding, sharpening, applying a vertical closing filter, and Wiener filtering, but none seem to help. I am probably asking for a miracle, but if you have any suggestions I would really appreciate it.
Code (commented sections are preprocessing methods I have tried with no success):
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)
回答1:
- This is not the optimal solution, if you have an improvement in your mind please share it with us so we all can learn.
- so depending on some statistics knowing that it's a barcode so there is a vertical black zone to represent each bar, so I did the summation of the rows, and thresholded the whole image depending on an empirical value near the mean of the summation, I solved the problem with this way:
#========================
# 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)
The Output is: [Decoded(data=b'00004980072868003004', type='CODE128', rect=Rect(left=34, top=0, width=526, height=99), polygon=[Point(x=34, y=1), Point(x=34, y=99), Point(x=560, y=98), Point(x=560, y=0)])]
来源:https://stackoverflow.com/questions/64111254/read-blurry-barcode-in-python-with-pyzbar