Tesseract: an Open-Source Optical Character Recognition Engine
I play with open-source OCR (Optical Character Recognition) packages periodically. My last foray was a few years ago when I bought a tablet PC and wanted to scan in some of my course books so I could carry just one thing to school. I tried every package I could find, and none of them worked well enough even to consider using. I ended up using the commercial version of Adobe Acrobat, which allows you to use the scanned page as the visual (preserving things like equations in math books), but it applies OCR to the text so you can search. It ended up being quite handy, and I was a little sad that I was incapable of getting any kind of result with open-source offerings.
Admittedly, the problem is very hard. Font variations, image noise and alignment problems make it extremely difficult to design an algorithm that can translate the image of text into actual text reliably.
Recently, I was looking again and found a project called Tesseract. Tesseract is the product of HP research efforts that occurred in the late 1980s and early 1990s. HP and UNLV placed it on SourceForge in 2005, and it is in the process of migrating to Google Code (see Resources).
It currently is lacking features, such as layout recognition and multicolumn support; however, the most difficult part, the actual character recognition, is superb.
Version 1.03 was the latest version at the time of this writing, and the build and install process still needed a little work. Also, integration with libtiff (which would allow you to use compressed TIFF as input) was configured by default, but it was not working properly. You might try configuring it with libtiff, as that would allow compressed TIFF image input:
If you later find that it doesn't recognize text, reconfigure it without libtiff:
# ./configure --without-libtiff
The build is done as expected:
Configure for version 1.03 also indicated that make install was broken. I managed to figure out the basics of installation by trial and error.
First, copy the executable from ccmain/tesseract to a directory on your path (for example, /usr/local/bin):
# cp ccmain/tesseract /usr/local/bin
Then, copy the tessdata directory and all of its contents to the same place as the executable (for example, /usr/local/bin/tessdata/...):
# cp -r tessdata /usr/local/bin/tessdata
Finally, make sure your shell PATH includes the former (/usr/local/bin).
First, you need access to a scanner or scanned pages. Sane is available with most Linux distributions and has a nice GUI interface called xsane. (I discuss more on scanning near the end of this article.)
Tesseract has no layout analysis, so it cannot detect multicolumn formats or figures. Also, the broken libtiff support means it can read only uncompressed TIFF. This means you must do a little work on your scanned document to get the best results. Fortunately, the steps are very simple; the most common ones can be automated, and the results are well worth it.
This is what you need to do:
Use a threshold function to drop lighting variations and convert the image to black and white.
Erase any figures or graphics (optional, but if you skip this step the recognizer will give a bunch of garbled text in those areas).
Break any multicolumn text into smaller, single-column images.
I recommend using a graphics program, such as The GIMP, to get a feel for what needs to be done. The most important step is the first one, as it drastically will improve the accuracy of the OCR.
The GIMP has a great function that easily can remove lighting variations in all but the worst cases.
First, go to the Image→Mode menu and make sure the image is in RGB or Grayscale mode. Thresholding will not work on indexed images. Next, select the menu Tools→Color Tools→Threshold. This tool allows you to drop pixels that are lighter than a specified cutoff value, and it converts all others to black. A pop-up (Figure 1) lets you select the threshold. Make sure image preview is turned on in order to get an idea of how it affects the image. Slide the threshold thumb left and right to choose the cutoff between white and black. You may not be able to get rid of all of the uneven lighting without corrupting the text. Find a good-looking result for the text, then erase the rest of the noise with a paint tool. The transition from the first part to the second part in Figure 2 shows a typical result of this step.
You should experiment and zoom in over a portion of the image while you play with thresholding, so you can see things closer to the pixel level. This lets you see more of what Tesseract will see and gives you a better feeling for how to get the best results. If you can't recognize the characters, Tesseract surely won't.
This page had handwritten notes, underlining and a section of lighting that threshold could not get rid of without compromising the rest of the image. Use a brush to paint over any easy-to-fix areas. I would not recommend spending much time on cases where the extraneous information (figure, noise and so on) has some distance from the text; Tesseract might insert a few garbled characters, but those are usually quicker to fix in a text editor. The resulting image should look something like the third part of Figure 2.
Now, switch the image to indexed mode (using the menu selection Image→Mode→Indexed), and choose black and white (one-bit palette). Also, make sure dithering is off. Save the image as an uncompressed TIFF image, and you are ready to do recognition.
The recognition part is easy:
$ tesseract image.tif result
The third argument is the base name of the output file. Tesseract adds a txt extension automatically, so in this example, the recognized text would be in result.txt.
The underlining in this example ended up significantly affecting the OCR. A few of the lines were recognized moderately well, but two of them were completely unintelligible after processing. This underscores the importance of using a clean source if possible. Manually removing the underlining drastically improved recognition, but it took more time than simply entering the text manually.