4
votes

I would like to take a photo of some text and make the text easier to read. The tricky part is that the initial photo may have dark regions as well as light regions and I want the opengl function to enhance the text in all these regions.

Here is an example. On top is the original image. On bottom is the processed images.

enter image description here

[edited] I have added in a better example picture of what is happening. I am able to enhance the text, but in areas where I have no text, this simple thresholding is creating speckled noise (image bottom left). If I wind back the threshold, then I lose the text in the darker region (bottom right).

At the moment, the processed image only picks up some of the text, not all the text. The original algorithm I used was pretty simple: - sample 8 pixels around the current pixel (pixels about 4-5 distant away seem to work best) - figure out the lightest and darkest pixels from this sample - if the current pixel is closer to the darkest threshold, then make black, and vice versa

This seemed to work very well for around text, but when it came to non-text, then it provided a very noisy image (even when I provided an initial rejection threshold)

I modified this algorithm to assume that text was always close to black. This provided the bottom image above, but once again I am not able to pull out all the text features I want.

2
Do you want to use OpenGL GLSL shaders for that task or ... ? It's hard to say judging only by OpenGL tag, when OpenGL is never mentioned in questions body.Kromster
Hi, I am using OpenGL ES on iOS and GLSL filters. The algorithm I describe above is a kernel routine. Sorry about the confusion.Mike Ullrich
I have added in a better example picture of what is happening. I am able to enhance the text, but in areas where I have no text, this simple thresholding is creating speckled noise (image bottom left). If I wind back the threshold, then I lose the text in the darker region (bottom right).Mike Ullrich

2 Answers

2
votes

Before implementing this as a program, you might want to take source photo and play with it in a GIMP or another editor to see what you can do.

One way to deal with shadows is to run high pass filter before thresolding.

This is how you do it in image editor (manually, without "highpass" filter plugin):
1. Convert image to grayscale and save it to "layer_A"
2. make a copy of "layer_A" into "Layer_B"
3. Invert colors in "Layer_B"
4. Gaussian blur "Layer_B" with radius that is larger than largest feature you want to preserve. (blur radius larger than letter)
5. Merge "Layer_A" with "Layer_B" where result = "Layer_A" * 0.5 + "Layer_B" * 0.5.
6. Increase contrast in resulting image.
7. Run thresold.


Example

In opengl it'll be done in same fashion (and without multiple layers)

It won't work well with strong/crisp shadows (obviously), but it will exterminate huge smooth shadows that occurs due to page being bent, etc.

The technique (high pass filter) is frequently used for making seamless textures, and you should be able to find several such tutorials and additional info with google (GIMP seamless texture high pass or GIMP high pass).

By the way, if you want to improve "readability", then you might want to keep it grayscale (while improving contrast) instead of converting it to "black and white" (1 bit color). Sharp letter edges make text harder to read.

1
votes

thanks for your help.

In the end I went for quite a basic approach.
Taking a sample of 8 nearby pixels, determining the max and min. Determined the local threshold (max - min). Then

smooth = dot(vec3(1.0/3.0), smoothstep(currentMin, currentMax, p11).rgb);
smooth = (localthreshold < threshold) ? 1.0 : smooth;
return vec4(smooth, smooth, smooth, 1);

This does not show me the text nicely in both the dark and light region, which is the ideal, but it nicely cleans up the text in the lighter region.

Mike