开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
前言
仿射变换将每个像素 从输入图像变换到输出图像中的位置 。如果变换的像素坐标位于输出图像中的两个像素之间,通常通过反射(扭曲,warping)解决。在本节中,我们将使用 Scipy 库的 ndimage 模块函数实现图像上的仿射变换。
仿射变换原理
对于输出图像中位置 处的每个像素,利用以下公式从输入图像中相应位置处获取像素值:
如果输入图像中的像素位于两像素之间,则使用来自相邻像素的插值(例如,使用双线性插值)像素值进行计算。下图显示了向扭曲和反扭曲的概念:
反向映射过程如下:
- 创建输出图像
- 对于输出图像中的每个像素,找到输入图像中的对应像素
- 赋予输出像素对应的像素值
下图给出了每个仿射变换操作的矩阵( M):
我们将通过将仿射转换矩阵传递给affine_transfom()函数函数来实现图像转换,affine_transfom()函数的输入参数如下:
scipy.ndimage.affine_transform(input, matrix, offset=0.0, output_shape= None, output=None, order=3, mode='constant', cval=0.0, prefilter=True)
应用仿射变换。输出图像中的位置 o 处的像素值由输入图像中的位置为 np.dot(matrix, o) + offset 处的像素值确定,其中矩阵和偏移量分别是传递给 affine_transform() 函数的 matriix 和 offset 参数。
使用 scipy.ndimage 实现仿射变换
接下来,我们使用 Scipy 库的 ndimage 模块实现仿射变换。
(1) 首先,导入所需的所有 Python 库:
from skimage.io import imread
from scipy.ndimage import affine_transform
import numpy as np
import matplotlib.pylab as plt
(2) 读取图像并通过传递 3×3 变换矩阵和偏移量使用函数 affine_transform() 来执行变换。 在这里,我们沿 x 轴和 y 轴(使用 @ 运算符乘上相应的变换矩阵)将图像沿正(逆时针)方向旋转 45 度:
im = imread("1.png")
rot_mat = np.array([[np.cos(np.pi/4),np.sin(np.pi/4), 0],[-np.sin(np.pi/4),np.cos(np.pi/4), 0], [0,0,1]])
shr_mat = np.array([[1, 0.45, 0], [0, 0.75, 0], [0, 0, 1]])
transformed = affine_transform(im, rot_mat@shr_mat, offset=[-im.shape[0]/4+25, im.shape[1]/2-50, 0], output_shape=im.shape)
(3) 绘制输入和输出图像,运行代码生成的输出图像:
plt.figure(figsize=(20,10))
plt.subplot(121), plt.imshow(im), plt.axis('off'), plt.title('Input image', size=10)
plt.subplot(122), plt.imshow(transformed), plt.axis('off'), plt.title('Output image', size=10)
plt.show()