OCR OpenCV in Forms and Receipts

Packages

  • opencv-pyhton
  • numpy
  • pytesseract
  • os

Installation of packages in PyCharm IDE

import cv2
import numpy as np
import pytesseract
import os
pytesseract.pytesseract.tesseract_cmd = 'C:\Program Files\Tesseract-OCR\tesseract.exe'

Feature Detection

Import Image

ocr opencv form
The Awesomeness Form

imgQ = cv2.imread('Query.png')

Feature of Query Image

orb = cv2.ORB_create()

orb = cv2.ORB_create(nfeatures=1000)

What are Features ?

What are features?

kp1, des1 = orb.detectAndCompute(imgQ, None)
imgKp1 = cv2.drawKeypoints(img1,kp1,None)

Importing User Forms

path ='UserForms'
myPicList = os.listdir(path)
print(myPicList)
print('Total Images {}'.format(len(myPicList)))

for j,y in enumerate(myPicList):
    img = cv2.imread(path+"/"+y)

kp2, des2 = orb.detectAndCompute(img, None)
imgKp2 = cv2.drawKeypoints(img,kp2,None)

bf = cv2.BFMatcher(cv2.NORM_HAMMING)
matches = bf.match(des2, des1)

matches.sort(key = lambda x: x.distance)
good = matches[:int(len(matches)*(per/100))]
imgMatches = cv2.drawMatches(img, kp2, imgQ, kp1, good,None, flags=2)
Feature Matching Result on one of the user forms

Aligning The Forms

  srcPts = np.float32([kp2[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
  dstPts = np.float32([kp1[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
  M, _ = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)

h, w = imgQ.shape[:2]
imgScan = cv2.warpPerspective(img, M, (w, h))

imgShow = imgScan.copy()
imgMask = np.zeros_like(imgShow)

Text Detection

myData = []
print(f'####### Extracting Data from Form {

ROI Selector

  1. How to get the ROI for the form?
  2. How to handle checkbox input?

"""
This script allows to collect raw points from an image.
The inputs are two mouse clicks one in the 0,0 position and
the second in (w,h)/diagonal position of a rectangle.
Once a rectangle is selected the user is asked to enter the type
and the Name:
Type can be 'text' or 'box'
Name can be anything
"""
import cv2
import random
path= 'Query.png'
scale = 0.4
circles = []
counter = 0
counter2 = 0
point1=[]
point2=[]
myPoints = []
myColor=[]
def mousePoints(event,x,y,flags,params):
    global counter,point1,point2,counter2,circles,myColor
    if event == cv2.EVENT_LBUTTONDOWN:
        if counter==0:
            point1=int(x//scale),int(y//scale);
            counter +=1
            myColor = (random.randint(0,2)*200,random.randint(0,2)*200,random.randint(0,2)*200 )
        elif counter ==1:
            point2=int(x//scale),int(y//scale)
            type = input('Enter Type')
            name = input ('Enter Name ')
            myPoints.append([point1,point2,type,name])
            counter=0
        circles.append([x,y,myColor])
        counter2 += 1
img = cv2.imread(path)
img = cv2.resize(img, (0, 0), None, scale, scale)
while True:
    # To Display points
    for x,y,color in circles:
        cv2.circle(img,(x,y),3,color,cv2.FILLED)
    cv2.imshow("Original Image ", img)
    cv2.setMouseCallback("Original Image ", mousePoints)
    if cv2.waitKey(1) & 0xFF == ord('s'):
        print(myPoints)
        break

for x,r in enumerate(roi):
        # For displaying the rois
        cv2.rectangle(imgMask, (r[0][0], r[0][1]), (r[1][0], r[1][1]), (0, 
        255,0), cv2.FILLED)
        imgShow = cv2.addWeighted(imgShow, 0.99, imgMask, 0.1, 0)

OCR with Pytesseract

imgCrop= imgScan[r[0][1]:r[1][1],r[0][0]:r[1][0]]

if r[2] == 'text':
            print('{}: {}'.format(r[3],pytesseract.image_to_string(imgCrop)))
            myData.append(pytesseract.image_to_string(imgCrop))

Check Box Input

        if r[2] == 'box':
            imgWarpGray = cv2.cvtColor(imgCrop, cv2.COLOR_BGR2GRAY)  
            imgThresh = cv2.threshold(imgWarpGray, 170, 255, 
            cv2.THRESH_BINARY_INV)[1]  # APPLY THRESHOLD AND INVERSE
            totalPixels = cv2.countNonZero(imgThresh)
            if totalPixels>minThreshold:totalPixels=1
            else:totalPixels=0
            print(f'{r[3]}: {totalPixels}')
            myData.append(totalPixels)

        cv2.putText(imgShow,str(myData[x]),(r[0][0], r[0][1]),
                   cv2.FONT_HERSHEY_PLAIN,2.5,(0,0,255),4)

Saving Data to File

with open('DataOutput.csv','a+') as f:
        for data in myData:
            f.write(str(data)+',')
        f.write('n')

Result

    imgShow = cv2.resize(imgShow, (w // 3, h // 3))
    cv2.imshow(y,imgShow)
    cv2.waitKey(1)

Video Tutorial

Part 1

Part 2

Complete Code

Share

Leave a Reply

Your email address will not be published. Required fields are marked *