2009-08-13

Batch Image Processing with Python

Adapted from http://www.coderholic.com/batch-image-processing-with-python/

If you want to make changes to a single image, such as resizing or converting from one file format to another, then you’ll probably load up the image in an editor and manually make the required changes. This approach is great for a single image, but it doesn’t really scale past more than a few images, at which point it becomes time consuming, not to mention boring!

This is where Python and the Python Imaging Library (or PIL) come in, allowing you to write scripts that process images in batch.

Batch Processing

No matter what processing we want to do on our images the script outline will be the same: loop over all provided arguments, and perform the processing. The code to do this is shown below:


#!/usr/bin/env python
import sys
import Image

# Loop through all provided arguments
for i in range(1, len(sys.argv)):
try:
# Attempt to open an image file
filepath = sys.argv[i]
image = Image.open(filepath)
except IOError, e:
# Report error, and then skip to the next argument
print "Problem opening", filepath, ":", e
continue
# Perform operations on the image here

This will allow our script to be called in all of the following ways:

$ batch_process.py image.gif
$ batch_process.py image1.png image2.gif image3.jpg
$ batch_process.py *.png
$ batch_process.py image1.gif, *.png


With the help of PIL the image processing is really simple. Below is a collection of just some of the operations we could perform. For more details see the PIL documentation.

#Resize an image
image = image.resize((width, height), Image.ANTIALIAS)

# Convert to greyscale
image = image.convert('L')

# Blur
image = image.filter(ImageFilter.BLUR)

# Sharpen
image = image.filter(ImageFilter.SHARPEN)

Saving

Once we’ve processed the image we need to save the changes. In some instances we might just want to save over the original filename. If that’s the case we can just call the save method of image with its original filename. If we want to save the file under a different name, or as a different filetype we need to do a little more work:

# Split our original filename into name and extension
(name, extension) = os.path.splitext(filepath)

# Save with "_changed" added to the filename
image.save(name + '_changed' + extension)

# Save the image as a JPG
image.save(name + '.jpg')

Notice in the last example how PIL takes care of the conversion to JPG for us. All we do is provide the file extension and PIL does the rest for us.

A Complete Example

Each of the steps above can easily be put together to create a batch image processing script. Below is a complete script which creates thumbnails of all provided images, and saves them as PNG images, not matter what their original format:

!/usr/bin/env python
# Batch thumbnail generation script using PIL

import sys
import os.path
import Image

thumbnail_size = (28, 28)

# Loop through all provided arguments
for i in range(1, len(sys.argv)):
try:
# Attempt to open an image file
filepath = sys.argv[i]
image = Image.open(filepath)
except IOError, e:
# Report error, and then skip to the next argument
print "Problem opening", filepath, ":", e
continue

# Resize the image
image = image.resize(thumbnail_size, Image.ANTIALIAS)

# Split our original filename into name and extension
(name, extension) = os.path.splitext(filepath)

# Save the thumbnail as "(original_name)_thumb.png"
image.save(name + '_thumb.png')

No comments: