NumPy库

用于表示数据

1. NumPy库入门

在cmd命令安装NumPy包

pip install -i https://mirrors.aliyun.com/pypi/simple/ NumPy

python中调用NumPy库,运行没有报错,说明安装完成

import numpy as np

as np:将import的numpy给出一个别名,即引入模块的别名。这里可以去掉as np,也可将np改成其他的名字
尽管别名可以省略或者更改,但是建议使用上述约定的别名

1.1 数据的维度

维度:一组数据的组织形式
一维数据:由对等关系的有序或无序数据构成,一般采用线性方式组织。对应列表、数组、集合等概念
列表和数组:都是表示一组数据的有序结构。列表的数据类型可以不同,数组的数据类型相同
二维数据:由多个一维数据构成,是一维数据的组合形式。表格是电信的二维数据,其中表头可以是二维数据的一部分,也可是之外的部分
多维数据:由一维或二维数据在新维度上扩展而形成的
高维数据:仅利用最基本的二元关系展示数据间的复杂结构。对应键值对,如湖南-长沙、陕西-西安等

类型 数据的Python表示
一维数据 列表 [1, 2, 3](有序)
一维数据 集合 {1, 2, 3}(无序)
二维/多维 列表 [[1, 2, 3], [1, 2, 3]]
高维数据字典 字典 {'键' : '值', '键' : '值'}
高维数据字典 数据表示格式 JSON、XML、YAML

1.2 ndarray

ndarray是NumPy中的数组类型
1.2.1 NumPy:开源的Python科学计算基础库
1)提供一个强大的N维数组对象ndarray,也叫数组
2)提供一组广播功能的函数,用于数组之间计算
3)整合C/C++/Fortran代码,并且提供整合这些代码的工具
4)提供线性代数、傅里叶变换、随机数生成等功能

1.2.2 ndarray:N维数组对象

# ndarray对象定义
import numpy as np
a = np.arary([1, 2])
a = np.arary([[1, 2], [1,2]]) # 用[]将数据括起来

用以下例子表明numpy和正常运算的区别:计算A2+B3,A、B是一维数组

'''正常运算'''
def pySum():
    a = [0, 1, 2, 3, 4]
    b = [9, 8, 7, 6, 5]
    c = []
    for i in range(len(a)):
        c.append(a[i]**2 + b[i]**3)
    return c
print(pySum()) # [729, 513, 347, 225, 141]

'''numpy方法'''
import numpy as np
def npSum():
    # 用np.array生成一个数组ab
    a = np.array([0, 1, 2, 3, 4])
    b = np.array([9, 8, 7, 6, 5])
    c = a**2 + b**3
    return c
print(npSum()) # [729, 513, 347, 225, 141]
  1. 数组对象可以去掉元素间运算所需的循环,使一维数据更像单个数据
  2. 设置专门的数组对象,提示运算速度
  3. 在科学计算中,一个维度所有数据的类型往往相同。所以数组对象采用相同的数据类型,有利于节省运算和存储空间

ndarray由2部分构成:实际的数据、表述这些数据的元数据(数据维度、数据类型等)
ndarray要求所以有元素类型相同(同质),数组下标从0开始

'''ndarray实例'''
import numpy as np
# 用np.arrary定义一个ndarray数组。ndarray在程序中的别名就是array
a = np.array([[0, 1, 2, 3, 4], [9, 8, 7, 6, 5]])
a # 直接显示时,会用array()来表明数组类型(如下图)
print(a) # 打印时用[]来表示维度关系,元素间以空格来分离
NumPy库_第1张图片
ndarray实例.png

1.2.3 ndarray属性

ndarray的2个基本概念:1)轴(axis):保存数据的维度;2)秩(rank):轴的数量,或者维度的数量,即数组有多少个维度
轴和秩是描述ndarray类型的基本向量和方式

ndarray属性 说明
.ndim
.shape 尺度,对于矩阵n行m列
.size 元素个数,相当于.shape中n*m的值
.dtype 元素类型
.itemsize 每个元素大小,以字节为单位
import numpy as np
a = np.array([[0, 1, 2, 3, 4], [9, 8, 7, 6, 5]])
a.ndim # 2
a.shape # (2, 5)
a.size # 10
a.dtype # dtype('int32')【int32在基础的Python语法中并不存在,他是numpy定义的元素类型(具体见下表)】
a.itemsize # 4

ndarray元素类型

元素类型 说明 元素类型 说明
bool 布尔类型,True或False uint8 8位无符号整数,取值:[0, 225]
intp 用于索引的整数 uint16 16位无符号整数,取值:[0, 65535]
intc int32或int64 uint32 32位无符号整数,取值:[0, 2^32-1]
int8 8位字节长度的整数,取值:[-128, 127] uint64 8位无符号整数,取值:[0, 2^64-1]
int16 16位长度的整数,取值:[-32768, 32767] float16 16位半精度浮点数:1位符号位,5位指数,10位尾数
int32 32位长度的整数,取值:[-2^31, 2^31-1] float32 32位半精度浮点数:1位符号位,8位指数,23位尾数
inte64 字节长度的整数,取值:[-2^63, 2^63-1] float64 64位半精度浮点数:1位符号位,11位指数,52位尾数
complex64 复数类型,实部和虚部都是32位浮点数 complex128 复数类型,实部和虚部都是64位浮点数

Python语法仅支持整数、浮点数和复数3种数据类型

ndarray的元素多样性

  1. 能够符合在科学计算(数据多)对存储和性能的高要求
  2. 对元素类型精细定义,有助于NumPy合理使用存储空间并优化性能,且有助于程序员对程序的规模合理评估

ndarray最好是同质的数组类型,但也可以包含非同质的元素(如下代码)

import numpy as np
a = np.array([[0, 1, 2, 3, 4], [9, 8, 7, 6]])
a # array([list([0, 1, 2, 3, 4]), list([9, 8, 7, 6])], dtype=object)
a.ndim # 1
# .shape只看到2个元素,但是没有进一步分析
a.shape # (2,)
a.size # 2
# 非同质ndarray,将每个元素认为是一个对象类型(dtype('0'))
a.dtype # dtype('0')
a.itemsize # 8

非同质ndarray无法发挥UnmPy的优势,应该尽量避免

1.3 数组创建

ndarray数组创建方法

  1. Python中的列表、元组
  2. NumPy中的函数
  3. 字节流(raw bytes)
  4. 从文件中读取特定格式

1.3.1 从Python中的列表、元组创建ndarray数组

import numpy as np
# 直接将列表、元组当相关参数输入给np.array()函数
# 可以用dtype指定每个元素的数据类型【如果不指定,NumPy将根据读入的数据关联一个dtype类型】
a = np.array(list/tuple, dtype = np.float34)

只要元组和列表包含的数据个数相同,可以将列表和元组回合,一起混合使用,来创建

1.3.2 使用NumPy中的函数创建ndarray数组

函数 说明
np.arange(n) 类似range(),返回ndarray类型,元素从0-n-1(整数类型)
np.ones(shape) 根据shape生成一个全1数组,shape是元组类型(浮点数类型)
np.zeros(shape) 根据shape生成一个全0数组,shape是元组类型(浮点数类型)
np.full(shape,val) 根据shape生成一个数组,每个元素值都是val
np.eye(n) 创建一个正方的n*n单位矩阵,对角线为1,其余为0(浮点数类型)
np.arange(10) # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.ones((3,6))
# Out[]: array([[1., 1., 1., 1., 1., 1.],
#              [1., 1., 1., 1., 1., 1.],
#              [1., 1., 1., 1., 1., 1.]])
np.zeros((3, 6), dtype=np.int32)
# Out[]: array([[0, 0, 0, 0, 0, 0],
#              [0, 0, 0, 0, 0, 0],
#              [0, 0, 0, 0, 0, 0]])
np.eye(3)
# Out[]: array([[1., 0., 0.],
#              [0., 1., 0.],
#              [0., 0., 1.]])


