Pytesseract Image OCR - digits not recogized - python-3.x

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)

Related

Tesseract doesn't fetch data clearly

In this Python script, First I increase the image Resolution for better accuracy of OCR.
Second, I apply many filters to that image to increase contrast and text clarity.
Third, I fetch text from filtered image using Tesseract But the issue is Tesseract doesn't fetch data clearly.
And also tried to add page segmentation modes and OCR Engine modes on the pytesseract but did not receive the expected output.
This is my Code...
import os,argparse
import pytesseract
from pytesseract import Output
import csv
import numpy as np
from PIL import Image
image = cv2.imread('dota.jpg')
height = 9000
width = 16000
dimensions = (width, height)
image = cv2.resize(image,dimensions, interpolation=cv2.INTER_LINEAR)
def get_grayscale(image):
return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
def adaptiveThreshold(image):
return cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
gray = get_grayscale(image)
sharpenKernel = np.array(([[2, -1, 2], [-1, 9, -1], [2, -1, 2]]), np.float32)/9
sharpen = cv2.filter2D(src=gray, kernel=sharpenKernel, ddepth=-1)
adthresh = adaptiveThreshold(sharpen)
cong = '--psm 6'
final = pytesseract.image_to_data(adthresh,output_type=Output.DICT,config=cong,lang='eng')
print(final['text'])
Also, this code is available on Github.
: https://github.com/Bhavin-Prydan/Dota-Esportz/blob/main/dota.py

How to extract letter from an image using pytesseract

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

Image Cropping to get just the particular shape out of image

