图像线性变换是图像处理中的基本运算,通常用于调整图像的视觉效果,例如图像对比度、亮度、平移以及缩放等操作。我们可以用以下公式表示图像线性变换,对于输入图像 f ( x , y ) f(x,y) f(x,y),输出图像 g ( x , y ) g(x,y) g(x,y),线性变换表达式为:
g ( x , y ) = α f ( x , y ) + β g(x,y)=\alpha f(x,y)+\beta g(x,y)=αf(x,y)+β
在本节中,我们将学习 2D
线性变换的基本概念以及如何在图像中应用 2D
线性变换。我们首先从基础数学原理入手,以便在代码实现之前了解线性变化的核心思想,然后介绍如何在图像上应用欧几里得变换(例如,旋转、反射)和仿射转换。
2D
线性几何变换是点转换,它们会被应用于图像中的每个像素。由于这些变换是线性的,因此可以使用矩阵乘法或加法等矩阵运算表示图像变换,有四类常见的线性变换:
euclidean transformation
) 或等距映射 (isometry
)最简单的变换称为欧几里得/等距转换,它保留了图像中像素间的欧几里得距离,且使用了相同的度量,属于正交变换,可以使用下式表示:
Ψ ( p ) = R p + t \Psi (p)= R p + t Ψ(p)=Rp+t
其中, R R R 是 2×2
的正交矩阵, t t t 是 2×1
的变换矢量, p = [ x , y ] p = [x,y] p=[x,y] 是要变换的点。欧几里得变换过程中距离、长度和面积是不变的,即等距变换后这些值保持不变。
等距映射具有三个自由度 (Degrees of Freedom
, DoF
),用于旋转矩阵 R R R 的角度 θ θ θ、用于沿 X X X 轴和 Y Y Y 轴方向的平移 t x t_x tx 与 t y t_y ty,对应于变换矢量。欧几里得变换中的矩阵 R R R 是正交的,对于旋转变换而言矩阵行列式为 1
,而对于反射变换而言行列式为 -1
。在坐标系中,一个 2D
点表示为 [ x , y ] [x, y] [x,y],欧几里得变换的旋转和平移可以由坐标中的 3 × 3 3×3 3×3 矩阵 H H H 表示。
仅位置均匀缩放的等轴映射被称为相似性转换。它具有四个自由度,增加的自由度参数用于各向同性缩放。
仿射变换可以认为是非奇异线性变换,它具有六个自由度,增加的两个参数用于进行不均匀缩放。
投影变化是均匀坐标中的非奇异线性变换,它具有八个自由度。
下图显示了 2D
线性几何变换的层次结构。如前所述,欧几里得是仿射的特殊情况,而后者又是投影变换的特殊情况:
有时,我们可能需要几何变换作为图像处理任务中的预处理步骤。在本节中,我们将学习如何使用 scipy.ndimage
模块中的 rotate()
函数旋转图像。接下来,我们将逆时针旋转图像一定的角度,并使用样条插值。
(1) 从相应的 Python
库模块导入所需的函数,读取彩色输入图像:
from scipy.ndimage import rotate
from skimage.io import imread
from matplotlib import pyplot as plt
im = imread('1.png')
(2) 应用 scipy.ndimage
模块的 rotate()
函数,根据输入图像与旋转值执行旋转变换,逆时针旋转按照惯例应当以正角度表示,而顺时针则以负角度表示:
im = rotate(im, -45)
plt.figure(figsize=(5,5))
plt.imshow(im)
plt.axis('off')
plt.show()
在本节中,我们将学习如何使用 NumPy
的翻转操作来实现垂直 (flipped
) 和水平 (flop
) 翻转图像。
(1) 导入必需库,通过 Matplotlib.pyplot
模块读取输入图像,以获取图像 ndarray
作为输入:
import matplotlib.pyplot as plt
import numpy as np
im = plt.imread('1.png')
(2) 使用 Numpy
的 flipud()
函数翻转图像 ndarray
(垂直翻转)。
im_filpped = np.flipud(im)
(3) 绘制原始图像和翻转图像:
plt.figure(figsize=(10, 12))
plt.subplot(211), plt.imshow(im), plt.axis('off'), plt.title('original', size=10)
plt.subplot(212), plt.imshow(im_filpped), plt.axis('off'), plt.title('flipped', size=10)
plt.show()
(4) 使用函数 numpy.filphr()
水平翻转输入图像:
im = plt.imread('2.png')
im_filpped = np.fliplr(im)
plt.figure(figsize=(15, 12))
plt.subplot(121), plt.imshow(im), plt.axis('off'), plt.title('original', size=10)
plt.subplot(122), plt.imshow(im_filpped), plt.axis('off'), plt.title('flopped', size=10)
# np.fliplr(im)
plt.show()
仿射变换将每个像素 f ( x , y ) f(x,y) f(x,y) 从输入图像变换到输出图像中的位置 ( x ′ , y ′ ) = T ( x , y ) (x',y')= T(x,y) (x′,y′)=T(x,y)。如果变换的像素坐标位于输出图像中的两个像素之间,通常通过反射(扭曲,warping
)解决。在本节中,我们将使用 Scipy
库的 ndimage
模块函数实现图像上的仿射变换。
对于输出图像中位置 ( x ′ , y ′ ) (x',y') (x′,y′) 处的每个像素,利用以下公式从输入图像中相应位置处获取像素值:
( x , y ) = T − 1 ( x ′ , y ′ ) (x,y)=T^{-1}(x',y') (x,y)=T−1(x′,y′)
如果输入图像中的像素位于两像素之间,则使用来自相邻像素的插值(例如,使用双线性插值)像素值进行计算。下图显示了向扭曲和反扭曲的概念:
下图给出了每个仿射变换操作的矩阵 (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
模块实现仿射变换。
(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()
图像线性变换是图像处理中的基本运算,在图像处理应用程序中用途广泛,例如增强图像对比度、调节图像亮度、平移图像以及缩放图像等操作,是常见的图像预处理技术。在本节中,我们学习了 2D
线性变换的基本概念以及如何在图像中应用 2D
线性变换,首先从基础数学原理入手,然后使用不同 Python
图像处理库实现了在图像上应用欧几里得变换(例如,旋转、反射)和仿射转换等线性变换。
Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用