How you can get started with Tesseract | by Kaan Kuguoglu | Towards Data Science

It’s far from a secret that Tesseract is not an all-in-one OCR tool that recognizes all sorts of texts and drawings. In fact, this couldn’t be further from the truth. If this was a secret, I’ve already spoiled it, and it’s already too late to go back anyway. So, why not dive deep into Tesseract and share a few tips and tricks that could improve your results?
Really, though. I do appreciate all those developers who contribute to open-source projects without expecting any benefits in return. After all, they provide us with relatively difficult capabilities for individuals to achieve, such as creating Deep Neural Networks via TensorFlow without much of the hassle. Who would have thought that Machine Learning would be as accessible as it is today?
Tesseract, too, helps us accomplish simple OCR tasks with a significant success rate and is completely open-source. In this post, I’ll try to get you going with Tesseract and hopefully help you clear some of the hurdles that you might face while working with it.
Even though there are quite a few options in the field, for example, OCRopus, Tesseract still seems to be the first choice for most free riders. Well, that all adds up if you consider Tesseract is still being developed by the Google community and has constantly grown over time. However, if you’ve had experience with Tesseract before, you might have noticed that Tesseract is likely to disappoint you when it comes to image pre-processing or custom font training.
Leaving custom font training for a later discussion, for now, I’ll be mainly focusing on going over the basics to get you started with Tesseract. First, let’s quickly go over the installation.
I’ll be using HomeBrew, a package manager, to install Tesseract libraries. After installing HomeBrew, you should prompt the following command.
$ brew install tesseract
Or, you could also do the same thing with MacPorts if you wish.
$ sudo port install tesseract
On Ubuntu, it’s quite simple as well.
$ sudo apt-get install tesseract-ocr
For Windows, you can download the unofficial installer from the official GitHub Repository. What a sentence, eh?
To verify if Tesseract is successfully installed, you can hit your terminal and type the following.
$ tesseract -v
If you receive a few lines of prompt similar to the one below, your Tesseract is installed correctly. Otherwise, you might want to check what has gone wrong by starting from your PATH variable in your system.
tesseract 3.05.01 leptonica-1.74.4  libjpeg 9c : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11
To start with, Tesseract is not a Python library. Nor does it have an official wrapper for Python. This is where all those golden-hearted developers came in and created this awesome Python wrapper, pytesseract, for us. We also need to install OpenCV and PIL for manipulating images.
$ pip install pillow$ pip install pytesseract$ pip install opencv-python
And that’s it!
Now, you got your Tesseract installed on your computer, ready to work with Python. So what are you waiting for? Well, there’s no one holding you back; please go ahead and try it out. Here comes a “but,” though. As stated in many articles, including the official documentation, Tesseract is likely to fail without image pre-processing.
For quite some time, I’ve been a regular visitor of the ImproveQuality page in TensorFlow’s repository, where they name a few methods you can try to improve your accuracy. Although it claims to have various image processing operations internally, it’s quite often not enough. Here I’ll try to apply a few of the things we can do by using OpenCV.
Let’s define a simple function that takes the image path as an input and returns the string as an output. I’m gonna get super-creative here and name this function “get_string.”
def get_string(img_path):    # Read image using opencv    img = cv2.imread(img_path)    # Extract the file name without the file extension    file_name = os.path.basename(img_path).split('.')[0]    file_name = file_name.split()[0]    # Create a directory for outputs    output_path = os.path.join(output_dir, file_name)    if not os.path.exists(output_path):        os.makedirs(output_path)
Rescaling: Tesseract works best on images that are 300 dpi or more. If you’re working with images with a DPI of less than 300 dpi, you might consider rescaling. Otherwise, rescaling may not make the impact that you thought it’d make.
I, personally, prefer to make sure that the images are at least 300 dpi rather than rescaling them later in the pipeline. However, everyone has their own preferences. You do you.
    # Rescale the image, if needed.    img = cv2.resize(img, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC)
Noise Removal: Most printed documents are likely to experience noise to some extent. Though the main reasons for this noise may vary, it’s clear that it makes it harder for computers to recognize characters. Noise on images can be removed by using a few different techniques combined. These include but are not limited to converting image to grayscale, dilation, erosion, and blurring.
Dilation, erosion, and blurring require a kernel matrix to work with. To put it simply, the larger your kernel size is, the wider the region your method gets to work on. And again, there’s no one kernel size value that fits all. You need to play with numbers and, eventually, find the right values for your images.
However, a good rule of thumb could be starting with small kernel values for small fonts. Similarly, for larger fonts, you may experiment with larger kernels.
    # 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)    # Apply blur to smooth out the edges    img = cv2.GaussianBlur(img, (5, 5), 0)
As you might notice in the piece of code above, we can create kernels in two similar ways: using a NumPy array or directly passing the kernel to the function.
Binarization: This is definitely a must. Let’s try to think like a computer for a second. In this cyber-reality where everything eventually boils down to 1’s and 0’s, converting images to black and white immensely helps Tesseract recognize characters. However, this might fail if input documents lack contrast or have a slightly darker background.
    # Apply threshold to get image with only b&w (binarization)    img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
After saving the filtered image in the output directory, we can finish writing our get_string function by passing the processed image to Tesseract with the following lines.
    # Save the filtered image in the output directory    save_path = os.path.join(output_path, file_name + "_filter_" + str(method) + ".jpg")    cv2.imwrite(save_path, img)    # Recognize text with tesseract for python    result = pytesseract.image_to_string(img, lang="eng")    return result
Now, you might think that you’ve got everything ready already — but there’s always room for improvement. Wouldn’t it be nicer if we had more filtering options? In effect, there is plenty of ‘em! I’ll be explaining a few of those in my next story.
For those who would like to look at my source code before moving on to the next story, here’s my complete code on GitHubGist. As you may notice, it actually does a bit more than text recognition. In fact, it does a lookup for a regular expression on a given region of an image and returns the value.
We’ll get there pretty soon, no worries! Meanwhile, best be on with your day and keep on the lookout for better opportunities*.