提出需求
用 Python 对图片做旋转、镜像操作时,小伙伴们可能首先想到的是 PIL 、Opencv
等图像处理程序包,只需要一行代码就可以实现目标转换。
这样做的确能够实预期目标,但图像是怎么实现旋转的,这个过程对我们来说就像一个黑盒子,很陌生,为了了解图像变换机制,这篇文章借助 Numpy
数组来实现图像翻转等操作
原理讲解
一张图片的本质是由 a(长) × b(宽)
与图像一样大小的矩阵的像素值组成的,一张照片的呈现因为两点:1,图像中各像素值不一样;2,图像中的像素不是随机排列,需要遵从某种固定的排列方式。
一般常见到的 角度旋转、水平镜像图像变换实质上就是图像的排列方式不同 , 如果想实现相应功能需要做的就是把原有排列方式的图像像素拼接成一种新的排列方式
为了方便大家理解,特地画了两张图用于展示图像变换的基本原理( 字母 A-I
表示像素 ),
下面这张图表示的是水平旋转 90度的过程,(本质就是像素点位置的移动,其值不变)
下面这张图表示图像水平镜像转换过程,原理图:
旋转180度整个思路就是把角对角像素进行替换:原理图:
代码实操
展示原图
上面知道图像变换原理,接下来就是代码实现了,要用数组实现转换功能, Numpy
程序包自然是主要工具,首先要做的是读取图像,再借助于函数 numpy.asarray()
把图像转化为数组形式
from PIL import Image
img_path = 'E:/ceshi/face_recognise/501.jpg'
img = Image.open(img_path)
arr = np.asarray(img)
#打印数组维度
print(arr.shape)
ply.imshow(arr)
可以看到数组维度为 354×236×3
, 354
和 236
表示的是图像的尺寸大小,后面的3表示的是每个像素值 RGB数值
,图像变换过程中需要变换的是 354 × 236
,主要注意的是,变换过程中不能改变是[r g b] 像素值
,
垂直镜像;
用数组来实现垂直镜像,需要做的只有一步,就是把像素中的行排列逆置即可,代码如下
arr1 = arr[::-1]
ply.imshow(arr1)
旋转180度
用代码实现的话分为三部分:
- 利用
reshape(arr.size/3,3)
把所有像素值重新排列成a*3
二维矩阵: - 利用
arr[::-1]
实现数组顺序逆置,把头部逆置到尾部; -
reshape(arr.shape[0],arr.shape[1],arr.shape[2])
,把逆置之后的数数组恢复到原数组维度;
arr2 =arr.copy()
arr2= arr.reshape(int(arr.size/3),3)#图像像素维度变形为 a*3格式,要保证每个RGB数组不发生改变;
arr2 =np.array(arr2[::-1])#进行行逆置
arr2 = arr2.reshape(arr.shape[0],arr.shape[1],arr.shape[2])#再对图像进行一次变换,变成 源图像的维度
ply.imshow(arr2)
水平镜像
水平镜像只需要在旋转180度的数组上面进行一次行逆置即可:
arr2 =arr.copy()
arr2= arr.reshape(int(arr.size/3),3)
arr2 =np.array(arr2[::-1])
arr2 = arr2.reshape(arr.shape[0],arr.shape[1],arr.shape[2])
ply.imshow(arr2[::-1])
逆时针旋转90度
逆时针旋转90度的话分为两步:
- 1,
arr2 = arr.transpose(1,0,2)
实现行列置换; - 2,
arr2 = arr2[::-1]
实现水平镜像;
arr2 =arr.copy()
arr2= arr.transpose(1,0,2)#行列转置
ply.imshow(arr2[::-1])
顺时针旋转90度
实现顺时针旋转 90 度,可以在实现逆时针旋转90度的基础上,进行一次180旋转即可:
arr2 =arr.copy()
arr2= arr2.transpose(1,0,2)[::-1]
arr2= arr2.reshape(int(arr2.size/3),3)
arr2 =np.array(arr2[::-1])
#恢复原数组维度,这个需要注意,图像长宽尺寸与原图相反;
arr2 = arr2.reshape(arr.shape[1],arr.shape[0],arr.shape[2])
ply.imshow(arr2)
好了以上就是本篇文章的基本内容,最后感谢阅读!