美文网首页
[python][科学计算][numpy]使用指南8-其他

[python][科学计算][numpy]使用指南8-其他

作者: jiedawang | 来源:发表于2019-03-05 22:48 被阅读0次

    最后一次更新日期: 2019/3/8

    NumPy 是一个 Python 包。 它代表 “Numeric Python”。 它是一个由多维数组对象(ndarray)和用于处理数组的例程集合组成的库。
    使用NumPy,开发人员可以执行以下操作:

    • 数组的算数和逻辑运算。
    • 傅立叶变换和用于图形操作的例程。
    • 与线性代数有关的操作。 NumPy 拥有线性代数和随机数生成的内置函数。

    使用前先导入模块:
    import numpy as np

    1. 矩阵类型

    numpy提供了一个专用的矩阵对象matrix,是基于 ndarray作了进一步的封装得到的,能够更加快捷地进行一些矩阵相关的运算,但相比ndarray没有性能上的优势且维数限制在二维,并不推荐使用。

    (1). 创建
    In [79]: m1=np.matrix([[1,2],[3,4]])
    
    In [81]: m1
    Out[81]: 
    matrix([[1, 2],
            [3, 4]])
    

    创建方式与ndarray类似。

    (2). 与 ndarray的相互转换
    In [82]: a=np.array([[5,6],[7,8]])
    
    In [83]: m2=np.matrix([[5,6],[7,8]])
    
    In [84]: np.asmatrix(a)
    Out[84]: 
    matrix([[5, 6],
            [7, 8]])
    
    In [85]: np.matrix(a)
    Out[85]: 
    matrix([[5, 6],
            [7, 8]])
    
    In [88]: np.asarray(m2)
    Out[88]: 
    array([[5, 6],
           [7, 8]])
    
    In [89]: np.array(m2)
    Out[89]: 
    array([[5, 6],
           [7, 8]])
    
    In [90]: m2.base
    Out[90]: 
    array([[5, 6],
           [7, 8]])
    
    (3). 矩阵运算
    In [94]: m1*m2
    Out[94]: 
    matrix([[19, 22],
            [43, 50]])
    
    In [95]: m1.I
    Out[95]: 
    matrix([[-2. ,  1. ],
            [ 1.5, -0.5]])
    
    In [96]: m1.T
    Out[96]: 
    matrix([[1, 3],
            [2, 4]])
    

    运算符*用在matrix上表示矩阵乘法,等效于np.dot(m1,m2),要实现元素相乘需要使用np.multiply(m1,m2)
    matrix.T表示转置矩阵,matrix.I表示逆矩阵。
    matrix可以使用大部分ndarray的方法,比如maxsumsort等。

    2. 张量运算

    张量是向量、矩阵这类概念的推广,标量是0阶张量,向量是1阶张量,矩阵是2阶张量。
    numpy提供了广义的张量点积运算np.tensordot

    In [2]: a=np.arange(1,9).reshape((2,2,2))
    
    In [3]: b=np.arange(1,5).reshape((2,2))
    
    In [4]: a
    Out[4]: 
    array([[[1, 2],
            [3, 4]],
    
           [[5, 6],
            [7, 8]]])
    
    In [5]: b
    Out[5]: 
    array([[1, 2],
           [3, 4]])
    
    In [8]: np.tensordot(a,b,axes=1)
    Out[8]: 
    array([[[ 7, 10],
            [15, 22]],
    
           [[23, 34],
            [31, 46]]])
    
    In [9]: np.tensordot(a,b,axes=(-1,0))
    Out[9]: 
    array([[[ 7, 10],
            [15, 22]],
    
           [[23, 34],
            [31, 46]]])
    
    In [10]: np.tensordot(a,b,axes=2)
    Out[10]: array([30, 70])
    
    In [12]: np.tensordot(a,b,axes=([-2,-1],[0,1]))
    Out[12]: array([30, 70])
    
    In [13]: np.dot(a,b)
    Out[13]: 
    array([[[ 7, 10],
            [15, 22]],
    
           [[23, 34],
            [31, 46]]])
    
    In [14]: np.tensordot(a,b,axes=(-1,-2))
    Out[14]: 
    array([[[ 7, 10],
            [15, 22]],
    
           [[23, 34],
            [31, 46]]])
    
    In [15]: np.inner(a,b)
    Out[15]: 
    array([[[ 5, 11],
            [11, 25]],
    
           [[17, 39],
            [23, 53]]])
    
    In [16]: np.tensordot(a,b,axes=(-1,-1))
    Out[16]: 
    array([[[ 5, 11],
            [11, 25]],
    
           [[17, 39],
            [23, 53]]])
    

    前两个参数ab为参与运算的两个张量。
    第三个参数axes用于指定收缩的轴,完整格式形如([a_axis1,a_axis2,...],[b_axis1,b_axis2,...]),两个序列分别指定ab的轴,轴方向上的元素会按照被指定的顺序对应、相乘并相加;可使用(a_axis,b_axis)的形式仅指定一个轴;
    可使用int类型快速指定a中最后N个轴和b中前N个轴用于收缩,即0等效于([],[]),对应张量积运算,1等效于([-1],[0]),对应张量内积运算,2等效于([-2,-1],[0,1]),对应张量双收缩运算,axes的默认值为2
    np.dotnp.inner这类运算可视作该函数表示的几个特例,np.dot(a1,a2)等效于np.tensordot(a1,a2,axes=(-1,-2))np.inner(a1,a2)等效于np.tensordot(a1,a2,axes=(-1,-1))

    3. 傅里叶变换

    (1) 频率序列
    In [12]: np.fft.fftfreq(10,1.0)
    Out[12]: array([ 0. ,  0.1,  0.2,  0.3,  0.4, -0.5, -0.4, -0.3, -0.2, -0.1])
    

    返回离散傅里叶变换采样频率,第一个参数n为窗口长度,int类型,第二个参数d为采样间距(采样率的倒数),默认为1.0,返回值单位与采样间距单位相对应。
    返回值序列的计算方式:
    如果n是偶数,f = [0, 1, ..., n/2-1, -n/2, ..., -1] / (d*n)
    如果n是奇数,f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n)

    (2) 快速傅里叶变换
    In [13]: x=np.cos(np.linspace(0,2*np.pi,30))
    
    In [14]: y=np.fft.fft(x)
    
    In [15]: x2=np.fft.ifft(y)
    
    In [16]: np.abs(x2-x).max()
    Out[16]: 3.8864883384594504e-16
    

    np.fftnp.ifft互为逆运算,用于一维快速傅里叶变换,经np.fft变换后的序列可通过np.ifft近似还原为原序列。
    第二个参数n指定输出的变换轴长度,超长裁剪,不足补0;
    第三个参数axis指定用于变换的轴,默认最后一个轴。

    (3) 移频
    In [21]: x=np.linspace(0,2*np.pi,8)
    
    In [22]: y=np.fft.fft(x)
    
    In [23]: y2=np.fft.fftshift(y)
    
    In [24]: y3=np.fft.ifftshift(y2)
    
    In [32]: np.abs(y3-y).max()
    Out[32]: 0.0
    

    np.fftshiftnp.ifftshift互为逆运算,用于将傅里叶变换输出中的直流分量移动到频谱的中央。第二个参数axis可指定用于转移的轴。

    4. 图像处理

    图像数据的存储方式是类似于数组的,可借助PIL库读取图片,再将图像数据转成ndarray进行计算处理。
    以下提供一些使用numpy配合PIL处理图片数据的方法:

    (1) 图片的创建、读取、缩放、保存
    In [2]: from PIL import Image
       ...: image1= Image.open("D:\\test.jpg")
    
    In [3]: image1.size
    Out[3]: (1015, 610)
    
    In [4]: image2=image1.resize((500,300))
    
    In [5]: image2.save("D:\\test2.jpg")
    
    In [6]: image0=Image.new('RGB',image2.size)
    
    In [7]: image2
    Out[7]: 
    

    Image.open用于打开一张图片,mode可以设置读取模式,最常用的是'L'灰度图和'RGB'彩色图,一般会自动匹配不需要设置。
    图片对象的resize方法可以缩放图片,大小参数以tuple类型(width,height)格式传入。
    图片对象的save方法可以保存图片,通过保存路径中的文件拓展名或是format参数指定保存文件类型,quality参数可以设置保存图像的质量,取值1(最差)~ 95(最佳),默认75。
    Image.new用于创建一个新的图片,mode参数指定模式,size指定大小。
    IPython中,直接输入图片变量名就可以显示图片。

    (2) 图片与数组之间的转换
    In [7]: a=np.asarray(image2)
    
    In [8]: a.shape
    Out[8]: (300, 500, 3)
    
    In [9]: image3=Image.fromarray(a,'RGB')
    

    np.asarraynp.array可以将图片转换为ndarraynp.asarray返回图片数据的ndarray类型视图,不能更改。根据类型的不同,得到的数组形状也不一样,常见的两种,灰度图转换得到形状为(height,width)的数组,彩色图转换得到形状为(height,width,channel)的数组,channel即颜色通道,RGB模式下channel=3,分别对应红绿蓝。
    Image.fromarray可以将ndarray转换为图片,可通过mode参数指定模式,默认会根据数组形状自动匹配,当指定某个模式时,数组形状也需要匹配。
    注意,数组转图片需要是uint8数据类型,取值0~255,如不符合要进行另外的转换。

    (3) 像素点绘制
    In [10]: a0=np.array(image0)
    
    In [11]: a0+=np.random.randint(0,256,a.shape,dtype='uint8')
    
    In [12]: image4=Image.fromarray(a0)
    
    In [13]: image4.putpixel((0,0),(255,255,255))
    
    In [14]: image4 
    Out[14]: 
    

    图片对象的putpixel方法可以添加单个像素点,第一个参数xy(x,y)的形式声明添加像素点的位置,第二个参数value指定像素点的值,例如,L灰度图模式下为标量值,RGB彩色图模式下为(r,g,b)形式的tuple,取值均在0~255之间。该方法一次只能绘制一个像素点,效率低,在需要批量绘制时建议转换为ndarray处理。
    上面的示例中使用ndarray的方法为新图片的每一个像素点添加了随机色彩。

    (4) 灰度图和彩色图之间的转换
    In [72]: a2=np.asarray(image2,dtype='float')
    
    In [73]: a5=(11*a2[:,:,0]+16*a2[:,:,1]+5*a2[:,:,2])/32
    
    In [74]: image5=Image.fromarray(np.uint8(a5))
    
    In [75]: a6=a5.repeat(3).reshape(a5.shape+(3,))
    
    In [76]: image6=Image.fromarray(np.uint8(a6))
    
    In [77]: image5
    Out[77]: 
    

    彩色图转灰度图,L=11*R+16*G+5*B只是一种可行的公式,也有其他公式可用。
    灰度图转彩色图,较为简单,即将灰度值拷贝到RGB3个通道上,转换后颜色还是灰色,因为灰度图不具备色彩方面的信息,即使先将彩色图转灰度图,再转换回彩色图,色彩信息同样会丢失。
    (5) 图片的翻转、旋转、裁剪
    In [84]:a2=np.asarray(image2)
    
    In [85]:Image.fromarray(a2[::-1,::-1,:])
    Out[85]: 
    
    In [90]:Image.fromarray(a2.transpose([1,0,2]))
    Out[90]: 
    
    In [91]:Image.fromarray(a2[:150,:,:])
    Out[91]: 
    

    以上示例展示了 左右翻转+上下翻转,左右翻转+逆时针转90°,截取上半部分 三种情况,借助倒序索引和轴交换的组合可以得到90°倍数旋转和上下左右翻转的所有组合情形。精确的旋转需要使用矩阵运算,此处不作展开。

    相关文章

      网友评论

          本文标题:[python][科学计算][numpy]使用指南8-其他

          本文链接:https://www.haomeiwen.com/subject/lngauqtx.html