Share @ Google LinkedIn Facebook  python, imagemanipulation

Note: This tutorial is inspired from Pillow Tutorial

What is PIL (Python Imaging Library)?

Python Imaging Library is used to for loading image in memory and doing various transformations on image.It supports loading images of variuos types like PNG, JPEG etc. It can be used to do various transformations on image and then store that transformed image. PIL is generally used in deep learning where preprocessing of images is required as part of object detection tasks. Image loaded using PIL can be easily converted to Numpy array as many Machine Learning and Deep Learning libraries take numpy array as input. Various deep learning libraries use PIL behind the scene to do image pre-processing.

How to install PIL?

pip install Pillow

Importing PIL and using it for image manipulation

In [377]:
import PIL
from PIL import Image, ImageFilter, ImageEnhance, ImageSequence
import numpy as np
import secrets
import matplotlib.pyplot as plt

np.set_printoptions(precision=4,threshold=5,edgeitems=2)

Loading an image in memory.

Image is main class of PIL which is responsible for representing image. Whenever you load am image in memory using PIL it'll be of class Image.

open() method is used to open file. This method loads file lazily as it reads header of image file to find out image format, mode and size. It does not load whole image into memory which can be of few MB for images with higher resolution. This can be helpful to findout image metadta without loading it in memory.

Note: Please save few png, jpeg images in directory where jupyter notebook is kept to load images in memory and do various operations. Also change image name according in below code to load your images.

In [378]:
Image.open('ml.jpeg')
Out[378]:
In [379]:
img = Image.open('ml1.png').resize((380,250)); img2 = Image.open('ml.jpeg').resize((380,250))
type(img), type(img2)
Out[379]:
(PIL.Image.Image, PIL.Image.Image)
  • size attribute of Image instance refers to size of image in pixels. (width, height)
  • mode attribute referes to in which mode image is loaded which is generally RGB, RGBA, CMYK, L etc.One can get more information about mode, pallette, bands etc over here
  • format refers to format of source file from which image was loaded, It'll be None for image generated after processing original image. One can read about formats supported over here
In [380]:
(img.size,img.mode, img.format, img.info), (img2.size,img2.mode, img2.format, img2.info)
Out[380]:
(((380, 250), 'RGBA', None, {'srgb': 0, 'gamma': 0.45455, 'dpi': (96, 96)}),
 ((380, 250), 'RGB', None, {}))
In [381]:
plt.figure(figsize=(15,8))
plt.hist(img.histogram(),bins=256,range=(0,255),color='red', label='Density of pixels within image')
Out[381]:
(array([472.,   4., ...,   1.,   0.]),
 array([  0.    ,   0.9961, ..., 254.0039, 255.    ]),
 <a list of 256 Patch objects>)
  • show() function saves image and then loads it in default image application on machine.
  • convert() function is used to convert image from one mode to another.Currently conversion only between images with mode types 'L', 'RGB' and 'CMYK'
In [382]:
img = img.convert('L')
img.show()

Save image using Image class instance method save()

  • It's required to provide file format in which to save file. We can give format as paramer to save() method or we can include it in file name as well. save() method will fail if format is not provided as part of file name or as format parameter.
In [383]:
img.save('img_rgb.jpg'); img.save('temp',format="jpeg")

Creating thumbnail

  • We can use thumbnail()method of Image class to create thumbnail from image. We need to provide size parameter as tuple (height, width).PIL will create image which has same aspect ratio as original image. Resulting thumbnail will not be same size as you provided as parameter.But it'll not be larger than that size.
  • Also make a note that thumbnail() method works in-place which means that it'll modify original image object rather than returning new modified object.
  • one can use size attribute of Image class to check size of resulting image after converting to thumbnail.
  • size attribute of Image class always return tuple in format (width, height).
In [384]:
img.thumbnail((128,128))
img.size
Out[384]:
(128, 84)

Resizing Image

resize() method is used to resize method. It requires new size of image as tuple first parameter. One can maximize and minimize image using this method.

In [385]:
img = Image.open('ml1.png').resize((380,250))
img.resize((200,150))
Out[385]:

Cropping Image

crop() method is used to crop particular part of image. It requires tuple of 4 integers (left,upper, right, lower). This number must be withing range of size of image otherwise error will be raised while cropping. Image is represented using coordinated system with (0,0) as upper-left corner and (width, height) as lower-right corner.

crop() method is lazy as it does not actually crops image until load() function is called to load cropped image.

  • One can find width and height of resulting image using below formula:
    • width = right - left, height = lower - upper.

size attribute of Image class always return tuple in format (width, height).

In [386]:
cropped_img = img.crop((100,100,250,150))
print('size of cropped image : %s'%str(cropped_img.size))
cropped_img
size of cropped image : (150, 50)
Out[386]:

Flip/Rotate an Image

  • transpose() function is used to flip/rotate image in various angles. Various flip/rotate types are Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM, Image.ROTATE_180, Image.ROTATE_90, Image.ROTATE_270, Image.TRANSPOSE and Image.TRANSVERSE

  • rotate() function is used to rotate image by certain degress. It takes on parameter which must be between (0,360).

In [387]:
img.transpose(Image.FLIP_TOP_BOTTOM)
Out[387]:
In [388]:
img.rotate(45)
Out[388]:

Converting Image object to numpy array and vice-versa

  • We can directly give Image class instance as input to numpy.array() method. It'll convert image to numpy array based on mode and it'll create channels accordingly.

  • We can create Image instance from numpy array again with Image.fromarray() function.

In [389]:
nparr = np.array(img)
nparr.shape, nparr.dtype, nparr
Out[389]:
((250, 380, 4), dtype('uint8'), array([[[  4,   6,  44, 255],
         [  4,   6,  44, 255],
         ...,
         [  6,   8,  47, 255],
         [  6,   8,  47, 255]],
 
        [[  5,   7,  45, 255],
         [  5,   7,  45, 255],
         ...,
         [  6,   8,  47, 255],
         [  6,   8,  47, 255]],
 
        ...,
 
        [[  4,   7,  42, 255],
         [  4,   7,  42, 255],
         ...,
         [  5,   7,  45, 255],
         [  5,   7,  46, 255]],
 
        [[  3,   6,  41, 255],
         [  3,   6,  41, 255],
         ...,
         [  5,   7,  45, 255],
         [  5,   7,  46, 255]]], dtype=uint8))
In [390]:
img2 = Image.fromarray(nparr); Image.fromarray(nparr)
Out[390]:
In [391]:
Image.fromarray(np.random.randint(0,255,size=(150, 150, 3), dtype=np.uint8))
Out[391]: