unable to get text from the image - opencv

I'm learning AI/ML and trying to get text from this sample form.
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r'C:\Users\Pranav\AppData\Local\Programs\Tesseract-OCR\tesseract.exe'
image = cv2.imread('image2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
x,y,w,h = 393, 531, 837, 80
firstROI = blur[y:y+h,x:x+w]
firstname = pytesseract.image_to_string(firstROI, lang='eng', config='--psm 6')
print(firstname)
firstname = re.sub(r'[^\w]', '', firstname)
cv2.imshow('image', firstROI)
cv2.waitKey()
cv2.destroyAllWindows()
Using the above code, I can able to get text the normal printed text in the white background but unable to get the text from the grey background boxes. For example, first name box real value is "Andrew" but I m getting as "oe" only.
firstROI shows like this:
As per Freddy's comments, I go through this link and updated the following code but still no output.
from tesserocr import PyTessBaseAPI, PSM, OEM
api = PyTessBaseAPI(psm=PSM.AUTO_OSD, lang='eng', path=r'C:\Users\Pranav\tessdata-master')
images = ['andrew1.png', 'andrew2.png', 'test1.png']
for img in images:
api.SetImageFile(img)
print (api.GetUTF8Text())
print (api.AllWordConfidences())
these are the sample images
It can read the text output from the third image only(Demographics). Please help me how to read the text from gray background images(Andrew).

This link provides me the answer. Its removing the noise in the background image.

Related

Resize a small image to get the text from it using python

I'm new to image processing libraries in python, currently i'm failing trying to get a text from a small image 147x15 with a transparent background. One way to perform that is to resize the image by making it bigger and trying not to loose quality so it can be well interpreted, there is the original image link:
(147x15)
https://www.lespagesmaghreb.com/generated/contact_methods/496321.png
This is my code to get the text from the image:
import cv2
import pytesseract
from PIL import Image
pytesseract.pytesseract.tesseract_cmd = r'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'
img = cv2.imread('img_new.png')
text = pytesseract.image_to_string(img)
print(text)
And there is the expected image (181 x 80) output which works with the previous code (manually edited)
How can I perform that automatically ? thanks.
EDIT:
I tried to resize the image to 200% of it's current size, the result is a black image, this is the used code:
import cv2
img = cv2.imread('img_n.png', cv2.IMREAD_UNCHANGED)
print('Original Dimensions : ',img.shape)
scale_percent = 200 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
print('Resized Dimensions : ',resized.shape)
cv2.imshow("Resized image", resized)
cv2.waitKey(0)
cv2.destroyAllWindows()
This is the image:

Resize selected area of image

I want to increase / decrease the height of the image for the selected area only (The area between the white lines) as depicted in the image and not the outside of that area.
This is the same functionality which is performed in the app Manly - Body Muscle Editor Pro
How can I achieve that? Any help is appreciated.
I've never written code for IOS but I know OpenCV also works in IOS. Here I use the cv2.resize.
import cv2
import numpy as np
img = cv2.imread("1.jpg")
print(img.shape)
h = img.shape[0]
w = img.shape[1]
part_to_resize = img[120:240,:]
old_height = 120 #240-120
new_height = 200
final_result = np.zeros((h-(240-120)+new_height,w,3),dtype='uint8')
final_result[0:119,:] = img[0:119,:]
final_result[120:320,:] = cv2.resize(part_to_resize, (w, new_height))
final_result[321:h-old_height+new_height,:] = img[241:h,:]
cv2.imshow("final_result", final_result)
cv2.imshow("img", img)
cv2.waitKey()

error: (-215:Assertion failed) totalSampleCount > 0 in function 'GMM::endLearning'

Im trying to use the opencv to remove the background of my pictures.
When Im running a single file. It works out.
The code as below:
def bgremove(name,count):
import cv2
import numpy as np
# cv2.namedWindow('image',cv2.WINDOW_NORMAL)
#Load the Image
imgo = cv2.imread(name)# the place to input picture path
height,width = imgo.shape[:2]
#Create a mask holder
mask = np.zeros(imgo.shape[:2],np.uint8)
#Grab Cut the object
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
#Hard Coding the Rect… The object must lie within this rect.
rect = (10,10,width-30,height-30)
cv2.grabCut(imgo,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img1 = imgo*mask[:,:,np.newaxis]
#Get the background
background = imgo-img1
#Change all pixels in the background that are not black to white
background[np.where((background > [0,0,0]).all(axis = 2))] = [255,255,255]
#Add the background and the image
final = background + img1
DP1=count
#To be done – Smoothening the edges….
cv2.imwrite("A%s.JPG"%DP1, final)
However, when I use the function in a for loop. it pops-up:
error: (-215:Assertion failed) totalSampleCount > 0 in function
'GMM::endLearning'
when Im generating a group of pictures
I encountered this problem and the issue was that the rectangle rect was too small. I don't know the dimensions of your image but try a bigger rectangle and it may solve this.

Get blue colored contours using scikit-image/opencv

I'm trying to get blue colored contours using scikit-image. I'm sure there are functions in opencv that are also available in scikit-image.
I am aware of the find_contours method which works well however it gets ALL colors of contours. I just wnat to get the blue contours.
http://scikit-image.org/docs/dev/api/skimage.measure.find_contours.html
Any ideas of how to do this? My guess is to preprocess the image somehow to remove every color other than blue.
Your suggestion of first suppressing all other colors is a good one. Here's some code for doing that:
from skimage import io, color, exposure, img_as_float
import matplotlib.pyplot as plt
# http://www.publicdomainpictures.net/view-image.php?image=26890&picture=color-wheel
image = img_as_float(io.imread('color-wheel.jpg'))
blue_lab = color.rgb2lab([[[0, 0, 1.]]])
light_blue_lab = color.rgb2lab([[[0, 1, 1.]]])
red_lab = color.rgb2lab([[[1, 0, 0.]]])
image_lab = color.rgb2lab(image)
distance_blue = color.deltaE_cmc(blue_lab, image_lab, kL=0.5, kC=0.5)
distance_light_blue = color.deltaE_cmc(light_blue_lab, image_lab, kL=0.5, kC=0.5)
distance_red = color.deltaE_cmc(red_lab, image_lab, kL=0.5, kC=0.5)
distance = distance_blue + distance_light_blue - distance_red
distance = exposure.rescale_intensity(distance)
image_blue = image.copy()
image_blue[distance > 0.3] = 0
f, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(20, 10))
ax0.imshow(image)
ax1.imshow(distance, cmap='gray')
ax2.imshow(image_blue)
plt.show()

Cropping images in opencv

I have an image that has some text in it. I want to send the image to OCR but the image has some white noise in it so the OCR results aren't that great. I've tried to erode/dilate the image but couldn't get the perfect threshold to work. Since all the text in the images will be perfectly horizontal I tried the Hough Transform.
Here is what the image looks like when I run the sample hough transform program bundled with OpenCV.
Question
How can I black out everything except where the red lines are?
OR How can I crop out a separate images for each of the areas highlighted by the red lines?
I would only like to concentrate on lines that are horizontal, I can discard the diagonal lines.
Either option will work for me when sending to OCR. However, I'd like to try both to see which fetches best results.
howto/s with output
How can I black out everything except where the red lines are?
dotess2()
['Footel text goes he: e\n', 'Some mole hele\n', 'Some Text Here\n']
OR How can I crop out a separate images for each of the areas highlighted by the red lines?
dotess1()
['Foolel text goes he: e\n', 'Some mole hele\n', 'Some Text Here\n', 'Directions\n']
code
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import math
import subprocess
import os
import operator
#some clean up/init blah blah
junk='\/,-‘’“ ”?.\';!{§_~!##$%^&*()_+-|:}»£[]¢€¥°><'
tmpdir='./tmp'
if not os.path.exists(tmpdir):
os.makedirs(tmpdir)
for path, subdirs, files in os.walk(tmpdir):
for name in files:
os.remove(os.path.join(path, name))
#when the preprocessor is not pefect, there will be junk in the result. this is a crude mean of ridding them off
def resfilter(res):
rd = dict()
for l in set(res):
rd[l]=0.
for l in rd:
for i in l:
if i in junk:
rd[l]-=1
elif i.isdigit():
rd[l]+=.5
else:
rd[l]+=1
ret=[]
for v in sorted(rd.iteritems(), key=operator.itemgetter(1), reverse=True):
ret.append(v[0])
return ret
def dotess1():
res =[]
for path, subdirs, files in os.walk(tmpdir):
for name in files:
fpath = os.path.join(path, name)
img = cv2.imread(fpath)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
'''
#if the text is too small/contains noise etc, resize and maintain aspect ratio
if gray.shape[1]<100:
gray=cv2.resize(gray,(int(100/gray.shape[0]*gray.shape[1]),100))
'''
cv2.imwrite('tmp.jpg',gray)
args = ['tesseract.exe','tmp.jpg','tessres','-psm','7', '-l','eng']
subprocess.call(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with open('tessres.txt') as f:
for line in f:
if line.strip() != '':
res.append(line)
print resfilter(res)
def dotess2():
res =[]
args = ['tesseract.exe','clean.jpg','tessres','-psm','3', '-l','eng']
subprocess.call(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with open('tessres.txt') as f:
for line in f:
if line.strip() != '':
res.append(line)
print resfilter(res)
'''
start of code
'''
img = cv2.imread('c:/data/ocr3.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
canny=cv2.Canny(gray,50,200,3)
cv2.imshow('canny',canny)
#remove the actual horizontal lines so that hough wont detect them
linek = np.zeros((11,11),dtype=np.uint8)
linek[5,...]=1
x=cv2.morphologyEx(canny, cv2.MORPH_OPEN, linek ,iterations=1)
canny-=x
cv2.imshow('canny no horizontal lines',canny)
#draw a fat line so that you can box it up
lines = cv2.HoughLinesP(canny, 1, math.pi/2, 50,50, 50, 20)
linemask = np.zeros(gray.shape,gray.dtype)
for line in lines[0]:
if line[1]==line[3]:#check horizontal
pt1 = (line[0],line[1])
pt2 = (line[2],line[3])
cv2.line(linemask, pt1, pt2, (255), 30)
cv2.imshow('linemask',linemask)
'''
* two methods of doing ocr,line mode and page mode
* boxmask is used to so that a clean image can be saved for page mode
* for every detected boxes, the roi are cropped and saved so that tess3 can be run in line mode
'''
boxmask = np.zeros(gray.shape,gray.dtype)
contours,hierarchy = cv2.findContours(linemask,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
idx=0
for cnt in contours:
idx+=1
area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
roi=img[y:y+h,x:x+w].copy()
cv2.imwrite('%s/%s.jpg'%(tmpdir,str(idx)),roi)
cv2.rectangle(boxmask,(x,y),(x+w,y+h),(255),-1)
cv2.imshow('clean',img&cv2.cvtColor(boxmask,cv2.COLOR_GRAY2BGR))
cv2.imwrite('clean.jpg',img&cv2.cvtColor(boxmask,cv2.COLOR_GRAY2BGR))
cv2.imshow('img',img)
dotess1()
dotess2()
cv2.waitKey(0)

Resources