5 Best Ways to Apply Affine Transformation on an Image in OpenCV Python

๐Ÿ’ก Problem Formulation: Affine transformation in image processing refers to altering an image to correct for distortions or to apply certain effects. When using OpenCV in Python, developers often need to apply affine transformations to shift, scale, rotate or skew images. This article walks through five methods to do this on an input image, aiming for a transformed output based on provided transformation matrices.

Method 1: Using warpAffine for Translation

This method leverages OpenCV’s warpAffine function to translate an image. Translation involves moving the image along the X and Y axes. This requires a transformation matrix which specifies the pixel shift in each direction.

Here’s an example:

import cv2
import numpy as np

# Load the image
image = cv2.imread('input.jpg')

# Define translation matrix
tx, ty = 100, 50  # shift 100 pixels on X and 50 pixels on Y axis
trans_mat = np.float32([[1, 0, tx], [0, 1, ty]])

# Apply the warpAffine function
translated_img = cv2.warpAffine(image, trans_mat, (image.shape[1], image.shape[0]))

# Save the output
cv2.imwrite('translated_image.jpg', translated_img)

The output is an image shifted 100 pixels right and 50 pixels down from its original position.

In this code snippet, warpAffine takes three arguments: the original image, the transformation matrix, and the size of the output image. It outputs the translated image which is saved to the file system.

Method 2: Rotating an Image

Rotation of an image by a certain angle around a pivot point can be accomplished with an appropriate rotation matrix. OpenCV’s getRotationMatrix2D can be used to create this matrix by specifying the center, angle, and scale factor.

Here’s an example:

import cv2
import numpy as np

image = cv2.imread('input.jpg')
height, width = image.shape[:2]

# Specify the rotation center, the rotation angle, and the scale factor.
center = (width//2, height//2)
angle = 45
scale = 1

# Get the rotation matrix
rot_mat = cv2.getRotationMatrix2D(center, angle, scale)

# Rotate original image
rotated_img = cv2.warpAffine(image, rot_mat, (width, height))

cv2.imwrite('rotated_image.jpg', rotated_img)

The output is the original image rotated 45 degrees about its center point.

The code creates a rotation matrix for a 45-degree rotation around the image’s central pixel, preserving the original size with no scaling. It then applies the warpAffine function to perform the rotation.

Method 3: Scaling an Image

Scaling changes the size of an image. To scale using OpenCV’s warpAffine, a scaling matrixโ€”comprising scaling factors along the X and Y axesโ€”and the function itself are needed.

Here’s an example:

import cv2
import numpy as np

image = cv2.imread('input.jpg')

# Scaling factors
sx, sy = 1.5, 1.5  

# Scaling matrix
scale_mat = np.float32([[sx, 0, 0], [0, sy, 0]])

# Scaling the image
scaled_img = cv2.warpAffine(image, scale_mat, (int(image.shape[1]*sx), int(image.shape[0]*sy)))

cv2.imwrite('scaled_image.jpg', scaled_img)

The output is the original image enlarged by 1.5 times along both axes.

The code snippet demonstrates enlarging an image by a factor of 1.5 in both dimensions, using the warpAffine function to apply the scaling matrix.

Method 4: Skewing or Shearing an Image

Skewing, also known as shearing, distorts an image along either the X-axis or Y-axis. You must define a shearing matrix for this transformation. OpenCV applies this transformation using the warpAffine function.

Here’s an example:

import cv2
import numpy as np

image = cv2.imread('input.jpg')
height, width = image.shape[:2]

# Shearing factor for x-axis
shx = 0.2

# Shearing matrix
shear_mat = np.float32([[1, shx, 0], [0, 1, 0]])

# Shear the image
sheared_img = cv2.warpAffine(image, shear_mat, (int(width + height*shx), height))

cv2.imwrite('sheared_image.jpg', sheared_img)

The output is a sheared image with a horizontal skew.

This code snippet applies horizontal shearing to the input image creating an output image that appears horizontally skewed by a factor defined by shx.

Bonus One-Liner Method 5: Complete Affine Transformation

For a complete affine transformation customizing rotation, scaling, and translation, a combined matrix can be created and applied with warpAffine.

Here’s an example:

import cv2
import numpy as np

image = cv2.imread('input.jpg')

# Combined affine transformation matrix
affine_mat = np.float32([[1.5, 0.5, 100], [0.5, 1.5, 50]])

# Apply affine transformation
transformed_img = cv2.warpAffine(image, affine_mat, (int(image.shape[1]*1.5 + image.shape[0]*0.5), int(image.shape[0]*1.5 + image.shape[1]*0.5)))

cv2.imwrite('affine_transformed_image.jpg', transformed_img)

The output is an image that has been scaled, rotated, and translated based on the parameters in the affine transformation matrix.

This one-liner code snippet applies a complete affine transformation, which simultaneously performs scaling, rotation, and translation as specified by the combined transformation matrix.

Summary/Discussion

  • Method 1: WarpAffine for Translation. Simple and effective for moving an image within the frame. Limited to shifting without altering image dimensions.
  • Method 2: Rotating an Image. Allows for rotation around a point with a customizable scale. Limited to rotations and requires calculation of the rotation matrix.
  • Method 3: Scaling an Image. Easy to adjust image size. Uniform scaling might not be ideal for all aspects or dimensions.
  • Method 4: Skewing or Shearing an Image. Good for artistic effects or correcting perspective distortions. Can be nonintuitive to set the right shearing factor.
  • Bonus Method 5: Complete Affine Transformation. Highly flexible with combined transformations. Complexity increases as transformation becomes more intricate.