Remove background color in image processing for OCR
I am trying to remove background color so as to improve the accuracy of OCR against images. A sample would loo开发者_如何学Gok like below:
I'd keep all letters in the post-processed image while just removing the light purple color textured background. Is it possible to use some open source software such as Imagemagick to convert it to a binary image (black/white) to achieve this goal? What if the background has more than one color? Would the solution be the same?
Further, what if I also want to remove the purple letters (theater name) and the line so as to only keep the black color letters? Simple cropping might not work because the purple letters could appear at other places as well.
I am looking for a solution in programming, rather than via tools like Photoshop.
You can do this using GIMP (or any other image editing tool).
- Open your image
- Convert to grayscale
- Duplicate the layer
- Apply Gaussian blur using a large kernel (10x10) to the top layer
- Calculate the image difference between the top and bottom layer
- Threshold the image to yield a binary image
Blurred image:
Difference image:
Binary:
If you're doing it as a once-off, GIMP is probably good enough. If you expect to do this many times over, you could probably write an imagemagick script or code up your approach using something like Python and OpenCV.
Some problems with the above approach:
- The purple text (CENTURY) gets lost because it isn't as contrasting as the other text. You could work your way around it by thresholding different parts of the image differently, or by using local histogram manipulation methods
The following shows a possible strategy for processing your image, and OCR it
The last step is doing an OCR. My OCR routine is VERY basic, so I'm sure you may get better results.
The code is Mathematica code.
Not bad at all!
In Imagemagick, you can use the -lat function to do that.
convert image.jpg -colorspace gray -negate -lat 50x50+5% -negate result.jpg
convert image.jpg -colorspace HSB -channel 2 -separate +channel \
-white-threshold 35% \
-negate -lat 50x50+5% -negate \
-morphology erode octagon:1 result2.jpg
You can apply blur to the image, so you get almost clear background. Then divide each color component of each pixel of original image by the corresponding component of pixel on the background. And you will get text on white background. Additional postprocessing can help further.
This method works in the case if text is darker then the background (in each color component). Otherwise you can invert colors and apply this method.
If your image is captured as RGB, just use the green image or quickly convert the bayer pattern which is probably @misha's convert to greyscale solutions probably do.
Hope this helps someone
Using one line code you can get is using OpenCV and python
#Load image as Grayscale
im = cv2.imread('....../Downloads/Gd3oN.jpg',0)
#Use Adaptivethreshold with Gaussian
th = cv2.adaptiveThreshold(im,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
Here's the result
Here's the link for Image Thresholding in OpenCV
精彩评论