In this blog, you will find steps to skew an image without using OpenCV. Skewing is a geometrical transformation of an image where we can change the appearance of the image by using small matrix operations.
Effect of the transformation:
- squares become parallelograms
- y coordinates skew to the right
x coordinates stay the same
In python, the image axis is not as per the conventional X-Y axis. Below is the pictorial representation of rows and columns.
Let’s consider ROW as X-axis and COL as Y-axis. If we skew with respect to the ROW (X-axis), we will find a shape like shown in Image-2. Similarly, if we skew with respect to COL(Y-axis), we will find observations like shown in Image-3.
Effect of shearing along X-axis.
To shear an image, we have to multiply the below matrix to each point to skew the image.
import math from PIL import Image import numpy as np import matplotlib.pyplot as plt class ICV_shearImage: def ICV_degreeToRadian(self, degree): ''' Convert degree to radian :param degree: degree :return: radian ''' return degree * np.pi / 180.0 def ICV_getImageMidPoints(self, image): ''' This method returns image midpoints :param image: :return: x_mid, y_mid ''' height, width, num_channels = image.shape y_mid = width / 2 x_mid = height / 2 return x_mid, y_mid def ICV_skew_XY(self, angle, x, y): ''' This method implements the tangent rule to X and Y :param angle: :param x: X coordinate :param y: Y coordinate :return: new_x and new_y ''' radian = self.ICV_degreeToRadian(angle) tangent = 1 / math.tan(radian) #new_x = round(x + (y * tangent)) #new_y = y new_x = x new_y = round(y + (x * tangent)) return new_x, new_y def ICV_shear(self, image, angle, newimage): ''' Shear the new image :param image: Original Image matrix :param angle: Degree :param newimage: New image matrix :return: New image ''' x_mid, y_mid = self.ICV_getImageMidPoints(image) newimage_x_mid, newimage_y_mid = self.ICV_getImageMidPoints(newimage) for row in range(0,image.shape): for col in range(0,image.shape): y_prime = y_mid - col x_prime = x_mid - row x_new, y_new = self.ICV_skew_XY(angle, x_prime, y_prime) xdist = int(newimage_x_mid - x_new) ydist = int(newimage_y_mid - y_new) if < newimage.shape and ydist < newimage.shape: newimage[xdist, ydist, :] = image[row, col, :] return newimage def ICV_canvasSize(self, image, degree): ''' Generate Canvas to hold skewed image :param image: Image :param degree: Degree :return: Place holder to contain skewed image ''' row, col, num_channels = image.shape radian = self.ICV_degreeToRadian(degree) new_y_value = round(row + (col * (1 / math.tan(radian)))) skewed_image_canvas = np.zeros((row, new_y_value, 3)) print("Skewed Image shape:", row, new_y_value) return skewed_image_canvas def ICV_plotImage(self, newImage, name): ''' This method plots the new image :param newImage: :return: Null ''' plt.gca().set_axis_off() plt.margins(0, 0) plt.gca().xaxis.set_major_locator(plt.NullLocator()) plt.gca().yaxis.set_major_locator(plt.NullLocator()) output_image = Image.fromarray(newImage.astype("uint8")) plt.imshow(output_image) plt.savefig("output_image_skewed"+name+".jpg",bbox_inches='tight', pad_inches=0) plt.show() def main(): shearimage = ICV_shearImage() image = Image.open('name.jpg') image = np.asarray(image) row, col, num_channels = image.shape print("Actual Image Shape:", row,col) degree = 30 skewed_image_canvas = shearimage.ICV_canvasSize(image, degree) newImage_30 = shearimage.ICV_shear(image, degree, skewed_image_canvas) shearimage.ICV_plotImage(newImage_30, "30") if __name__ == "__main__": main()
In this blog, you learned how to skew an image using python and skew an image without using OpenCV library. In the case of any queries please comment below.
#Skew Image without using OpenCV library