I have some old documents that have been scanned, and I want to convert them to black and white. Content should be always black, and background white:
I use Photoshop.
Graphic Design Stack Exchange is a question and answer site for Graphic Design professionals, students, and enthusiasts. It only takes a minute to sign up.Sign up to join this community
If you have control over the scanning, or can get them rescanned, increase the contrast setting in the scan and set the black point at the darkest bit of text you can find. That would make the steps below easier. If not, read on...
Here's part of a fairly typical old document scan:
The details will be different depending on the document (this has somewhat higher contrast than your sample, for example) but the broad outline will be the same.
Notice that the yellows slider is far to the right, lightening the yellowish background. I was able to darken the text only a little.
This gets you 95% of the way there. A scanned document typically has a histogram with a large lump toward the right (the paper) and a smaller lump toward the left (text). You'll have to experiment with your documents to find the right settings.
From this point, you can duplicate the image, flatten the duplicate, and use your regular Photoshop retouching tools to clean up the remainder.
You mention Photoshop, but in case you are interested there's also a GIMP plugin that does advanced grayscale cleaning and processing:
It's called Nuvola Tools, and it's mainly focused on scanned art, but you might want to give it a try.
Source: GIMP Plugin Registry
I tried various mentioned methods incl. free FineThreshold http://www.mehdiplugins.com/english/finethreshold.htm plugin. This plugin produces good results quickly provided that the document is homogenously lighted and the paper itself is also of homogenous quality. However this was not my case. I experienced that the upper side of every document was more light than the bottom. Consequently, every method and its partial setting worked well only for the part of every page and not for the rest of it.
Eventually I found the effect "Dynamic Thresholding" which is part of Zoner Photo Studio v15. Its eval version is free for some period, I guess. It seems to offset the b/w threshold according to the neighbourhood lightness. Its application is one-step process only. For me the parameters "Large, value +14" worked very well. Beside "Editor" Zoner contains also the "Manager" interface in which you can process the batch over all selected images. In the end I was able to print the result on the very old 300 dpi laser printer with excellent contrast.
Now, the only remaining task for which I am looking is automatic CROP of every image in an inteligent manner to cut-out the unnecessary margins. Any hints are welcome because manual cropping is boring as well as time consuming.
There was a plugin in the GIMP plugin registry that did this. It's archived here now.
Some time ago I translated this to Python and it ran a lot faster.
Here's the result of its application to the image in the original question:
Here's the result of its application to the image in Alan's answer:
Anyway here's the code of the plugin:
from __future__ import division import random import gimp, gimpfu pdb = gimp.pdb sample_count = 100 def set_image_background_to_white(image, drawable): pdb.gimp_context_push() pdb.gimp_image_undo_group_start(image) pdb.gimp_progress_set_text('Correcting background') if drawable.is_gray: channel_count = 1 elif drawable.is_rgb: channel_count = 3 assert not drawable.is_indexed # get some random points in the image sum_by_channel = *channel_count for sample_index in range(sample_count): px = pdb.gimp_drawable_get_pixel(drawable, random.randint(0, pdb.gimp_drawable_width (drawable)-1), random.randint(0, pdb.gimp_drawable_height(drawable)-1)) for i in range(channel_count): sum_by_channel[i] += px[i] pdb.gimp_progress_update(sample_index/sample_count) if drawable.is_gray: pdb.gimp_levels(drawable, gimpfu.HISTOGRAM_VALUE, 0, sum_by_channel/sample_count, 1., 0, 255) elif drawable.is_rgb: for i in range(channel_count): pdb.gimp_levels(drawable, 1+i, 0, sum_by_channel[i]/sample_count, 1., 0, 255) pdb.gimp_levels(drawable, gimpfu.HISTOGRAM_VALUE, 0, 255, 0.6, 0, 255) pdb.gimp_image_undo_group_end(image) pdb.gimp_displays_flush() pdb.gimp_progress_update(1.) pdb.gimp_context_pop() gimpfu.register('set_image_background_to_white', # name 'Set image background to white', # blurb 'No help info yet', # help 'Robert Fleming', # author 'Robert Fleming', # copyright '2015', # date '<Image>/Filters/Set Background to White', # menupath 'RGB*, GRAY*', # imagetypes , # params , # results set_image_background_to_white, # function ) gimpfu.main()