5

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?

enter image description here

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)
Mason McGough
  • 532
  • 5
  • 13

1 Answers1

6
  • This solution might not be optimal, but it somehow solves the problem.
  • Using statistics knowing that it's a barcode where the vertical black pixels represent each bar, I did the summation of the rows, and thresholded the whole image depending on an empirical value near the mean of the summation, then reconstructed the bars accordingly, Here is the solution:
#========================
# 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

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)])]

Bilal
  • 3,191
  • 4
  • 21
  • 49
  • Excuse me , what else in daily life can be applied by this method? Thank you. – ABCDEFG user157844 Dec 08 '21 at 07:42
  • @ABCDEFG user157844 I didn't get your question, can you please elaborate more? – Bilal Dec 08 '21 at 09:49
  • for example , can we bring this method to improve documents photo or anything like this. Thank you. – ABCDEFG user157844 Dec 12 '21 at 06:46
  • 1
    @ABCDEFGuser157844 I'm not sure if it can be used with documents as the letters don't have simple bar shapes, but maybe to extract the external documents boundaries and make a projection into rectangular shape where the lines can be straight and easily detected and interpreted by ocr algorithms, but that won't be a straight forward implementation, it requires more work on the method. – Bilal Dec 12 '21 at 12:22