# 生成多维数组。最外层有2个元素,每个元素有3个维度,每个维度有4个元素
x = np.ones((2,3,4))
x
# Out[]: array([[[1., 1., 1., 1.],
#              [1., 1., 1., 1.],
#              [1., 1., 1., 1.]],

#             [[1., 1., 1., 1.],
#             [1., 1., 1., 1.],
#             [1., 1., 1., 1.]]])
x.shape # (2,3,4)[shape是由最外层到最内层表示]

np.full((2,3,4), 25, dtype=np.int)
# array([[[25, 25, 25, 25],
#        [25, 25, 25, 25],
#        [25, 25, 25, 25]],

#       [[25, 25, 25, 25],
#        [25, 25, 25, 25],
#        [25, 25, 25, 25]]])
函数 说明
np.ones_like(a) 根据数组a的形状生成一个全1数组
np.zeros_like(a) 根据数组a的形状生成一个全0数组
np.full_like(a, val) 根据数组a的形状生成一个全val数组
np.linspace() 根据起止数据等间距地填充数据
np.concatenate() 将2个或多个数组合并成1个新数组
a = np.linspace(1, 10, 4)
a # array([ 1.,  4.,  7., 10.])[起始分别为1,10,一共4个数据),不限定数据类型时,生成的是浮点数]

# endpoint表示最后一个元素10是否是元素中的一个
b = np.linspace(1, 10, 4, endpoint = False)
b # array([1.  , 3.25, 5.5 , 7.75])[在1-10之间等间距的生成一个新的值]

c = np.concatenate((a, b))
c # array([ 1.  ,  4.  ,  7.  , 10.  ,  1.  ,  3.25,  5.5 ,  7.75])

1.4 数组变换

维度变换

方法 说明
.reshape(shape) 不改变数组元素,返回一个shape形状的新数组(保证元素总体个数不发生改变)
.resize(shape) 与.reshape(shape)类似,但是替换原数组
.swapaxces(ax1, ax2) 将数组n个维度中的2个维度进行调换
.flatten() 对数组进行降维,返回折叠后的一维数组,原数组不变
a = np.ones((2,3,4), dtype=np.int32)
a
# array([[[1, 1, 1, 1],
#        [1, 1, 1, 1],
#        [1, 1, 1, 1]],

#       [[1, 1, 1, 1],
#        [1, 1, 1, 1],
#        [1, 1, 1, 1]]])

# 将3维数组变为2维数组。都是24个元素个数,a未改变
a.reshape(3, 8)
# Out[]: array([[1, 1, 1, 1, 1, 1, 1, 1],
#              [1, 1, 1, 1, 1, 1, 1, 1],
#              [1, 1, 1, 1, 1, 1, 1, 1]])

# a已改变
a.resize(3, 8)
a
# Out[]: array([[1, 1, 1, 1, 1, 1, 1, 1],
#              [1, 1, 1, 1, 1, 1, 1, 1],
#              [1, 1, 1, 1, 1, 1, 1, 1]])

a.flatten()
# Out[]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

astype()类型变换

# np.int:程序会将元素解析为整数类型,是int32还是int64,是由程序自动调节
a = np.ones((2,3,4), dtype=np.int)
a

# np.float代表一类浮点数类型
b = a.astype(np.float)
b
# array([[[1., 1., 1., 1.],
#        [1., 1., 1., 1.],
#        [1., 1., 1., 1.]],

#       [[1., 1., 1., 1.],
#        [1., 1., 1., 1.],
#        [1., 1., 1., 1.]]])

astype()方法一定会创建一个新的数组,即使定义一个与原数组类型相同的数组,也会有一个新的数组,即可利用这个特性进行拷贝数组

a.tolist()方法将ndarray数组向列表转换

a = np.full((2,3,4), 25, dtype=np.int)
a
a.tolist() # [[[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]], [[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]]]

列表时Python中最原始的数据类型,可能在空间和运算速度比NumPy慢很多。但是更适合传统的或者原生的Python语言语法

1.4 ndarray操作

对数组的索引:获取数组中特定位置元素的过程
对数组的切片:获取数组元素子集的过程
一维数组的索引和切片(与python列表相似)

import numpy as np
a = np.array([1, 2, 3, 4, 5])
a[2] # 3

# 切片,[开始编号:终止编号(不含):步长]
a[1 : 4 : 2] # array([2, 4])
a # array([1, 2, 3, 4, 5])

多维数组的索引和切片

a = np.arange(24).reshape((2, 3, 4))
a
# array([[[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11]],

#        [[12, 13, 14, 15],
#         [16, 17, 18, 19],
#         [20, 21, 22, 23]]])

# 索引,每个维度使用逗号分隔,[第一维度,第二维度,第三维度]
a[1, 2, 3] # 23
a[0, -1, 1] # 9

# 切片,不考虑第一维度,第二维度是1,第三维度是-3的元素
a[:, 1, -3] # array([ 5, 17])

# 切片,第一维度是1,第三维度是所有范围,但是以2为步长
a[1, :, :: 2]
# array([[12, 14],
#        [16, 18],
#        [20, 22]])

1.5 ndarray运算

数组与标量之间的运算:运算作用于数组的每一个元素

a = np.arange(12).reshape((2, 3, 2))

# 平均值
a.mean() # 5.5

# 相除
a / a.mean()
# array([[[0.        , 0.18181818],
#         [0.36363636, 0.54545455],
#         [0.72727273, 0.90909091]],

#        [[1.09090909, 1.27272727],
#         [1.45454545, 1.63636364],
#         [1.81818182, 2.        ]]])

NumPy一元函数:对ndarray中的数据执行元素级运算的函数

函数 说明
np.abs(x) np.fabs(x) 计算数组x各元素的绝对值
np.sqrt(x) np.square(x) 计算数组x元各素的平方根、平方
np.log(x) np.log(10) np.log2(x) 计算数组x各元素的自然对数、10底对数、2底对数
np.ceil(x) np.floor(x) 计算数组x各元素的ceiling值(大于元素的最小整数值)、floor值(小于元素的最大整数值)
np.rint(x) 计算数组x各元素的四舍五入
np.modf(x) 将数组x各元素的小数部分和整数部分以2个独立数组返回
np.cos(x) np.cosh(x) np.sin(x) np.sinh(x) np.tan(x) np.tanh(x) 计算数组x各元素的普通型和双曲线型三角函数
np.exp(x) 计算数组x各元素的指数值
np.sign(x) 计算数组x各元素的符号值,1(+),0,-1(-)
a = np.array([[1.1, 2.1, 3.6], [2.5, 5.9, 4.1]])
np.ceil(a)
# array([[2., 3., 4.],
#        [3., 6., 5.]])

np.floor(a)
# array([[1., 2., 3.],
#        [2., 5., 4.]])

np.modf(a)
# (array([[0.1, 0.1, 0.6],
#         [0.5, 0.9, 0.1]]), array([[1., 2., 3.],
#         [2., 5., 4.]]))

np.exp(np.array([1, 2, 3])) # array([ 2.71828183,  7.3890561 , 20.08553692])

在使用数组时,一定要注意原数组是否被真实改变,
一元函数几乎都是只改变输出结果,不改变原数组(要改变需要重新赋值)

NumPy的二元函数 说明
+ - * / ** 2个数组各元素进行对应运算
np.maximum(x,y) np.fmax() np.miximum(x,y) np.fmix() 元素级的最大值/最小值计算
np.mod(x,y) 元素级的模运算
np.copysign(x,y) 将数组y中个元素值的符号赋值给数组x
< > =< => == != 算术比较,产生布尔型数组
a = np.array([[1.1, 2.1, 3.6], [2.5, 5.9, 4.1]])
b = np.array([[1, 2, 3], [4, 5, 6]])

np.maximum(a, b)
# array([[1.1, 2.1, 3.6],
#        [4. , 5.9, 6. ]])

np.fmax(a, b)
# array([[1.1, 2.1, 3.6],
#        [4. , 5.9, 6. ]])

a > b
# array([[ True,  True,  True],
#        [False,  True, False]])

np.mod(a, b)
# array([[0.1, 0.1, 0.6],
#        [2.5, 0.9, 4.1]])

2. NumPy数据存取

2.1 一、二维

CSV(Comma-Separated Value)逗号分隔值
一种文件格式,用来存储批量数据
将数据写入CSV文件(将数据保存为CSV文件)

np.savetxt(frame, array, fmt = '%.18e', delimiter = None)

frame:文件、字符串或产生器,可以是.gz或.bz的压缩包
array:存入文件的数组
fmt:写入文件的格式,例如%d(整数)、%.2f(保留2个小数点)、%.18e(科学计算法,保留18位小数点的浮点数)
delimiter:分割字符串,默认是任何空格(写入CSV需呀改成逗号)

a = np.arange(100).reshape(5, 20)
np.savetxt('a.csv', a, fmt = '%d', delimiter=',') # 【在python运行目录下生成相应的a.csv文件,包含维度信息】

读入csv文件

np.loadtxt(frame, dtype = np.float, delimiter = None, unpack = False)

dtype:数据类型,可选np.int
unpack:False读入文件写入一个数组,如果True,读入属性将分别写入不同变量

b = np.loadtxt('a.csv', delimiter=',')

局限性:只能有效存储一维和二维数组

2.2 多维数组

写入/存储多维数组

a.tofile(frame, sep = '', format = '%s')

frame:文件、字符串
sep:数据分隔字符串,如果是空串,写入文件为二进制
format: 写入数据的格式

a = np.arange(100).reshape(5, 10, 2)
a.tofile('b.dat', sep = ',', format = '%d') # 【在python运行目录下生成相应的b.dat文件,不包含维度信息)

读入多维数据文件

np.fromfile(frame, dtype = np.float, count = -1, sep = '')

count:读入元素个数,-1表示读入整个文件

c = np.fromfile('b.dat', dtype = np.int, sep = ',')
c # 【一维数组,没有维度信息】

c.reshape(5, 10, 2)

tofile()写入多维数组,维度信息消失,读取后需要重新定义维度信息
存入是需要知道数组的维度信息和元素类型

2.3 便捷文件存储

# 存入(有原数组的维度信息)
np.save(frame, array)
np.savez(frame, array)
# 读取(有原数组的维度信息)
np.load(frame)

frame:文件名,以.npy为扩展名,压缩扩展名为.npz

a = np.arange(100).reshape(5, 10, 2)
np.save('a.npy', a)
b = np.load('a.npy')

这个方法是以二进制 存储文件,第一行为数组的原始信息(包括维度)

3. NumPy函数

3.1 随机数函数

NumPy的random子库,能够提供随机数,调用方法np.random.

常用随机数函数 说明
randint(low,high, (shape)) 根据shape创建随机整数数组,范围[low,high)
seed(s) 随机数种子,s是给定的种子值
np.random.randint(100, 200, (5,))
# array([111, 128, 174, 188, 109])【一维数组创建】
np.random.randint(100, 200, (2,3))
# array([[109, 115, 164],
#        [128, 189, 193]])

np.random.seed(10)
np.random.randint(100, 200, (2,3))
# array([[109, 115, 164],
#        [128, 189, 193]])
np.random.seed(10)
np.random.randint(100, 200, (2,3))
# array([[109, 115, 164],
#        [128, 189, 193]])

通过重复给定随机数种子,可以生成同一个随机数组

高级随机数函数 说明
shuffle(a) 根据数组a的第0轴(最外维度)进行随机排列,改变数组a
permutation(a) 根据数组a的第0轴进行随机排列,产生一个新数组,不改变数组a
choice(a,size,replace,p) 从一维数组a中以概率p抽取元素,形成size形状的新数组,replace表示是否可以重用元素,默认为Ture
a = np.random.randint(100, 200, (2,3))
a
# array([[127, 118, 193],
#        [177, 122, 123]])

