How to extract letter from an image using pytesseract - python-3.x

my problem is that I have an image that is this the image and I would like to know how to extract all the letters that can be seen in it. I have already tried with pytesseract but it returns me HANUTG and it therefore forgets the I. Here is my code:
import cv2
from PIL import Image, ImageEnhance, ImageFilter
im = cv2.imread("crop1.jpg")
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
print(pytesseract.image_to_string(im, config='--psm 13 --oem 1 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
It is not very long but sufficient to extract the letters except apparently the I, I tested with other letters and there are some others who are not recognized too, how to do?

You need to process the image before feeding it to the tesseract as input when you couldn't get the desired output.
For example:
You could apply some adaptive-thresholding and add some white-borders to the current image. Results:
Adaptive-thresh result
White-border
now when you feed it to the tesseract:
H | AN U T G
Code:
import cv2
import pytesseract
bgr_img = cv2.imread("53wU6.jpg") # Load the image
gry_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gry_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 21)
border_img = cv2.copyMakeBorder(gry_img, 50, 50, 50, 50, cv2.BORDER_CONSTANT, value=255)
txt = pytesseract.image_to_string(border_img, config='--psm 6')
print(txt)
Suggested reading: Improving the quality of the output

Related

Alphanumeric recognition problem in pytesseract and opencv

I am new to image processing. I am going to detect characters in the image using below code but the problem it does not detect characters that are very adjacent to the boundary.
import cv2
import numpy as np
import pytesseract
try:
import Image, ImageOps, ImageEnhance, imread
except ImportError:
from PIL import Image, ImageOps, ImageEnhance
image = cv2.imread(r"bmdc2.jpg")
image = cv2.blur(image, (3, 3))
ret, image = cv2.threshold(image, 90, 255, cv2.THRESH_BINARY)
image = cv2.dilate(image, np.ones((3, 1), np.uint8))
image = cv2.erode(image, np.ones((2, 2), np.uint8))
#image = cv2.dilate(image, np.ones((2, 2), np.uint8))
#enlarge the image to get rid off boundary letter
cv2.resize(image,(200,80))
cv2.imshow("1", image)
cv2.waitKey(0)
#convert to image in memroy
img = Image.fromarray(image)
text = pytesseract.image_to_string(img)
print(text)
cv2.imshow("1", np.array(image))
cv2.waitKey(0)
Image I am trying to read but it is detected as 8677 without beginning 6. is detected as 460973, as 25469.
Any better solution is welcome. Image sample can be found at https://www.bmdc.org.bd/search-doctor

why does opencv threshold returns absurd output on a very simple image?

I am trying to count seeds in an image using cv2 thresholding. The test image is below:
When I run the below code to create a mask:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('S__14278933.jpg')
#img = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
mask = cv2.threshold(img[:, :, 0], 255, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
plt.imshow(mask)
I get the following mask:
But ideally it should give a small yellow dot at the centre. I have tried this with other images and it works just fine.
Can someone help?
The lighting in your image seems not uniform. Try using Adaptive Thresholding:
import cv2
import numpy as np
# image path
path = "D://opencvImages//"
fileName = "c6pBO.jpg"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Convert the image to grayscale:
grayImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Get binary image via Adaptive Thresholding :
windowSize = 31
windowConstant = 40
binaryImage = cv2.adaptiveThreshold( grayImage, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, windowSize, windowConstant )
cv2.imshow("binaryImage", binaryImage)
cv2.waitKey(0)
You might want to apply an Area Filter after this, though, as dark portions on the image will yield noise.
Try it
img=cv2.imread('foto.jpg',0)
mask = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV )[1]

Pytesseract Image OCR - digits not recogized

I have this image.
Running Pytesseract with python 3.8 produced follwoing problem:
The word "phone" is read as O (not zero, O as in oscar)
The word "Fax" is read as 2%.
The phone number is read as (56031770
The image in consideration does not contain the boxes.The boxes are taken from the cv2 output after applying boxes around detected text regions / words.
The fax number is read without a problem. (866)357-7704 (includeing the parentheses and the hyphen)
The image size is 23 megapixels (converted from a pdf file)
The image has been preporcessed with a threshholding in opencv so that you get a binary image
The image does not contain bold fonts. So I did not use any erosion.
What can I do to properly read the Phone Number?
Thank you.
PS: I am using image_to_data (not image_to_text) as I would need to know the locations of the strings on the page as well.
Edit: here is the relevant part of code:
from PIL import Image
import pytesseract
from pytesseract import Output
import argparse
import cv2
import os
import numpy as np
import math
from pdf2image import convert_from_path
from scipy.signal import convolve2d
import string
filename = "image.png"
image = cv2.imread(filename)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# estimate noise on image
H, W = gray.shape
M = [[1, -2, 1],
[-2, 4, -2],
[1, -2, 1]]
sigma = np.sum(np.sum(np.absolute(convolve2d(gray, M))))
sigma = sigma * math.sqrt(0.5 * math.pi) / (6 * (W-2) * (H-2))
# if image has too much noise then go with blurring method
if sigma > 10 :
# noisy
gray = cv2.medianBlur(gray, 3)
print("noises deblurred")
# otherwise go with threshholding method
else :
gray = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
print("threshhold applied")
d = pytesseract.image_to_data(gray, output_type=Output.DICT)
for t in d['text'] :
print(t)
This will thus be psm 3 (default)
Version :
Tesseract : tesseract 4.1.1 (retrieved with tesseract --version) &
pytessract : Version: 0.3.2 (retrieved with pip3 show pytesseract)

Unable to properly read text from image which has a Color text in python

What I tried so far. it's working fine most of image which is text black and background is white.
from PIL import Image
import pytesseract
import nltk
import cv2
imageName = "p9.png"
img = cv2.imread(imageName,cv2.IMREAD_COLOR) #Open the image from which charectors has to be recognized
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #convert to grey to reduce detials
gray = cv2.bilateralFilter(gray, 11, 17, 17) #Blur to reduce noise
original = pytesseract.image_to_string(gray, config='')
print (original)
but below image I do not give right text.
Output:
REMIUM OKING OIL
KETTLE-RENDERED 9s MADE FROM POR siren!
fatworks €)
NET WT. 4 02 (3966)
how to resolve this issue.
What I meant is
imageName = "p9.png"
img = cv2.imread(imageName,cv2.IMREAD_COLOR) #Open the image from which charectors has to be recognized
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #convert to grey to reduce detials
gray = cv2.bilateralFilter(gray, 11, 17, 17) #Blur to reduce noise
img = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,71,2)
#img = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
cv2.THRESH_BINARY,11,2)
original = pytesseract.image_to_string(img, config='')
Play around with parameters of this function to find what works for you best
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]).
I also keep here a link to original tutorial: https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html

How to make image more contrast, grayscale then get all characters exactly with PIL and pytesseract?

PLease download the attatchment here and save it as /tmp/target.jpg.
You can see that there are 0244R in the jpg,i extract string with below python code:
from PIL import Image
import pytesseract
import cv2
filename = "/tmp/target.jpg"
image = cv2.imread(filename)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, threshold = cv2.threshold(gray,55, 255, cv2.THRESH_BINARY)
print(pytesseract.image_to_string(threshold))
What I get is
0244K
The right string is 0244R,how to make image more contrast, grayscale then get all characters exactly with with PIL and pytesseract?
Here is the webpage which generate the image :
http://www.crup.cn/ValidateCode/Index?t=0.14978241776661583
If you apply adaptive-thresholding and bitwise-not operations to the input image, the result will be:
Now if you remove the special characters like (dot, comma, etc..)
txt = pytesseract.image_to_string(bnt, config="--psm 6")
res = ''.join(i for i in txt if i.isalnum())
print(res)
Result will be:
O244R
Code:
import cv2
import pytesseract
img = cv2.imread("Aw6sN.jpg")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thr = cv2.adaptiveThreshold(gry, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 23, 100)
bnt = cv2.bitwise_not(thr)
txt = pytesseract.image_to_string(bnt, config="--psm 6")
res = ''.join(i for i in txt if i.isalnum())
print(res)

Resources