Unable to decode Aztec barcode

Question:

I’m trying to decode an Aztec barcode using the following script:

import zxing
reader = zxing.BarCodeReader()
barcode = reader.decode("test.png")
print(barcode)

Here is the input image:

enter image description here

Following is the output:

BarCode(raw=None, parsed=None,
path=’/Users/dhiwatdg/Desktop/test.png’, format=None, type=None,
points=None)

I’m sure it a valid Aztec barcode. Not the script is not able to decode.

Asked By: DhiwaTdG

||

Answers:

The barcode is not detected because there is a strong "ringing" artifact around the black bars (could be result of "defocus" issue).
We may apply binary threshold for getting higher contrast between black and while.
Finding the correct threshold is difficult…

For finding the correct threshold, we may start with the automatic threshold value returned by cv2.THRESH_OTSU, and increasing the threshold until the barcode is detected.
(Note that need to increase [and not decrease] the threshold is specific to the image above).


Note:

  • The suggested solution is a bit of an overfit, and it’s not very efficient.
    Other solution I tried, like sharpening were not working…

Code sample:

import cv2
import zxing

reader = zxing.BarCodeReader()

img = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)  # Read the image as grayscale.

thresh, bw = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)  # Apply automatic binary thresholding.

while thresh < 245:
    print(f'thresh = {thresh}')
    cv2.imshow('bw', bw)  # Show bw image for testing
    cv2.waitKey(1000)  # Wait 1 second (for testing)
    cv2.imwrite('test1.png', bw)  # Save bw as input image to the barcode reader.
    barcode = reader.decode("test1.png", try_harder=True, possible_formats=['AZTEC'], pure_barcode=True)  # Try to read the barcode

    if barcode.type is not None:
        break  # Break the loop when barcode is detected.

    thresh += 10  # Increase the threshold in steps of 10
    thresh, bw = cv2.threshold(img, thresh, 255, cv2.THRESH_BINARY)  # Apply binary threshold

cv2.imwrite('bw.png', bw)  # Save bw for debugging

cv2.destroyAllWindows()
print(barcode)

Last value of thresh = 164.

Last bw image:
enter image description here

Answered By: Rotem

@Rotem’s solution works perfectly. I also found the below solution workable by applying Wiener filter.

import cv2
import zxing

img = cv2.imread("test.png")

dst = cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
cv2.imwrite("test_tmp.png", dst)

reader = zxing.BarCodeReader()
barcode = reader.decode("test_tmp.png")
print(barcode)
Answered By: DhiwaTdG