How can I extract cheque amount from cheque images? - python-3.x

I am trying to extract the cheque amount (underlined text in Input Image) from cheque images. I am trying to do this in the following 2 steps:
Locate the rectangle box of the amount in the image.
Perform OCR using OCR libraries like Tesseract OCR and get the text.
I tried to locate the rectangle box but it is locating so many things from the image.
How can we approach this problem? If anyone has a different approach to extract the amount then please guide me.
My Code
import numpy as np
import cv2
img = cv2.imread("Ex2.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
contours,_ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for contour in contours:
(x,y,w,h) = cv2.boundingRect(contour)
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
cv2.imshow('detected.jpg',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Input Image
Currently, I am getting this.

Related

Difficulty reading text with pytesseract

I need to read the highest temperature on thermographic images, as shown below:
IR_1544_INFRA.jpg
IR_1546_INFRA.jpg
IR_1560_INFRA.jpg
IR_1564_INFRA.jpg
I used the following code, this was the best result.
I also tried several other ways, such as: blur, gray scale, binarization, and others but they all failed.
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Users\User\AppData\Local\Tesseract-OCR\tesseract.exe"
# Load image, grayscale, Otsu's threshold
entrada = cv2.imread('IR_1546_INFRA.jpg')
image = entrada[40:65, 277:319]
#image = cv2.imread('IR_1546_INFRA.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = 255 - cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Blur and perform text extraction
thresh = cv2.GaussianBlur(thresh, (3,3), 0)
data = pytesseract.image_to_string(thresh, lang='eng', config='--psm 6')
print(data)
cv2.imshow('thresh', thresh)
cv2.waitKey()
In the first image, I found
this
In the second image, I found this.
The imagem layout is always the same, that is, the temperature is always in the same place, so I cropped the image to isolate only the number. I would like (97.7 here, and 85.2 here).
My code needs to find from these images to always detect this temperature and generate a list indicating from highest to lowest.
What do you indicate for me to improve the assertiveness of pytesseract in the case of these images?
Note 1: When I annalyze the entire image (without cropping), it returns data that is not even present.
Note 2: In some images even with the binary number, pytesseract (image_to_string) does not return any data.
Thank you all and sorry for the typos, writing in english is still a challenge for me.
Because you have same images, you can crop the area you want and then do processing there. The processing is also simple. Change to gray, get threshold, invert, resize, and then do the OCR. You can see it in my code below. It works on all your attached images.
import cv2
import pytesseract
import os
image_path = "temperature"
for nama_file in sorted(os.listdir(image_path)):
print(nama_file)
img = cv2.imread(os.path.join(image_path, nama_file))
crop = img[43:62, 278:319]
gray = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.bitwise_not(thresh)
double = cv2.resize(thresh, None, fx=2, fy=2)
custom_config = r'-l eng --oem 3 --psm 7 -c tessedit_char_whitelist="1234567890." '
text = pytesseract.image_to_string(double, config=custom_config)
print("detected: " + text)
cv2.imshow("img", img)
cv2.imshow("double", double)
cv2.waitKey(0)
cv2.destroyAllWindows()

How to apply threshold counters to only specified/masking region in the image using opencv

I am new in OpenCV and stuck at a point actually, I study lots of QA but all are unable or I can say not fully satisfied my requirement.
Suppose I have an image and I want to find counters for objectifying specified area only.
It is easy to counter a complete image but I want to counters only masking area.
For masking purpose I have x,y coordinates with me.
So my question is how to counter only masking area in the image using OpenCV
This is the one solution matching with my question->Stackoverflow suggestion -:
But it does not solving my problem completely.
The given solution in this solution is quite complicated and not solving my problem. as I want my counters ROI to be show in the same image using mask coordinates(xmin, ymin, xmax, ymax).
Means i first drawing reactangle mask into the image and i want to draw counters boundary only into that rectangle mask in the same image.
This is my Demo.py file:-
import cv2
img = cv2.imread("F:/mycar.jpg",1)
crop_img = cv2.rectangle(img, (631,181), (698,386), (0,255,0), 3)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
retval, thresh = cv2.threshold(gray_img, 127, 255, 0)
img_contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, img_contours, -1, (255, 0, 0))
cv2.imshow("dflj",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
output
From this image, you can see that the complete image is countering.
But I want to just counter only that green-rectangle part of the image.
Means that blue counter boundary lines is visible inside whole image but I want to show only it inside of green-rectangle box.
I have rectangle coordinates with me (eg. minx-631, miny-181, maxx-698, maxy-386).
Please help.
You can apply functions to ROIs using Numpy indexing as explained in this tutoral:
top,left = 338,282
h,w = 216,106
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
crop_img = cv2.rectangle(img, (left,top), (left+w,top+h), (0,255,0), 3)
retval, thresh = cv2.threshold(gray_img, 127, 255, 0)
img_contours, _ = cv2.findContours(thresh[top:top+h,left:left+w], cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img[top:top+h,left:left+w], img_contours, -1, (255, 0, 0))
Please note that with Numpy indexing y comes first then x, as opposed to point coordinates with (x,y).
With this image we get:

Not able to extract number from a Image

I am developing an application to read the numbers from an image using opencv in Python 3. I first converted the image to gray scale,then Apply dilation and erosion to remove some noise, then Apply threshold to get image with only black and white, then Write the image to local disk to do some ..., then apply tesseract to recognise the number for python.
I need to extract the numbers from the image. I am new to openCV. Does anybody know any other method to get the result??
I have share the image link bellow, i was trying to extract from that image. Thanks in advance
https://drive.google.com/file/d/141y-3okLPGP_STje14ukSqSHcgtwMdRO/view?usp=sharing
import cv2
import numpy as np
import pytesseract
from PIL import Image
from pytesseract import image_to_string
# Path of working folder on Disk
src_path = "/Users/sougata.a.roy/Desktop/Images/"
def get_string(img_path):
# Read image with opencv
img = cv2.imread(img_path)
# Convert to gray
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply dilation and erosion to remove some noise
kernel = np.ones((1, 1), np.uint8)
img = cv2.dilate(img, kernel, iterations=1)
img = cv2.erode(img, kernel, iterations=1)
# Write image after removed noise
cv2.imwrite(src_path + "removed_noise.jpg", img)
# Apply threshold to get image with only black and white
img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 31, 2)
# Write the image after apply opencv to do some ...
cv2.imwrite(src_path + 'thres.jpg', img)
# Recognize text with tesseract for python
result = pytesseract.image_to_string(Image.open(src_path + "thres.jpg"), lang='eng')
return result
print('--- Start recognize text from image ---')
print(get_string(src_path + 'abcdefg195.jpg'))
print("------ Done -------")
365

How to crop the green colored rectangle from an image

I need to crop an image for further processing on it using opencv and python. I need to crop the region inside the green colored rectangle in the image. The rectangle is drawn using "haar_cascade_fullbody_Detector"
The code is as follows :
import numpy as np
import cv2
bodydetection = cv2.CascadeClassifier('haarcascade_fullbody.xml')
img = cv2.imread('original.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
body = bodydetection.detectMultiScale(gray, 1.009, 5)
for x, y, w, h in body:
# so we slightly shrink the rectangles to get a nicer output.
pad_w, pad_h = int(0.15*w), int(0.02*h)
cv2.rectangle(img, (x+pad_w+10, y+pad_h+10), (x+w-pad_w, y+h-pad_h), (0, 255, 0), 2)
cv2.imshow('img',img)
crop_img = img[x:x+w, y:y+h]
cv2.imshow('crop',crop_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
The input image is :
The output of haar cascade is :
after the crop the image is :
Please suggest any solution. Thanks!
Ok! I got the answer. The line of crop_img should be modified as
crop_img = img[y:y+h, x:x+w]
This produces required output.This is because in opencv the img coordinated sequence is y-coordinates and then x-coordinates.

Extracting text OpenCV Contours

I tried doing ocr of each individual contour using tesseract but not getting proper text out of it. Contour Identification is done properly by using Extracting text OpenCV.
Please suggest.
You are not getting proper text from OCR because of bad image pre-processing.
Try various image processing techniques to narrow down on a workable approach for your image.
As you have asked under python, If you have a colour image,
Convert it into black and white image, to remove the colour noise.
img = cv2.imread('name_of_the_coloured_input_image',0)
Blur the image using blurring techniques of opencv (averaging, gaussian blurring, median blurring and bilateral filtering), this decreases various noises in the image.
Please refer to this link and try out various techniques
Then use thresholding (simple, adaptive or otsu thresholding), which removes all the pixels which are less than a certain threshold.
Please refer to this link and try out various techniques
Now, get contours and try using tesseract on the contours to get better results.
Note : Please remember that for tesseract to work, you should have the text in black against a white background.
Please check for the below function, tell me if anything is missing.
#gray out the image
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
cv2.waitKey(0)
#image blurring
blur = cv2.blur(gray,(1,1))
cv2.imshow('Blur', blur)
cv2.waitKey(0)
#threshold & invert
ret, thresh = cv2.threshold(blur, 127, 255, cv2.THRESH_BINARY_INV)
thresh_copy = thresh.copy()
cv2.imshow("Threshold", thresh_copy)
cv2.waitKey(0)
#Erosion
kernel1 = np.ones((1,1), np.uint8)
img_erosion = cv2.erode(thresh, kernel1, iterations=1)
cv2.imshow("Erosion", img_erosion.copy())
cv2.waitKey(0)
#applying dilation
kernel = np.ones((6,10), np.uint8)
img_dilation = cv2.dilate(img_erosion.copy(), kernel, iterations=1)
cv2.imshow("Dilation", img_dilation)
cv2.waitKey(0)
#find contours
im2, ctrs, hier = cv2.findContours(img_dilation.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
return ctrs

Resources