We now have these nifty copying machines that allow you to save scanned pages
to a PDF document instead of printing them. Using Acrobat Pro, it is very easy
to turn these scans into fully searchable PDFs. Much better than simple paper
copies. So, last time I wanted to keep some pages of a book for reference,
guess what I did.
Unfortunately, after returning the book to the library I discovered that the
default settings of the copier try to save space and produce heavily pixelated
black and white images. The text is nearly unreadable. Zooming in to 200%, the
scan looks like this:
Nevertheless, the problem can be fixed using morphological operations
which are readily available in OpenCV. After applying a closing
operation (a dilation followed by an erosion) with a small circle as
structuring element the image already looks much better (pixels added by
the closing highlighted in red):
As you can see, the closing operation fills all the tiny gaps but keeps the
shape of letters intact. Finally, I applied a small blur filter and then
increased the contrast to get nice, smooth edges. Here is a comparison of the
scan before and after the repair:
Now, that is something I can live with. And all of this can be done in
just a few lines of code:
#!/usr/bin/env python
import sys
import cv2
import numpy as np
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
for filename in sys.argv[1:]:
print "Processing {0:s}n".format(filename)
# read image as grayscale:
img = cv2.imread(filename, 0)
# close gaps:
cv2.erode(img, kernel, img)
cv2.dilate(img, kernel, img)
# blur and then increase contrast to get smooth edges:
img = cv2.GaussianBlur(img, (5, 5), 0)
tmp = (img.astype('int32') - 25) * ((255 + 50) / 255.0)
np.clip(tmp, 0, 255, out=tmp)
img = tmp.astype('uint8')
cv2.imwrite(filename, img)