1

I have almost completed a sucessfull program as the code works with a sample file, but I can't get to edit the photograph of my meter in order for OCR to work.

I find my output image to be quite near a working mode, however I don't know what else I can do to the image to get it working.

This is my code:

import pytesseract
import Image
import sys

from PIL import Image
from PIL import ImageFilter
import PIL
import PIL.ImageOps

image_file_ocr = 'ocr_output.jpg'

image_file = 'image_original.jpg'
#image_file = 'ocr2.jpg'
#image_file = 'sample1.jpg'
#image_file = 'sample2.jpg'
#image_file = 'sample3.jpg'
#image_file = 'sample4.jpg'     # texto largo
#image_file = 'sample5.jpg'     #image_text = "1234567890"

print image_file

# LOAD THE IMAGE
#image = Image.open('sample5.jpg')
image = Image.open(image_file)              # open colour image
image = image.convert('L')               # convert image to monochrome - this works
#image = image.convert('1')              # convert image to black and white

image = image.rotate(-90)

# EDIT THE IMAGE
w, h = image.size
#image = image.crop((0, 30, w, h-30))
image = image.crop((350, 680, 1100, 770))
image.filter(ImageFilter.SHARPEN)

image = PIL.ImageOps.invert(image)

image.save(image_file_ocr,'jpeg')

# PROCESS THE IMAGE
print "\n\nProcessing image: " + image_file_ocr
image = Image.open(image_file_ocr)

print "Process method 1:"
text = pytesseract.image_to_string(image, config='outputbase digits')
print text

print "Process method 2:"
text = pytesseract.image_to_string(image)
print text

This is the original image original image

This is my progress so far to process the image process so far

The following image works correctly

working correctly

martineau
  • 119,623
  • 25
  • 170
  • 301
Serge
  • 312
  • 5
  • 20
  • I'd guess that tesseract internally binarizes greyscale images and the process probably does not work well on your given image. Try to binarize it properly first and then pass it to tesseract; I'd bet it works much better then. – Martin Krämer Jan 22 '17 at 18:16
  • I'd also suggest converting the image to 1-bit pixels (`mode "1"`). Note that you may have to convert it back to 8-bit grayscale or rgb to do the rest of the processing. – martineau Jan 22 '17 at 18:22
  • I have tried with #image = image.convert('1') # convert image to black and white . but this does not work well as there are many dots left from the background. Can you help me on how to use binarize with python? – Serge Jan 22 '17 at 18:22
  • martineau, we wrote at the same time. as I was saying it does not work well as there is too much background noise. any other suggestion on how to reduce the background noise? – Serge Jan 22 '17 at 18:23
  • Sounds like you need to "despeckle" the image. Photoshop has a filter that does that, but I'm not sure exactly how it works. Also, doing it in pure Python might not be feasible because it would be too slow. – martineau Jan 22 '17 at 18:27
  • One possibly feasible (with PIL or pillow) approach would be to convert it to 1-bit mode manually (i.e. pixel-at-time) but allow the threshold be something other that 50%. This basically reduces to one conditional statement per pixel, so might be fast enough to be usable. – martineau Jan 22 '17 at 18:37
  • good idea, but I cant find how to set a different % level – Serge Jan 22 '17 at 18:40
  • You would do it with a Python `if` statement that compared the luminosity of a given pixel to the desired threshold value (like `.75` for 75%) with the result being `0` to give it the color black or `1` for white. I just noticed that Pillow has a [`ImageFilter.ModeFilter`](http://pillow.readthedocs.io/en/4.0.x/reference/ImageFilter.html#PIL.ImageFilter.ModeFilter) which might be useful, too. – martineau Jan 22 '17 at 18:43
  • Binarization is not just mode "1". There are global approaches, i.e. thresholding, and local approaches based on patchwise statistics that are generally more suitable. You should have a look into the topic, there is tons of research available. – Martin Krämer Jan 22 '17 at 18:46
  • Look at this question http://stackoverflow.com/questions/40711516/python-image-segmentation-as-pre-process-for-classification/40728800#40728800 which had a similar problem – Amitay Nachmani Jan 22 '17 at 19:19
  • Thanks you for the comments. I have tried to find about binarization but can't find the method information. Could I get an example code line for binarization and or modefilter? Can't make it work – Serge Jan 23 '17 at 09:35
  • I have done lots of image cleaning using paint.net and still the characters are not recognized, so now I have noticed that its a problem with the OCR. The sample works, but my number 1 for example is different and is not recognized. Any example code? – Serge Jan 24 '17 at 10:37

1 Answers1

1

You may consider to add a config user file with the pattern \d\d\d\d\d\d\d\d (8-digits). In addition please keep in mind the default page segmentation method:

By default Tesseract expects a page of text when it segments an image. If you're just seeking to OCR a small region try a different segmentation mode, using the -psm argument. Note that adding a white border to text which is too tightly cropped may also help, see issue 398.

As of 3.04:

 0   Orientation and script detection (OSD) only.
 1   Automatic page segmentation with OSD.
 2   Automatic page segmentation, but no OSD, or OCR.
 3   Fully automatic page segmentation, but no OSD. (Default)
 4   Assume a single column of text of variable sizes.
 5   Assume a single uniform block of vertically aligned text.
 6   Assume a single uniform block of text.
 7   Treat the image as a single text line.
 8   Treat the image as a single word.
 9   Treat the image as a single word in a circle.
10   Treat the image as a single character.

So you'd probably want -psm 7 for your cropped image.

Also have a look at this answer for how to apply filters.

Community
  • 1
  • 1
not2qubit
  • 14,531
  • 8
  • 95
  • 135