Python图像处理经典实例
上QQ阅读APP看书,第一时间看更新

1.3 应用仿射变换

仿射变换是一种保留了点、直线和平面的几何变换。在变换前平行的线,在变换后仍保持平行。对于图像中的每个像素x,仿射变换可以用映射“x |→Mx+b”表示,其中M是线性变换(矩阵),而b是偏移向量。

在本实例中,我们将使用SciPy库的ndimage模块的affine_transform()函数在图像上实现这样一个转换。

1.3.1 准备工作

首先,导入在灰度图像上实现仿射变换所需要的库和函数:

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

1.3.2 执行步骤

通过使用SciPy库的ndimage模块的函数,执行以下步骤来对图像应用仿射变换。

1.读取彩色图像,将其转换成灰度图像,获得灰度图像形状:

img = rgb2gray(imread('images/humming.png'))
w, h = img.shape

2.应用恒等变换:

mat_identity = np.array([[1,0,0],[0,1,0],[0,0,1]])
img1 = ndi.affine_transform(img, mat_identity)

3.应用反射变换(沿着x轴):

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)

4.缩放变换(沿着x轴缩放0.75倍,沿着y轴缩放1.25倍):

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)

5.将图像逆时针旋转30°。这是一个多步骤组合操作,先将图像移位/居中,应用旋转变换,然后对图像应用逆向移位:

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)

6.对图像应用剪切变换:

lambda1 = 0.5
mat_shear = np.array([[1,lambda1,0],[lambda1,1,0],[0,0,1]])
img1 = ndi.affine_transform(img1, mat_shear)

7.按顺序将所有变换一并应用于图像:

mat_all = mat_identity @ mat_reflect @ mat_scale @ mat_rotate @
mat_shear
ndi.affine_transform(img, mat_all)

仿射变换操作的每一个矩阵(M)如图1-4所示。

图1-4

1.3.3 工作原理

注意,对于图像而言,x轴是垂直(+ve向下)轴,y轴是水平(+ve从左到右)轴。

使用affine_transform()函数,输出(变换后)图像中位置“o”的像素值是由输入图像中位置“np.dot(matrix, o) + offset”处的像素值来确定的。因此,提供用作函数输入项的矩阵实际上是逆向变换矩阵。

在某些情况下,为了将变换后的图像置于可视区域内,需要使用附加矩阵对图像进行平移。

上述代码演示了如何使用affine_transform()函数来实现不同的仿射变换,例如反射、缩放、旋转和剪切。针对每种变换,需要(使用齐次坐标)提供适当的变换矩阵M(见图1-4)。

通过使用所有变换矩阵的乘积,可以同时执行所有仿射变换的组合(例如,如果想要在完成变换T1之后再执行变换T2,需要使用“输入图像”乘矩阵“TT1”)。

如果依次应用所有变换并且逐个绘制变换后图像,将得到图1-5所示的输出。

图1-5

1.3.4 更多实践

针对上一实例,我们对灰度图像应用affine_transform()函数。把该函数应用于彩色图像也能获得同样的效果,例如通过对每个图像通道同时且独立地应用映射函数。scikit-image图像库还提供了AffineTransform类和PiecewiseAffineTransform类,可供读者实现仿射变换。