[I have the images as below, i need to extract just the white strip portion from all the images.
i Have tried using PIL to extract the rectangular portion by manually specifying the pixel value, Can there be any automated way to get this work done where by just feeding the image gives back the rectangular portion
Below is My snipped code:
from PIL import Image
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = Image.open('C:/Users/ShAgarwal/Documents/image_dataset/pic9.jpg')
half_the_width = img.size[0] / 2
half_the_height = img.size[1] / 2
img4 = img.crop(
(
half_the_width-1632,
half_the_height - 440,
half_the_width+1632,
half_the_height + 80
)
)
sample image
import cv2
import numpy as np
from matplotlib import pyplot as plt
image='IMG_3134.JPG'
# read image
imgc = cv2.imread(image)
img = cv2.resize(imgc, None, fx=0.25, fy=0.25) # resize since image is huge
#cropping the strip dimensions
#crop_img = img[1010:1650,140:1099723]
blurred = cv2.blur(img, (3,3))
canny = cv2.Canny(blurred, 50, 200)
Marking coordinates through auto image detection using canny's algorithm
## find the non-zero min-max coords of canny
pts = np.argwhere(canny>0)
y1,x1 = pts.min(axis=0)
y2,x2 = pts.max(axis=0)`
`## crop the region
cropped = img[y1:y2, x1:x2]
cv2.imwrite("cropped.png", cropped)
#Select the bounded area around white boundary
tagged = cv2.rectangle(img.copy(), (x1,y1), (x2,y2), (0,255,0), 3, cv2.LINE_AA)
r = cv2.selectROI(tagged)
imCrop = im[int(r[1]):int(r[1]+r[3]), int(r[0]):int(r[0]+r[2])]
#Bounded Area
cv2.imwrite("taggd2.png", imcrop)
cv2.waitKey()
Results from above code

How to detect Roads from satellite images and get the outline using opencv python

Hey guys, I am trying to detect roads from satellite images.
After identifying the roads am getting the co-ordinates like roads coordinates and building coordinates.
The code which i tried to extract roads from satellite images.
Input image
from __future__ import print_function, division
from PIL import Image
import operator
import cv2
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
#reading image directly from current working directly
build_image = cv2.imread("avilla_san_marcos_gilbert,az.png")
#Doing MeanShift Filtering
#shifted = cv2.pyrMeanShiftFiltering(image, 21, 51)
#GrayScale Conversion
build_gray = cv2.cvtColor(build_image, cv2.COLOR_BGR2GRAY)
#OTSU Thresholding
thresh = cv2.threshold(build_gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("OTSU Thresholded Image",thresh)
cv2.imwrite("OTSU_1 image.jpg",thresh)
#Checking Coordinates of White Pixels
build_white = np.argwhere(thresh == 255)
#Creating an array
build_data= np.array(build_white)
np.savetxt('build_coords.csv', build_data,delimiter=",")
#Checking Coordinates of White Pixels
road_white = np.argwhere(thresh == 0)
#Creating an array
road_data = np.array(road_white)
print(road_data)
#Saving vector of roads in a csv file
np.savetxt('road_coords.csv', road_data,delimiter=",")
Output image is plotted based on csv of Road pixel Coordinates
I have a problem with the output image obtained. It has detected trees i have to eliminate it by obtaining the pixel coordinates of tree.
So From that output image i have to extract the layout of the roads alone.Please try to help me out guys. Thanks in advance.

Crop an image to smaller size from left to right and top to bottom using OpenCV

I have an image 315x581. I want to crop it in 28x28 from top left to bottom right, then I need to save each 28x28 image in folder.
I could crop just one image from y1=0 to y2=28 and x1=0 to x2=28.
First problem is: I used cv2.imwrite("cropped.jpg", cropped) to save this small image, but It doesn't save it, provided that it works some line above.
Second problem is: How can I write a code which it keeps on cropping the image in 28x28 from left to right and top to bottom and save each subimage.
I used for loop, but I don't know how to complete it.
Thank you so much for any help.
Here this is my code,
import cv2
import numpy as np
from PIL import Image
import PIL.Image
import os
import gzip
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.cm as cm
#%%
image1LL='C:/Users/Tala/Documents/PythonProjects/Poster-OpenCV-MaskXray/CHNCXR_0001_0_LL.jpg'
mask1LL='C:/Users/Tala/Documents/PythonProjects/Poster-OpenCV-MaskXray/CHNCXR_0001_0_threshLL.jpg'
#finalsSave='C:/Users/Tala/Documents/PythonProjects/Poster-OpenCV-MaskXray/Xray Result'
# load the image
img = cv2.imread(image1LL,0)
mask = cv2.imread(mask1LL,0)
# combine foreground+background
final1LL = cv2.bitwise_and(img,img,mask = mask)
cv2.imshow('final1LL',final1LL)
cv2.waitKey(100)
final1LL.size
final1LL.shape
# Save the image
cv2.imwrite('final1LL.jpg',final1LL)
# crop the image using array slices -- it's a NumPy array
# after all!
y1=0
x1=0
for y2 in range(0,580,28):
for x2 in range(0,314,28):
cropped = final1LL[0:28, 0:28]
cv2.imshow('cropped', cropped)
cv2.waitKey(100)
cv2.imwrite("cropped.jpg", cropped)
Your approach is good, but there is some fine tuning required. The following code will help you:
import cv2
filename = 'p1.jpg'
img = cv2.imread(filename, 1)
interval = 100
stride = 100
count = 0
print img.shape
for i in range(0, img.shape[0], interval):
for j in range(0, img.shape[1], interval):
print j
cropped_img = img[j:j + stride, i:i + stride] #--- Notice this part where you have to add the stride as well ---
count += 1
cv2.imwrite('cropped_image_' + str(count) + '_.jpg', cropped_img) #--- Also take note of how you would save all the cropped images by incrementing the count variable ---
cv2.waitKey()
My result:
Original image:
Some of the cropped images:
Cropped image 1
Cropped image 2
Cropped image 3
If you are using it in PyTorch as a deep learning framework, then this task would be quite easy and can be done without the need for any other external image processing libraries such as OpenCV. The below code will convert a single image into a stack of multiple images in a form of PyTorch tensor. If you want to use only images then you need to remove the line "transforms.ToTensor()" and save the "tens" variable in the code as an image using matplotlib.
Note: Here bird image is used with dimension 32 x 32 x 3, crop images 5x5x3 with stride =1.
image = Image.open('bird.png')
tensreal = trans(image)
trans = transforms.Compose([transforms.Resize(32),
transforms.ToTensor(),
])
stride = 1
crop_height = 5
crop_width = 5
img_height = 32
img_width = 32
tens_list = []
for i in range(0,img_width-crop_width,stride):
for j in range(0,img_height-crop_height ,stride):
tens = trans(image)
tens1 = tens[:, j:j+crop_height, i:i+crop_width]
tens_list.append(tens1)
all_tens = torch.stack(tens_list)
print(all_tens.size())

Resources