In Basic Python Scripts to Save and Load Audio Files, I’ve promised to also provide some basic scripts to save and load images. In this article, I do exactly that. As always, I’ve assumed that you want to use NumPy and SciPy for processing your data, and that you use floating point numbers for all processing and convert to integers just before saving to file.
Note that there is also the completely different approach of creating a plot with Matplotlib and saving that as an image. You might be familiar with that for things like line and bar charts, but you can also do that for images that you create with Matplotlib. You need to do some trickery to get rid of the axes and stuff, but it can result in a clean image. There is an example of that in How to Compute Colorful Fractals using NumPy and Matplotlib, but I won’t talk about that approach in this article.
The go-to library for saving and loading images is imageio. The following Python script demonstrates how to create a black-and-white image, a color image, and a color image with an alpha channel (an alpha channel is an extra “layer” of the image that specifies the transparancy of the image).
import numpy as np from imageio import imwrite # Configuration. m = 10 n = 100 scale = 5 # Create a black-and-white image. im = np.random.rand(m, n) im = im.repeat(scale, axis=0).repeat(scale, axis=1) # Save 50 x 500 image (range of im is [0, 1]). imwrite('bw.png', np.round(im * 255).astype(np.uint8)) # Create a color image, with red, green, and blue channels. im_r = np.random.rand(m, n) im_g = np.random.rand(m, n) im_b = np.random.rand(m, n) im_color = np.stack((im_r, im_g, im_b), axis=-1) im_color = im_color.repeat(scale, axis=0).repeat(scale, axis=1) # Save 50 x 500 x 3 image (range of all three channels is [0, 1]). imwrite('color.png', np.round(im_color * 255).astype(np.uint8)) # Add an alpha channel to the color image. im_alpha = np.repeat(np.linspace(1, 0, num=n), m).reshape(n, m).T im_alpha = im_alpha.repeat(scale, axis=0).repeat(scale, axis=1) im_alpha = np.dstack((im_color, im_alpha)) # Save 50 x 500 x 4 image (range of all four channels is [0, 1]). imwrite('alpha.png', np.round(im_alpha * 255).astype(np.uint8))
Below are the three images that this script produces. The black-and-white image is 50×500, based on a random 10×100 matrix where each element has a value in the range [0, 1]. When used as input to the actual
imwrite function, these values are mapped to the range [0, 255] and converted to the data type
np.uint8. If your image is in the range [0, 1], then
imwrite will automatically do the right thing, even if you don’t do the conversion to
uint8. However, that isn’t clearly stated in the documentation, and it also wasn’t the case for
misc.imsave from SciPy, the previous go-to library function to save images to file, so I’ve left it in for clarity.
For the color image, three random 10×100 matrices are created, and then scaled and combined into a 50×500×3 NumPy array. When such a data structure is passed to the
imwrite function, the third dimenstion is interpreted as the channel number, with 0 the red, 1 the green, and 2 the blue channel.
If an alpha channel is required, simply put it into a fourth channel (channel number 3). This results in a 50×500×4 NumPy array for the current example. For the example, I’ve added an alpha channel that goes from fully opaque on the left to fully transparent on the right.
The type of the image, PNG in case of the example script, is determined from the filename. So, e.g., if you simply rename
'color.jpg' in the call to
imwrite, then the file will be saved in the JPEG format. Of course, the image won’t be lossless anymore (which is why PNG is a good basic choice), and alpha channels are not supported in JPEG, so this won’t work for the third image.
The following script loads an image, performs an operation on it, and saves the middle part of it again. The example operation converts the image to grayscale. It applies gamma correction before converting the image to grayscale, taking into account the sensitivity of the human eye.
from __future__ import division import numpy as np from imageio import imread, imwrite # Load image from file. # Returns image as floats in the range [0, 1]. lena = imread('4.2.04.tiff').astype(float) / 255 # Example operation: convert to grayscale. This operation keeps the image in # the range [0, 1]. gamma = 2.2 lena **= gamma lena = lena[:, :, 0] * 0.3 + lena[:, :, 1] * 0.59 + lena[:, :, 2] * 0.11 lena **= 1 / gamma # Save middle part of image to file (range of all three channels is [0, 1]). imwrite('lena-gray.jpg', np.round(lena[180 : 400] * 255).astype(np.uint8))
Figure 4 shows the output image that this script produces. The line that loads the image normalizes it to the range [0, 1]. The example image is the Lena test image, which was downloaded from the USC-SIPI Image Database.
And that’s it, you’re all set to so create and edit images from Python! As I’ve already mentioned in the beginning of the article, there’s also a similar post on audio files.