Python库之numpy库

numpy库处理的是最起初数据类型是由同种元素构成的多维数组,也就是所谓的数组。数组中的所有元素的类型必须相同,数组中元素可以用整数索引,序号从0开始。

数组类型的维度叫做轴(axes),轴的个数叫做秩(rank)。例如,一维数组的秩为1,二维数组的秩为2。

通常用import numpy as np引入numpy库,以免混淆

一、numpy介绍

  • numpy库常用创建数组函数有以下7个
函数 描述
np.array([x, y, z], dtype = int) 从python列表和元组创建数组
np.arange(x, y, i) 创建一个由x到y,步长为i的数组
np.linspace(x, y, n) 创建一个由x到y,等分成n个元素的数组
np.indices((m, n)) 创建一个m行n列的矩阵
np.random.rand(m, n) 创建一个m行n列的随机数组
np.ones((m, n), dtype) 创建一个m行n列全1的数组,dtype是数据类型
np.empty((m, n), dtype) 创建一个m行n列全0的数组,dtype是数据类型
>>>import numpy as np
>>>a = np.ones((4,5))
>>>a
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])
  • 在创建好数组后,通过以下方法查看基本属性
属性 描述
ndarray.ndim 数组轴的个数
ndarry.shape 数组在每个维度上大小的整数元祖
ndarray.size 数组元素的总个数
ndarray.dtype 数组元素的数据类型,dtype类型可以用于创建数组
ndarray.itemsize 数组中每个元素的字节大小
ndarray.data 包含实际数组元素的缓冲区地址
ndarray.flat 数组元素的迭代器
>>>a.ndim
2
>>>a.shape
(4, 5)
>>>a.size
20
>>>a.dtype
dtype('float64')
>>>a.itemsize
8
>>>a.data

>>>a.flat

  • 改变数组基础形态的操作方法

数组在numpy中被当做对象,可以采用以下方法进行操作。(其中flatten()用于数组降维,在矩阵运算及图像处理中用处很大)

方法 描述
ndarray.reshape(n, m) 不改变数组ndarray,返回一个维度为(n, m)的数组
ndarray.resize(new_size) 与reshape()作用相同,直接修改数组ndarray
ndarray.swapaxes(ax1, ax2) 将数组n个维度中任意两个维度进行调换
ndarray.flatten() 对数组进行降维,返回一个折叠后的一维数组
ndarray.ravel() 作用同flatten()相同,但是返回的是一个数组的视图
>>>a.ravel()
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
       1., 1., 1.])
  • numpy类的索引和切片

数组切片得到的是原始数组的视图,所有修改都会直接反映到源数组

方法 描述
x[i] 索引第i个元素
x[-i] 从后向前索引第i个元素
x[n:m] 默认步长为1,从前往后索引,不包含m
x[-m:-n] 默认步长为1,从后往前索引,结束位置为n
x[n:m :i] 指定i步长的由n到m的索引
>>>b = np.random.rand(5,3);b
array([[0.59532428, 0.72198343, 0.31319579],
       [0.53958629, 0.01385479, 0.35459807],
       [0.06605026, 0.78682018, 0.16177456],
       [0.37520112, 0.93865079, 0.9332923 ],
       [0.97885532, 0.06937877, 0.925661  ]])
>>>b[2]
array([0.06605026, 0.78682018, 0.16177456])
>>>b[1:3]
array([[0.53958629, 0.01385479, 0.35459807],
       [0.06605026, 0.78682018, 0.16177456]])
  • numpy的算术及比较运算函数

numpy的算术运算函数有以下8个

函数 描述
np.add(x1, x2, [,y]) y = x1 + x2
np.subtract(x1, x2, [,y]) y = x1 - x2
np.multiply(x1, x2, [,y]) y = x1 * x2
np.divide(x1, x2, [,y]) y = x1 / x2
np.floor_divide(x1, x2, [,y]) y = x1 // x2
np.negative(x, [,y] y = -x
np.power(x1, x2, [,y]) y = x1 ** x2
np.remainder(x1, x2, [,y]) y = x1 % x2

numpy的比较运算函数有以下7个

函数 描述
np.equal(x1, x2, [,y]) y = x1 == x2
np.not_equal(x1, x2, [,y]) y = x1 != x2
np.less(x1, x2, [,y]) y = x1 < x2
np.less_equal(x1, x2, [,y]) y = x1 <= x2
np.greater(x1, x2, [,y]) y = x1 > x2
np.greater_equal(x1, x2, [,y]) y = x1 >= x2
np.where(condition[x, y]) 根据给出的条件判断输出x还是y
  • numpy还有其他一些实用的函数
函数 描述
np.abs(x) 计算基于元素的整型、浮点型或复数的绝对值
np.sqrt(x) 计算每个元素的平方根
np.squre(x) 计算每个元素的平方
np.sign(x) 计算每个元素的符号:1(+)、0、-1(-)
np.ceil(x) 计算大于或等于每个元素的最小值
np.floor(x) 计算小于或等于每个元素的最大值
np.rint(x, [,out]) 圆整、取每个元素为最近的整数,保留数据类型
np.exp(x, [,out]) 计算每个元素的指数值
np.log(x), np.log10(x), np.log2(x) 计算自然对数(e),基于10/2的对数

二、实例操作

下面将numpy与之前的PIL结合来提取图像特征形成手绘效果

  • 图像的基本处理
>>>from PIL import Image
>>>import numpy as np
>>>im = np.array(Image.open(r'C:\Users\acer\Desktop\flash.jpg'))#加载图像并转换成数组对象
>>>print(im.shape, im.dtype)
(553, 960, 3) uint8

其中(553,960,3)分别表示长度、宽度(单位是像素)以及RGB值

>>>im = np.array(Image.open(r'C:\Users\acer\Desktop\flash.jpg').convert('L'))
>>>print(im.shape, im.dtype)
(553, 960) uint8

通过convert()将图片转换成带有灰度的黑白色,ndarray也变为二维数据

>>>im0 = np.array(Image.open(r'C:\Users\acer\Desktop\flash.jpg').convert('L'))
>>>im1 = 255 - im0 #反变换
>>>im2 = (100/255)*im0 + 150 #区间变换
>>>im3 = 255 * (im1/255) ** 2 #像素平方处理
>>>pil_im1 = Image.fromarray(np.uint(im1))
>>>pil_im2 = Image.fromarray(np.uint(im2))
>>>pil_im3 = Image.fromarray(np.uint(im3))#分别对im1、im2、im3执行
>>>pil_im1.show()
>>>pil_im2.show()
>>>pil_im3.show()

效果图:(左上为原图)

  • 手绘效果处理

为了实现手绘风格,首先需要读取原图像的明暗变化。通常可以使用梯度计算来提取图像轮廓,在numpy中即使用gradient()函数

附上代码

from PIL import Image
import numpy as np
vec_el = np.pi/2.2                   #光源的俯视角度,弧度值
vec_az = np.pi/4.                    #光源的方位角度,弧度值
depth = 10.                             #(0-100)
im = Image.open(r'C:\Users\acer\Desktop\flash.jpg').convert('L')
a = np.asarray(im).astype('float')
grad = np.gradient(a)                #取图像灰度的梯度值
grad_x, grad_y = grad                #分别取横纵图像梯度值
grad_x = grad_x * depth / 100.
grad_y = grad_y * depth / 100.
dx = np.cos(vec_el) * np.cos(vec_az) #光源对x轴的影响
dy = np.cos(vec_el) * np.sin(vec_az) #光源对y轴的影响
dz = np.sin(vec_el)                  #光源对z轴的影响
A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1.)
uni_x = grad_x / A
uni_y = grad_y / A
uni_z = 1. / A
a2 = 255 * (dx*uni_x + dy*uni_y +dz*uni_z)  #光源归一化
a2 = a2.clip(0, 255)
im2 = Image.fromarray(a2.astype('uint8'))   #重构图像
im2.save(r'C:\Users\acer\Desktop\flashHandDraw.jpg')

在上述代码中,利用梯度重构图像时,对应不同梯度取0~255之间不同的灰度值,depth的作用在于调节这个对应关系。当depth较小时,背景区接近白色,显示轮廓描绘;当depth较大时,整体画面灰度值较深,显示浮雕效果

最后附上图片效果
原图:
Python库之numpy库_第1张图片
效果图1(depth = 10):
Python库之numpy库_第2张图片
效果图2(depth = 40):
Python库之numpy库_第3张图片

你可能感兴趣的:(Python)