skip to Main Content

I am doing OCR to extract information from the ID card. However, accuracy is quite low.

My assumption is that removing the background will make OCR more accurate.

I use the ID scanner machine (link) to obtain the grey image below. It seems that the machine uses IR instead of image processing.

Does anyone knows how to get the same result by using Opencv or tools (photoshop, gimp, etc)?

Thanks in advance.

original
processed

2

Answers


  1. EDIT:

    since there are different lighting conditions, contrast adjustment is added here.

    The simple approache in my mind to solve your issue is that: since the undesired background colours are Green and Red, and the desired font colour is Black, simply suppress the Red and green colours as following:

    import numpy as np
    import matplotlib.pyplot as plt
    from skimage.io import imread, imsave
    from skimage.color import rgb2gray
    from skimage.filters import threshold_otsu
    from skimage import exposure
    
    
    def adjustContrast(img):
        p2, p98 = np.percentile(img, (2, 98))
        img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))
        return img_rescale
    
    # Read the image
    img = imread('ID_OCR.jpg')
    
    # Contrast Adjustment for each channel
    
    img[:,:,0] = adjustContrast(img[:,:,0]) # R
    img[:,:,1] = adjustContrast(img[:,:,1]) # G
    img[:,:,2] = adjustContrast(img[:,:,2]) # B
    
    # # Supress unwanted colors
    
    img[img[...,0] > 100] = 255 # R
    img[img[...,1] > 100] = 255 # B
    
    
    # Convert the image to graylevel
    img = rgb2gray(img)
    
    # Rescale into 0-255
    img = 255*img.astype(np.uint8)
    
    # Save the results
    imsave('Result.png', img)
    

    The image will look like:

    image

    The Results are not optimal, because also your image resolution isn’t high.

    At the end, there are many solutions, and improvements, also you can use Morphology to make it look nicer, this is just a simple proposal to solve the problem.

    Login or Signup to reply.
  2. Here are two more methods: adaptive thresholding and division normalization.

    Input:

    enter image description here

    import cv2
    import numpy as np
    
    # read image
    img = cv2.imread("green_card.jpg")
    
    # convert img to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # do adaptive threshold on gray image
    thresh1 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 51, 25)
    
    # write results to disk
    cv2.imwrite("green_card_thresh1.jpg", thresh1)
    
    
    # apply morphology
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT , (11,11))
    morph = cv2.morphologyEx(gray, cv2.MORPH_DILATE, kernel)
    
    # divide gray by morphology image
    division = cv2.divide(gray, morph, scale=255)
    
    # threshold
    thresh2 = cv2.threshold(division, 0, 255, cv2.THRESH_OTSU )[1] 
    
    # write results to disk
    cv2.imwrite("green_card_thresh2.jpg", thresh2)
    
    # display it
    cv2.imshow("thresh1", thresh1)
    cv2.imshow("thresh2", thresh2)
    cv2.waitKey(0)
    

    Adaptive Thresholding Result:

    enter image description here

    Division Normalization Result:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search