Search code examples
pythonimage-processingzxingbarcode-scanneraztec-barcode

Unable to decode Aztec barcode


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.


Solution

  • 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