np.random.shuffle(a)
a
# array([[177, 122, 123],
#        [127, 118, 193]])【数组改变】

np.random.permutation(a) # 【不改变数组】
# array([[127, 118, 193],
#        [177, 122, 123]])
a
# array([[177, 122, 123],
#        [127, 118, 193]])

b = np.random.randint(100, 200, (5,))
b
# array([105, 104, 171, 188, 188])
np.random.choice(b,(2,2))
# array([[171, 188],
#        [171, 105]])
np.random.choice(b,(2,2),p = b/np.sum(b))
# array([[171, 104],
#        [171, 105]]) 【设定的这个概率使得越大的数抽到的概率越大】
分布式随机数函数 说明
rand(d0,d1,...,dn) 产生浮点数[0,1)的均匀分布的数组,d0-dn是维度信息
uniform(low, high, size) 产生具有均匀分布的数组
randn(d0,d1,...,dn) 产生数值是标准正态分布的数组,d0-dn是维度信息
normal(loc, scale,size) 产生具有正太分布的数组,loc均值,scale标准差
poisson(lam, size) 产生具有泊松分布的数组,lam随机事件发生概率
np.random.rand(2, 3)
# array([[0.37447814, 0.03649257, 0.4805653 ],
#        [0.48993116, 0.41622894, 0.5778854 ]])

np.random.randn(2,3)
# array([[-0.70733753, -1.97096895,  0.9567542 ],
#        [ 1.09554293,  1.52540993, -0.84229966]])

np.random.uniform(1, 10, (2,2))
# array([[1.35353591, 4.21463583],
#        [1.71651781, 3.74913927]])

np.random.normal(10, 5, (2,2))
# array([[15.64392577,  6.51094985],
#        [ 9.59438908,  7.3535196 ]])

3.2 统计函数

NumPy直接提供统计函数,调用方法np.

常用统计函数 说明
sum(a, axis = None) 根据给定轴axis计算数组a相关元素之和
mean(a, axis = None) 根据给定轴axis计算数组a相关元素的期望
average(a,axis=None,weights=None) 根据给定轴axis计算数组a相关元素的加权平均值
std(a, axis = None) 根据给定轴axis计算数组a相关元素的标准差
var(a, axis = None) 根据给定轴axis计算数组a相关元素的方差

axis = None是统计函数的标配参数,axis是整数或元组

a = np.arange(24).reshape(2,3,4)
a
# array([[[ 0,  1,  2,  3],
#         [ 4,  5,  6,  7],
#         [ 8,  9, 10, 11]],

#        [[12, 13, 14, 15],
#         [16, 17, 18, 19],
#         [20, 21, 22, 23]]])

np.sum(a) # 276

# 第一维度上,相对应的元素相加,得到一个第二维度和第三维度的数组
# 本例中,第一维度有2个,第1个第一维度+第2个第一维度
np.sum(a, axis = 0) 
# array([[12, 14, 16, 18],
#        [20, 22, 24, 26],
#        [28, 30, 32, 34]])

# 第二维度上,相对应的元素相加,得到一个第一维度和第三维度的数组
# 本例中,第二维度有3个,在第1个第一维度中:第1个第二维度+第2个第二维度+第3个第二维度;在第2个第一维度中亦然
np.sum(a, axis = 1)
# array([[12, 15, 18, 21],
#        [48, 51, 54, 57]])

# 第三维度上,相对应的元素相加,得到一个第一维度和第二维度的数组
np.sum(a, axis = 2)
# array([[ 6, 22, 38],
#        [54, 70, 86]])
NumPy库_第2张图片
统计函数 1.png

axis = 0,红框数字运算
axis = 1,蓝框数字运算
axis = 2,黄框数字运算

np.average(a,axis=1)
# array([[ 4.,  5.,  6.,  7.],
#        [16., 17., 18., 19.]])

# 轴为1时,是第二维度数据,第二维度有3个,所有需要分别指出其加权力度
np.average(a,axis=1, weights=[2,4,6])
# array([[ 5.33333333,  6.33333333,  7.33333333,  8.33333333],
#        [17.33333333, 18.33333333, 19.33333333, 20.33333333]])

加权平均数=元素*相应加权之和/权重之和
不设定时,默认哥权重为1,即平均值

其他统计函数 说明
min(a) max(a) 计算数组a中元素的最小、大值
argmin(a) argmax(a) 计算数组a中元素最小、大值的降一维下标(即获得最小、大值的一维位置)
unravel_index(index,shape) 根据shape将一维下标的index装换成多维下标
ptp(a) 计算数组a中元素最大值与最小值差
median(a) 计算数组a中元素中位数的运算(中值)
np.argmax(a) # 23
np.unravel_index(np.argmax(a), a.shape) # (1, 2, 3)
NumPy库_第3张图片
统计函数 2.png

axis = 0,黑框,第1个第一维度
axis = 1,红框,第1个第二维度
axis = 2,绿框,第4个第三维度

3.3 阶梯函数

np.gradient(a):计算数组a中的梯度,当a为多维数组时,返回每个维度梯度
梯度:连续值之间的变化率,即斜率。反应元素的变化率

在XY坐标抽连续三个X坐标应用的Y轴值:a,b,c,b的梯度是(c-a)/2
对于2个顶点数值,是(当前数值-隔壁数值)/1

import numpy as np
a = np.random.randint(0, 20,(5))
a # array([ 2, 19, 15, 12, 19])
np.gradient(a) # array([17. ,  6.5, -3.5,  2. ,  7. ])
NumPy库_第4张图片
统计函数 1.png
b = np.arange(24).reshape(2,3,4)
np.gradient(b)
# [array([[[12., 12., 12., 12.],
#          [12., 12., 12., 12.],
#          [12., 12., 12., 12.]],
 
#         [[12., 12., 12., 12.],
#          [12., 12., 12., 12.],
#          [12., 12., 12., 12.]]]),【数组在第一维度(红框)梯度值】
# array([[[4., 4., 4., 4.],
#          [4., 4., 4., 4.],
#          [4., 4., 4., 4.]],
 
#         [[4., 4., 4., 4.],
#          [4., 4., 4., 4.],
#          [4., 4., 4., 4.]]]), 【数组在第二维度(蓝框)梯度值】
# array([[[1., 1., 1., 1.],
#          [1., 1., 1., 1.],
#          [1., 1., 1., 1.]],
 
#         [[1., 1., 1., 1.],
#          [1., 1., 1., 1.],
#          [1., 1., 1., 1.]]])] 【数组在第三维度(黄框)梯度值】

4. 图像的手绘

4.1 图像的数组

RBG色彩模式:通过颜色通道变化和叠加得到各种颜色,形成的颜色包括人类实例所能感知的所有颜色

  • R红色:0-255
  • G绿色:0-255
  • B蓝色:0-255

PIL库(Python Image Library):具有强大图像处理能的第三方库

# 安装
pip install pillow
# 导入
from PIL import Image

Image:是PIL库中代表一个图像的类(对象)

图像的数组表示:由像素组成的三维矩阵,每个元素是一个RGB值

from PIL import Image
import numpy as np
# 将打开的图片生成一个数组
im = np.array(Image.open('E:\TDRDIS Book\编程\Python应用\pig\数据算法途径.jpg'))

# 打印维度和类型
print(im.shape, im.dtype) # (1136, 2122, 3) uint8

维度分别是高度、宽度、像素RGB值构成

4.2 图像的变换

from PIL import Image
import numpy as np
# 读入图像,并获得RGB值数组
im = np.array(Image.open('E:\\TDRDIS Book\\编程\\Python应用\\pig\\111.jpg'))

# 改变数组像素,计算补值
a = [255, 255, 255] - im
# 将数组生成图像对象
im_a = Image.fromarray(a.astype('uint8'))
# 保存图像
im_a.save('E:\\TDRDIS Book\\编程\\Python应用\\pig\\111_a.jpg') # 【获得图片】
NumPy库_第5张图片
aaa.jpg
NumPy库_第6张图片
aaa_a.jpg

