Reading a barcode on pyzbar that's a little unfocused in python 2

349 Views Asked by At

I tried reading this barcode with pyzbar. I've tried at least 2 different approaches for fuzzy barcode filters here on stack overflow, none of them work. I try rotating the barcode to different angles. Doesn't work.unclear barcode i've tried doing threshold with fuzbar() function, I've tried grayscaling. I've tried rotating it at 360 angles. How can I improve teh quality of this barcode to make it scannable with pyzbar?

Here is my code, I'm running python 2.7 btw:

# Importing library
import cv2
from pyzbar.pyzbar import decode
from pyzbar import pyzbar

import numpy as np
from time import sleep
import math

cv = cv2

def rot3(image, angleInDegrees):
    h, w = image.shape[:2]
    img_c = (w / 2, h / 2)

    rot = cv2.getRotationMatrix2D(img_c, angleInDegrees, 1)

    rad = math.radians(angleInDegrees)
    sin = math.sin(rad)
    cos = math.cos(rad)
    b_w = int((h * abs(sin)) + (w * abs(cos)))
    b_h = int((h * abs(cos)) + (w * abs(sin)))

    rot[0, 2] += ((b_w / 2) - img_c[0])
    rot[1, 2] += ((b_h / 2) - img_c[1])

    outImg = cv2.warpAffine(image, rot, (b_w, b_h), flags=cv2.INTER_LINEAR)
    return outImg

def fuzbar(img):

    import matplotlib.pyplot as plt 

    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)



def cropb(image):
    cropped_img = image[image.shape[0]/2:image.shape[0]]
    return cropped_img


def rotate(img):
    #path = r'C:\Users\user\Desktop\geeks14.png'
 
    # Reading an image in default mode
    #src = cv2.imread(path)
     
    # Window name in which image is displayed
    #window_name = 'Image'
     
    # Using cv2.rotate() method
    # Using cv2.ROTATE_90_CLOCKWISE rotate
    # by 90 degrees clockwise
    image = cv2.rotate(src, cv2.ROTATE_90_CLOCKWISE)
     
    # Displaying the image
    #cv2.imshow(window_name, image)
    #cv2.waitKey(0)

def rot2(image, angle):
  image_center = tuple(np.array(image.shape[1::-1]) / 2)
  rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
  result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
  return result


# Make one method to decode the barcode
def BarcodeReader(image):

    print 'yep'
    # read the image in numpy array using cv2
    #img = cv2.imread(image)
    img = cv2.imread(image, cv.IMREAD_GRAYSCALE)


    

    
# cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cropb(img)
    #img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


    fuzbar(img)

    kernel = np.array([[0, -1, 0],
                   [-1, 5,-1],
                   [0, -1, 0]])
    img = cv2.filter2D(src=img, ddepth=-1, kernel=kernel)



    # Decode the barcode image
    detectedBarcodes = decode(img)


    
    
    # If not detected then print the message
    if not detectedBarcodes:
        print 'trying loop NO barcode found'


        cv2.imshow("Image", img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

    
        origimg = img
        zz = 0
        while zz != 360:
                    zz+=1
                    img = rot3(origimg,zz)

                    #cv2.resizeWindow("Resized_Window", 200, 500)

                    #cv2.imshow("Image", img)
                    #cv2.waitKey(0)
                    #cv2.destroyAllWindows()
        
                    print 'detect at angle', zz
                    
                    detectedBarcodes = decode(img)
                    if detectedBarcodes:
                        break
        print 'bob'

        if not detectedBarcodes:
            print("no angle detect")
            return



        # Traverse through all the detected barcodes in image
    for barcode in detectedBarcodes:
            print ('first try found barcodes')
    
            # Locate the barcode position in image
            (x, y, w, h) = barcode.rect
            
            # Put the rectangle in image using
            # cv2 to highlight the barcode
            cv2.rectangle(img, (x-10, y-10),
                                    (x + w+10, y + h+10),
                                    (255, 0, 0), 2)
            
            if barcode.data!="":
            
            # Print the barcode data
                print(barcode.data)
                print(barcode.type)

    print 'done'
                        


    

    
image = "tbar.jpg"
BarcodeReader(image)
1

There are 1 best solutions below

0
Shalini Krishna On

The issue might be with the focus light or camera's light on the bar code, try turning that off and check, else increasing the contrast or converting the barcode image to black and white should do improve the detection.