I am trying to read this image and do the arithmetic operation in the image. For some reason i am not able to read 7 because of the font it has. I am relatively new to image processing. Can you please help me with solution. I tried pixeliating the image, but that did not help.
import cv2
import pytesseract
from PIL import Image
img = cv2.imread('modules/visual_basic_math/temp2.png', cv2.IMREAD_GRAYSCALE)
thresh = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
print(pytesseract.image_to_string(img, config='--psm 6'))
Response i am getting is -
+44 849559
+46653% 14
+7776197
+6415995
+*9156346
x4463310
+54Q%433
+1664 20%
Right now, tesseract is a bit outdated. There are much more powerful libraries. I recommend PaddleOCR. To install it:
pip install paddlepaddle
pip install paddleocr
Then:
from paddleocr import PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang='es')
predictions = ocr.ocr("ietDJpng")[0]
filtered_text = []
for pred in predictions:
filtered_text.append(pred[-1][0])
filtered_text = [t.replace(" ", "") for t in filtered_text] # Remove spaces
['+4487559', '+4665714', '+7776157', ':6415995', ':9156346', 'x4463310', '-54q7433', '+1664207']
The output is not completely correct (the division symbols are : and one of them is wrong). Also, it confuses a 9 with a q). However, the results are better and the use of the library is as comfortable as tesseract.
Hope it helps!
Related
I'm a programmer, but i have no prior experience with Python or any of its libraries, or even OCR/ALPR as a whole. I have a script that i made (basically copying and paste other scripts for all over the web) that I pretend to use to recognize License Plates. But the reality is my code is very bad right now. It can recognize text in images pretty well, but it sucks to capture license plates. Very rarely i can get a License Plate with it.
So I would like some help on how should I change my code to make it better.
In my code, I simply choose an image, convert it to binary and BW, and try to read it.
I ONLY NEED the string (image_to_string); I do NOT NEED THE IMAGE.
Also is important to note that, as I said, I have no expertise with this code or the functions I'm using.
My code:
from PIL import Image
import pytesseract
import numpy as np
import cv2
image = cv2.imread('redcar.jpg')
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
se=cv2.getStructuringElement(cv2.MORPH_RECT , (8,8))
bg=cv2.morphologyEx(image, cv2.MORPH_DILATE, se)
out_gray=cv2.divide(image, bg, scale=255)
out_binary=cv2.threshold(out_gray, 0, 255, cv2.THRESH_OTSU )[1]
#cv2.imshow('binary', out_binary)
cv2.imwrite('binary.png',out_binary)
#cv2.imshow('gray', out_gray)
cv2.imwrite('gray.png',out_gray)
filename = 'gray.png'
img1 = np.array(Image.open(filename))
text = pytesseract.image_to_string(filename,config ='--psm 6')
print(text)
The image I'm using:
I hope easyocr will be helpfull in such case. You can install easyocr by pip install easyocr with opencv version of opencv-python-4.5.4.60
import easyocr
IMAGE_PATH = 'AQFCB.jpg'
reader = easyocr.Reader(['en'])
result = reader.readtext(IMAGE_PATH)
for detection in result:
if detection[2] > 0.5:
print(detection[1])
the output is
HR.26 BR.9044
My code is:
import cv2,numpy
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" # For Windows OS
def scan(image):
try:
img = cv2.cvtColor(numpy.array(image), cv2.COLOR_RGB2BGR)
except:
img = cv2.imread(image)
# Apply OCR
data = pytesseract.image_to_string(img, config="-c tessedit"
"_char_whitelist=1234567890"
" --psm 6"
" ")
return data
And when I make it scan this image it just gives me ''. Nothing. I don't know whats wrong, works on every other digit number, what should I change? If you have some python ocr that works on this image, you can also send it.
Using Tesseract or any OCR can get really tricky. The pictures you mentioned worked perfectly might have better quality or are closely related to the dataset version you are using in your code/computer.
Some basic steps you can do to improve this are:
Add a new trained data file that has similar font to the font you are trying to detect
Do some preprocessing on the image, sharpen it, change resolution and color, basically the whole routine till you find the perfect mix
Try a different OCR
Let me know if this works!
Read the documentation, understand what are you doing and you will get the correct result. Hint: pretending that the single character is a uniform block of text is not wise.
Your picture works for me. My guess is that you didn't successfully read the image? You can debug by print(img.shape) or if img is None: print('None'). Python might be operating in a different directory. os.getcwd() gets Pythons current working directory. You can also do os.path.isfile(image) to see if Python can find file where you are looking.
This is what I tried:
import cv2,numpy
import pytesseract
# ~ pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" # For Windows OS
img = cv2.imread('niner.png')
# Apply OCR
data = pytesseract.image_to_string(img, config="-c tessedit"
"_char_whitelist=1234567890"
" --psm 6"
" ")
print('tesseract version: ', pytesseract.get_tesseract_version())
print('=============================================')
print(data)
and the result is:
tesseract version: 4.0.0.20181030
leptonica-1.76.0
libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.3) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.2.0
=============================================
9
♀
I want to read the text from an image.
I use pytesseract in Python.
Here is my code:
import pytesseract
from PIL import Image
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
image = Image.open(r'a.jpg')
image.resize((150, 50),Image.ANTIALIAS).save("pic.jpg")
image = Image.open("pic.jpg")
captcha = pytesseract.image_to_string(image).replace(" ", "").replace("-", "").replace("$", "")
image
However, it returns empty string.
What should be the correct way?
Thanks.
i agree with #Jon Betts
tesseract is not very strong in OCR, only good in binary cases with right settings
CAPTCHAs ment to fool OCRs!
but if you really need to do it, you need to come up with the manual procedure for it,
i created the code below specifically for the type of CAPTCHAs that you gave (but its completely rigid and is not generalized/optimized for all cases)
psudo code
apply median blur
apply a threshold to get Blue colors only (binary image output from this stage)
apply opening to reduce small white pixels in binary image
give the image to tesseract with options:
limited whitelist of output chars
OEM 3 : tesseract + cube
PSM 8 : one word per image
Code
from PIL import Image
import pytesseract
import numpy as np
import cv2
img = cv2.imread('a.jpg')
img = cv2.medianBlur(img, 3)
# extract blue parts
img2 = np.zeros((img.shape[0], img.shape[1]), dtype=np.uint8)
cond = np.bitwise_and(img[:, :, 0] >= 100, img[:, :, 2] < 100)
img2[np.where(cond)] = 255
img = img2
# delete the noise
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
str1 = pytesseract.image_to_string(Image.fromarray(img),
config='-c tessedit_char_whitelist=abcedfghijklmnopqrtuvwxyz0123456789 -oem 3 -psm 8')
cv2.imwrite("frame.png", img)
print(str1)
output
f2e4
image
in order to see full options of tesseract, type the following command tesseract --help-extra or refere to this_link
Tesseract is intended for performing OCR on text documents. In my experience it's good but a bit patchy even with very clean data.
In this case it appears you are trying to solve a CAPTCHA which is specifically designed to defeat OCR software. It's very likely you cannot use Tesseract to solve this issue, because:
It's not really designed for that
The scenario is adversarial:
The example is specifically designed to prevent what you are trying to do
If you could get it to work, the other party would likely change it to break again
If you want to proceed I would suggest:
Working on cleaning up the image before attempting to process it (can you get a nice readable black and white image?)
Train your own recognition network using a lot of examples
I am working with python to make an OCR system that reads from the ID Cards and give the exact results from the image but it is not giving me the righteous answers as there are so many wrong characters that the tesseract reads. How can I train tesseract in a way that it reads the ID card perfectly and gives us the right and exact details, furthermore how can I get myself to the .tiff file and to make tesseract work for my project.
Steps to improve Pytesseract recognition:
Clean your image arrays so there is only text(font generated, not handwritten). The edges of letters should be without distortion. Apply threshold (try different values). Also apply some smoothing filters. I also recommend to use Morpholofical opening/closing - but thats only a bonus. This is exaggerated example of what should enter pytesseract recognition in form of array: https://i.ytimg.com/vi/1ns8tGgdpLY/maxresdefault.jpg
Resize the image with text you want to recognize to higher resolution
Pytesseract should generally recognize letters of any kind, but by installing font in which the text is written, you are superbly increasing accuracy.
How to install new fonts into pytesseract:
Get your desired font in TIFF format
Upload it to http://trainyourtesseract.com/ and receive trained data into your email (EDIT: This site doesnt exist anymore. At this moment you have to find alternative or train font yourself)
add the trained data file (*.traineddata) to this folder C:\Program Files (x86)\Tesseract-OCR\tessdata
add this string command to pytesseract reconition function:
lets say you have 2 trained fonts: font1.traineddata and font2.traineddata
To use both, use this command
txt = pytesseract.image_to_string(img, lang='font1+font2')
Here is a code to test your recognition on web images:
import cv2
import pytesseract
import cv2
import numpy as np
import urllib
import requests
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract'
TESSDATA_PREFIX = 'C:/Program Files (x86)/Tesseract-OCR'
from PIL import Image
def url_to_image(url):
resp = urllib.request.urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
return image
url='http://jeroen.github.io/images/testocr.png'
img = url_to_image(url)
#img = cv2.GaussianBlur(img,(5,5),0)
img = cv2.medianBlur(img,5)
retval, img = cv2.threshold(img,150,255, cv2.THRESH_BINARY)
txt = pytesseract.image_to_string(img, lang='eng')
print('recognition:', txt)
>>> txt
'This ts a lot of 12 point text to test the\nocr code and see if it works on all types\nof file format\n\nThe quick brown dog jumped over the\nlazy fox The quick brown dog jumped\nover the lazy fox The quick brown dog\njumped over the lazy fox The quick\nbrown dog jumped over the lazy fox'
Obviously this image is pretty tough as it is low clarity and is not a real word. However, with this code, I'm detecting nothing close:
import pytesseract
from PIL import Image, ImageEnhance, ImageFilter
image_name = 'NedNoodleArms.jpg'
im = Image.open(image_name)
im = im.filter(ImageFilter.MedianFilter())
enhancer = ImageEnhance.Contrast(im)
im = enhancer.enhance(2)
im = im.convert('1')
im.save(image_name)
text = pytesseract.image_to_string(Image.open(image_name))
print(text)
outputs
, Mdfiaodfiamms
Any ideas here? The image my contrasting function produces is:
Which looks decent? I don't have a ton of OCR experience. What preprocessing would you recommend here? I've tried resizing the image larger, which helps a little bit but not enough, along with a bunch of different filters from PIL. Nothing getting particularly close though
You are right, tesseract works better with higher resolutions so sometimes resizing the image helps - but don't convert to 1 bit.
I got good results converting to grayscale, making it 3 times as large and making the letters a bit brighter:
>>> im = Image.open('j78TY.png')\
.convert('L').resize([3 * _ for _ in im.size], Image.BICUBIC)\
.point(lambda p: p > 75 and p + 100)
>>> pytesseract.image_to_string(im)
'NedNoodleArms'
Check this jupyter notebook: