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

- Read the color image, convert it into grayscale, and obtain the grayscale image shape:

img = rgb2gray(imread('images/humming.png'))

w, h = img.shape

- Apply identity transform:

mat_identity = np.array([[1,0,0],[0,1,0],[0,0,1]])

img1 = ndi.affine_transform(img, mat_identity)

- 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)

- 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)

- 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)

- 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)

- 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: