Scikit Image - Piecewise Affine Transform



The PiecewiseAffineTransform is a type of geometric transformation, applied to an input image to move each pixel to a new position in the output image. It is a non-linear transformation technique that involves dividing an image into smaller regions (triangles) and applying individual affine transformations to each region. This is especially useful for tasks like image warping, morphing, and non-rigid image registration.

The Scikit-image library in Python provides a class called PiecewiseAffineTransform() in the transform module to perform this geometric transformation on images.

The PiecewiseAffineTransform class

In the scikit-image library, the class skimage.transform.PiecewiseAffineTransform is used to perform a piecewise affine transformation. The transformation is defined by a set of control points that are used to create a mesh of triangles using Delaunay triangulation. Each triangle is then used to compute a local affine transform, which allows for more flexible local geometric changes.

Syntax

Following is the syntax of this class −

class skimage.transform.PiecewiseAffineTransform

Here are the attributes of the class −

  • affines: A list of AffineTransform objects. Each object represents an affine transformation for a triangle in the mesh.
  • inverse_affines: A list of AffineTransform objects. Each object represents the inverse affine transformation for a triangle in the mesh.

Here is the attribute of the class −

  • params: A (D+1, D+1) array representing the homogeneous transformation matrix.

Following are the methods of the class −

  • estimate(src, dst): This method is used to estimate the piecewise affine transformation based on a set of corresponding source and destination coordinates (control points).
  • __call__(self, coords): This method applies the forward transformation to a set of input coordinates and returns the transformed coordinates.
  • inverse: This method returns a transformation object representing the inverse transformation.

The PiecewiseAffineTransform class is inherited from the _GeometricTransform (Abstract base class for geometric transformations).

Example

The following example demonstrates how to use the PiecewiseAffineTransform class to perform a piecewise affine transformation on an image using the set of control points.

import numpy as np
import matplotlib.pyplot as plt
from skimage.transform import PiecewiseAffineTransform, warp
from skimage import io

# Load the input image
image = io.imread('Images/butterfly.jpg')

# Define source and destination control points for transformation
src = np.array([[10, 10], [300, 150], [150, 200]])
dst = np.array([[50, 30], [280, 70], [70, 180]])

# Create an instance of the PiecewiseAffineTransform class
tform = PiecewiseAffineTransform()

# Estimate the piecewise affine transformation based on control points
tform.estimate(src, dst)

# Apply the transformation using the warp function
warped = warp(image, tform)

# Display the original and transformed images
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
axes[0].imshow(image, cmap='gray')
axes[0].set_title('Original Image')
axes[0].axis('off')

axes[1].imshow(warped, cmap='gray')
axes[1].set_title('Transformed Image')
axes[1].axis('off')

plt.tight_layout()
plt.show()

Output

On executing the above program, you will get the following output −

Example

The following example demonstrates how to use the PiecewiseAffineTransform class to perform a piecewise affine transformation on an image.

import numpy as np
import matplotlib.pyplot as plt
from skimage.transform import PiecewiseAffineTransform, warp
from skimage import io

# Load an input image
image = io.imread('Images/butterfly.jpg')

# Define the shape of the image
rows, cols = image.shape[0], image.shape[1]

# Create a grid of source control points
src_cols = np.linspace(0, cols, 10)
src_rows = np.linspace(0, rows, 7)
src_rows, src_cols = np.meshgrid(src_rows, src_cols)
src = np.dstack([src_cols.flat, src_rows.flat])[0]

# Add sinusoidal oscillation to row coordinates of destination control points
dst_rows = src[:, 1] - np.sin(np.linspace(0, 3 * np.pi, src.shape[0])) * 50
dst_cols = src[:, 0]
dst_rows *= 1.5
dst_rows -= 1.5 * 50
dst = np.vstack([dst_cols, dst_rows]).T

# Create a PiecewiseAffineTransform object and estimate the transformation
tform = PiecewiseAffineTransform()
tform.estimate(src, dst)

# Compute the shape of the output image
out_rows = image.shape[0] - 1.5 * 50
out_cols = cols

# Perform the transformation
out = warp(image, tform, output_shape=(out_rows, out_cols))

# Plot the original and transformed images
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
ax[0].imshow(image)
ax[0].set_title('Original Image')
ax[0].axis('off')

ax[1].imshow(out)
ax[1].set_title('Piecewise Affine Transformed Image')
ax[1].axis('off')

plt.show()

Output

On executing the above program, you will get the following output −

Advertisements