Title: Perform binary contrast enhancement with Python and PIL
Binary contrast enhancement is an image processing technique where you convert every pixel in an image to either black or white. This can be handy for removing noise from an image. For example, the picture on the right shows the letter R drawn with a felt-tip pen on white paper. The picture (taken by my phone's camera) made the paper look gray. Binary contrast enhancement makes the paper white.
If you look closely at the original image on the left, you'll see that the character has bright and dark areas so it isn't a uniform green. Binary contrast enhancement makes all of the pieces of the character the same color.
The key to this example is the following binary_contrast_enhancement method.
def binary_contrast_enhancement(image, cutoff):
'''Perform binary contrast enhancement.'''
# Convert the cutoff from a fraction to an absolute value.
cutoff = int(3 * 255 * cutoff)
# Make a copy so we don't mess up the original.
image = image.copy()
# Process the copy's pixels.
pixels = image.load()
for y in range(image.height):
for x in range(image.width):
(r, g, b, a) = pixels[x, y]
if r + g + b < cutoff:
pixels[x, y] = (0, 0, 0, a)
else:
pixels[x, y] = (255, 255, 255, a)
# Return the result image.
return image
This method takes as inputs an image to process and a cutoff value between 0.0 and 1.0. The code first converts the cutoff to a value between 0 and 3 * 255. We'll look at each pixel's red, green, and blue color components, so the brightest it could be is 3 * 255 when all three components have their maximum possible values.
Next, the code makes a copy of the image so it can modify it without destroying the original. It then calls the image's load method to prepare it for pixel-by-pixel manipulation. You can use the image object's getpixel and putpixel methods instead, but using load is faster if you're going to work with many of the image's pixels.
The code then loops through the image's pixels. It gets each pixel's color components and sees whether the sum of the red, green, and blue components is smaller than the cutoff value. If so, the code makes that pixel black. Otherwise the code makes that pixel white.
That's all there is to it! Here are a few notes.
If the cutoff is smaller, fewer pixels turn black so less of the letter R comes through as shown in the picture below.
If the cutoff is larger, more pixels turn black so more of the paper's "noise" comes through as shown in the second picture below.
You may need to experiment for any given image to get a result that you like.
Finally, if you want the image to remain nice and clean, save the result in a lossless format like PNG. If you save it as a JPG file, the JPG compression will add noise to reduce the image size. Try it and see!
Download the example to see additional details and to experiment with it.
For more information image processing in Python, see my Manning liveProject Algorithm Projects with Python: Image Processing. It explain how to do things like:
|
• Rotation | • Scaling | • Stretching |
• Brightness enhancement | • Contrast enhancement | • Cropping |
• Remapping colors | • Image sharpening | • Embossing |
• Color enhancement | • Sharpening | • Gray scale |
• Black and white | • Sepia tone | • Other color scales |
|