1

Good afternoon,

I am writing an ocr program to detect text on images. So far I am getting good results but when text is black and background is white. What can I do to improve images that have white text on light colored background (yellow, green, etc)?

One original example image could be: original image

So far I am just converting it to grey_scale using:

image = image.convert('L')

Then apply a series of filters like for example: SHARPEN SMOOTH BLUR etc

Then i do binarization like this:

image = image.point(lambda x: 0 if x<128 else 255, '1') #refers to http://stackoverflow.com/questions/18777873/convert-rgb-to-black-or-white and also to http://stackoverflow.com/questions/29923827/extract-cow-number-from-image

My outoup images are indeed very bad for ocr feeding like this one: Output

What am I doing wrong? What should be the best approach for white text on light colored background?

Another doubt: is my binarization step to strong/exagerated?

Should I mix some filters? Could you suggest some?

PS: I am a total newbie to image processing, so please keep it simple =x

Thanks so much for your attention and help/advices.

Community
  • 1
  • 1
Inês Martins
  • 530
  • 2
  • 10
  • 23

1 Answers1

2

I tried this with ImageMagick, which has Python bindings too - except I did it at the command line. I guess you can adapt what I did quite readily - I don't speak Pythonese nor use PIL but hopefully it will give you some insight as to a possible avenue.

convert https://i.stack.imgur.com/2cFk3.jpg -fuzz 50% -fill black +opaque white -threshold 50% x.png

Basically it takes any colour that is not within 50% of white and fills it with black, then it thresholds the result to pure black and white.

enter image description here

Another option would be to threshold the image according to the saturation of the colours. So, you convert to HSB colorspace, separate the channels and discard the hue and brightness. You are then left with the saturation which you threshold as follows:

convert https://i.stack.imgur.com/2cFk3.jpg -colorspace hsb -separate -delete 0,2 -threshold 50% x.png

Throw in a -negate to get white letters on black.

enter image description here

I have copied some other code for PIL, and am modifying it kind of/sort of to something that may be close to what you need - bear in mind I know no Python:

import colorsys
from PIL import Image
im = Image.open(filename)
ld = im.load()
width, height = im.size
for y in range(height):
    for x in range(width):
        r,g,b = ld[x,y]
        h,s,v = colorsys.rgb_to_hsv(r/255., g/255., b/255.)

        if s>0.5:                     // <--- here onwards is my attempted Python
           ld[x,y] = (0,0,0)
        else:
           ld[x,y] = (255,255,255)
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • well now I have to figure out how to do it with pil, thanks! – Inês Martins Jul 08 '15 at 12:55
  • Anyone can help me "translate" this to pythonic language? :) – Inês Martins Jul 08 '15 at 12:55
  • 1
    The only difference I can see between what Mark did and what you did is the grayscale conversion. There are different ways to do rgb to gray, and your threshold of 50% (or 128) works for one of them but not the one you used. The real solution here is not changing the grayscale conversion or the threshold value to make it work with your yellow-on-white image, but to write an algorithm that will search for a suitable threshold. One example would be to perform clustering by color, then identifying the white and black clusters and blacking out all but those. – dvhamme Jul 08 '15 at 14:09
  • I still don't know any Python, but I believe you should be able to convert your image to a `numpy` array (whatever that is) and then convert to HSV using http://matplotlib.org/api/colors_api.html#matplotlib.colors.rgb_to_hsv After that, you would threshold the Saturation value at 50% to get my second suggested answer. – Mark Setchell Jul 08 '15 at 14:30
  • Thanks for your clarification @dvhamme . When you say "One example would be to perform clustering by color, then identifying the white and black clusters and blacking out all but those. " you mean an adaptative thresholding? – Inês Martins Jul 09 '15 at 09:50
  • Correct, you really want to find a threshold that separates white or black from whatever color is around it. In this example, the color is separable on saturation (like Mark Setchell has done), but when you have white on grey, it won't. That's why I would try clustering the colors, it will find suitable color separation in any image which has close to uniform lighting and no color gradients. – dvhamme Jul 09 '15 at 13:31