convert(L)将彩色变换成灰色图片,生成的数组时一个二维数组,对应的值是灰度值,不是RGB值

im = np.array(Image.open('E:\\TDRDIS Book\\编程\\Python应用\\pig\\aaa.jpg').convert('L'))
# 灰度值取反
b = 255 - im
im_a = Image.fromarray(b.astype('uint8'))
im_a.save('E:\\TDRDIS Book\\编程\\Python应用\\pig\\aaa_b.jpg')

# 区间变化,对当前图片的灰度值做一个区间压缩,再扩充一个区间范围(150)
c = (100/255)*im + 150
im_a = Image.fromarray(b.astype('uint8'))
im_a.save('E:\\TDRDIS Book\\编程\\Python应用\\pig\\aaa_c.jpg')

# 像素平方
d = 255*(a/255)**2
im_a = Image.fromarray(b.astype('uint8'))
im_a.save('E:\\TDRDIS Book\\编程\\Python应用\\pig\\aaa_d.jpg')
NumPy库_第7张图片
aaa_b.jpg
NumPy库_第8张图片
aaa_c.jpg
NumPy库_第9张图片
aaa_d.jpg

4.3 图形的手绘

手绘效果特点:

  • 黑白灰色
  • 边界线较重
  • 相同或相近色彩趋于白色
  • 略有光源效果:根据灰度变化模拟人类视觉的远近程度
NumPy库_第10张图片
图形手绘 1.png
from PIL import Image
import numpy as np
a = np.array(Image.open('E:\\TDRDIS Book\\编程\\Python应用\\pig\\doctor.jpg').convert('L')).astype('float')

# 预设虚拟深度值为10【取值范围是(0-100)】
depth = 10.   
# 取图像灰度的梯度值
grad = np.gradient(a)  
# 分别取横纵图像梯度值
grad_x, grad_y = grad     
# 根据深度调整xy方向的梯度值【添加深度对于梯度的影响因素】
# /100对深度值进行归一化
grad_x = grad_x*depth/100.
grad_y = grad_y*depth/100.
# 构造xy梯度的三维归一化单位坐标系
A = np.sqrt(grad_x**2 + grad_y**2 + 1.)
# 继续整体归一化,uni_x、uni_y、uni_z表示图像平面的单位法向量
uni_x = grad_x/A
uni_y = grad_y/A
uni_z = 1./A

# 光源的俯视角度,弧度值
vec_el = np.pi/2.2                   
# 光源的方位角度,弧度值
vec_az = np.pi/4.  
# 光源对xyz 轴的影响,np.cos(vec_el)在个方向上的投影长度
# dx,sy,dz可以看做光源在坐标中的表示
dx = np.cos(vec_el)*np.cos(vec_az)   
dy = np.cos(vec_el)*np.sin(vec_az)   
dz = np.sin(vec_el)              

# 光源归一化【梯度与光源相互作用,将梯度转化为灰度】
b = 255*(dx*uni_x + dy*uni_y + dz*uni_z)   
# 之前各种归一化,都是为了将影响因子局限在0-1之间,以免投影到梯度范围内,产生溢出,但也有不可避免的
# 为了避免数据越界(溢出),将生产的灰度值裁剪至0-255
# clip()舍弃掉少许溢出的灰度值
b = b.clip(0,255)

# 重构图像
im = Image.fromarray(b.astype('uint8'))  
im.save('E:\\TDRDIS Book\\编程\\Python应用\\pig\\doctor_手绘.jpg')
NumPy库_第11张图片
doctor.jpg
NumPy库_第12张图片
doctor_手绘.jpg

利用像素之间的梯度值和虚拟深度值对图像进行重构
根据灰度变化来模拟人类视觉的明暗程度

目录:Python数据分析与展示
一、NumPy库
二、Matplotlib库
三、Pandas库

NumPy库_第13张图片
Python数据分析与展示.jpg

你可能感兴趣的:(NumPy库)