Book Image

Python Image Processing Cookbook

By : Sandipan Dey
Book Image

Python Image Processing Cookbook

By: Sandipan Dey

Overview of this book

With the advancements in wireless devices and mobile technology, there's increasing demand for people with digital image processing skills in order to extract useful information from the ever-growing volume of images. This book provides comprehensive coverage of the relevant tools and algorithms, and guides you through analysis and visualization for image processing. With the help of over 60 cutting-edge recipes, you'll address common challenges in image processing and learn how to perform complex tasks such as object detection, image segmentation, and image reconstruction using large hybrid datasets. Dedicated sections will also take you through implementing various image enhancement and image restoration techniques, such as cartooning, gradient blending, and sparse dictionary learning. As you advance, you'll get to grips with face morphing and image segmentation techniques. With an emphasis on practical solutions, this book will help you apply deep learning techniques such as transfer learning and fine-tuning to solve real-world problems. By the end of this book, you'll be proficient in utilizing the capabilities of the Python ecosystem to implement various image processing techniques effectively.
Table of Contents (11 chapters)

Applying affine transformation

An affine transformation is a geometric transformation that preserves points, straight lines, and planes. Lines that are parallel before the transform remain parallel post-application of the transform. For every pixel x in an image, the affine transformation can be represented by the mapping, x |→ Mx+b, where M is a linear transform (matrix) and b is an offset vector.

In this recipe, we will use the scipy ndimage library function, affine_transform(), to implement such a transformation on an image.

Getting ready

First, let's import the libraries and the functions required to implement an affine transformation on a grayscale image:

import numpy as np
from scipy import ndimage as ndi
from skimage.io import imread
from skimage.color import rgb2gray

How to do it...

Perform the following steps to apply an affine transformation to an image using the scipy.ndimage module functions:

  1. Read the color image, convert it into grayscale, and obtain the grayscale image shape:
img = rgb2gray(imread('images/humming.png'))
w, h = img.shape
  1. Apply identity transform:
mat_identity = np.array([[1,0,0],[0,1,0],[0,0,1]])
img1 = ndi.affine_transform(img, mat_identity)
  1. Apply reflection transform (along the x axis):
mat_reflect = np.array([[1,0,0],[0,-1,0],[0,0,1]]) @ np.array([[1,0,0],[0,1,-h],[0,0,1]])
img1 = ndi.affine_transform(img, mat_reflect) # offset=(0,h)
  1. Scale the image (0.75 times along the x axis and 1.25 times along the y axis):
s_x, s_y = 0.75, 1.25
mat_scale = np.array([[s_x,0,0],[0,s_y,0],[0,0,1]])
img1 = ndi.affine_transform(img, mat_scale)

  1. Rotate the image by 30° counter-clockwise. It's a composite operation—first, you will need to shift/center the image, apply rotation, and then apply inverse shift:
theta = np.pi/6
mat_rotate = np.array([[1,0,w/2],[0,1,h/2],[0,0,1]]) @ np.array([[np.cos(theta),np.sin(theta),0],[np.sin(theta),-np.cos(theta),0],[0,0,1]]) @ np.array([[1,0,-w/2],[0,1,-h/2],[0,0,1]])
img1 = ndi.affine_transform(img1, mat_rotate)
  1. Apply shear transform to the image:
lambda1 = 0.5
mat_shear = np.array([[1,lambda1,0],[lambda1,1,0],[0,0,1]])
img1 = ndi.affine_transform(img1, mat_shear)
  1. Finally apply all of the transforms together, in sequence:
mat_all = mat_identity @ mat_reflect @ mat_scale @ mat_rotate @ mat_shear
ndi.affine_transform(img, mat_all)

The following screenshot shows the matrices (M) for each of the affine transformation operations:

How it works...

Note that, for an image, the x axis is the vertical (+ve downward) axis and the y axis is the horizontal (+ve left-to-right) axis.

With the affine_transform() function, the pixel value at location o in the output (transformed) image is determined from the pixel value in the input image at position np.dot(matrix, o) + offset. Hence, the matrix that needs to be provided as input to the function is actually the inverse transformation matrix.

In some of the cases, an additional matrix is used for translation, to bring the transformed image within the frame of visualization.

The preceding code snippets show how to implement different affine transformations such as reflection, scaling, rotation, and shear using the affine_transform() function. We need to provide the proper transformation matrix, M (shown in the preceding diagram) for each of these cases (homogeneous coordinates are used).

We can use the product of all of the matrices to perform a combination of all of the affine transformations at once (for instance, if you want transformation T1 followed by T2, you need to multiply the input image by the matrix T2.T1).

If all of the transformations are applied in sequence and the transformed images are plotted one by one, you will obtain an output like the following screenshot:

There's more...

Again, in the previous example, the affine_transform() function was applied to a grayscale image. The same effect can be obtained with a color image also, such as by applying the mapping function to each of the image channels simultaneously and independently. Also, the scikit-image library provides the AffineTransform and PiecewiseAffineTransform classes; you may want to try them to implement affine transformation as well.