opencv-python学习笔记3-数组矩阵

目录

一、NumPy概述:

(1)NumPy的主要特点包括:

(2)NumPy的安装:

(3)NumPy的使用示例:

​编辑 二、ndarray对象:

(1)ndarray 的主要特点包括:

(2)创建 ndarray 的方法:

(3)ndarray 的属性:

(4)ndarray 的操作示例:

 三、NumPy数据类型:

(1)常用的 NumPy 数据类型:

(2)代码示例:

 (3) np.dtype 类:

(4)内建类型的字符: 

四、数组属性:

 (1)属性介绍:

(2)示例访问属性:

 (3)ndarray对象的内存信息:

(4)代码示例:

五、新建数组:

(1)使用 np.array:

(2)使用 np.zeros:

(3)使用 np.ones:

(4)使用 np.full:

(5)使用 np.arange:

(6)使用 np.linspace:

(7)使用 np.eye:

(8)使用 np.diag:

(9)使用 np.random 模块:

(10)使用 np.empty:

(11)使用 np.stack, np.concatenate, np.vstack, np.hstack:

 六、从已有的数组创建数组:

 (1)np.asarray:

(2)np.frombuffer :

七、从数值范围创建数组: 

(1)np.arange:

(2)np.linspace:

(3)np.logspace:

(4)np.fromfunction:

(5)np.tile:

(6)np.repeat:

 八、切片和索引:

(1)索引:

(2)切片:

(4)切片语法:

(5)省略和默认值:

(6)负索引:

(7)花式索引:

(8)布尔索引:

(9)切片与复制:

(10)多维数组切片:

 九、迭代数组:

(1) 使用 Python 的 for 循环:

(2)使用 np.nditer:

(3)使用 np.flat 或 np.ravel:

(4) 使用 np.ndenumerate:

(5)使用条件迭代:

(6)使用生成器表达式:

 (7)np.nditer详细介绍:

(8)注意事项:

十、数组操作:

(1) 修改数组形状:

np.reshape:

numpy.ndarray.flat:

 numpy.ndarray.flatten:

numpy.ravel: 

(2)翻转数组:

np.flip:

numpy.transpose : 

 numpy.rollaxis:

numpy.swapaxes : 

(3)修改数组维度:

np.expand_dims:

(4)分割数组:

np.split:

(5) 数组元素的添加和修改:

np.append:

np.insert:


一、NumPy概述:

        NumPy(Numerical Python的缩写)是一个开源的Python科学计算库。它提供了一个强大的N维数组对象ndarray和用于操作这些数组的工具和函数。NumPy是许多其他科学计算和数据分析库(如SciPy、Pandas、Matplotlib、Scikit-learn等)的基础。

(1)NumPy的主要特点包括:

  • 多维数组对象(ndarray):

    • NumPy的核心是一个强大的N维数组对象,它比Python原生的列表更加高效,因为它提供了连续内存块的快速操作。
  • 广泛的数学函数库:

    • 提供了大量的数学函数,用于在数组上进行各种计算,包括统计、代数、傅里叶变换、随机数生成等。
  • 高效的操作:

    • NumPy的数组操作是高度优化的,可以利用底层的C语言和Fortran代码来提高性能。
  • 广播功能:

    • 允许不同形状的数组在算术运算中协同工作,无需显式地匹配维度。
  • 索引和切片:

    • 提供了强大的索引和切片功能,可以方便地访问和修改数组的子集。
  • 输入和输出:

    • 可以轻松地将数组保存到磁盘(使用np.savenp.savez等)和从磁盘加载(使用np.load),也可以与其他格式(如CSV、TXT、JSON等)进行转换。
  • 线性代数、傅里叶变换和随机数生成:

    • 提供了线性代数运算、傅里叶变换和随机数生成的功能,这些都是科学计算中常见的需求。

(2)NumPy的安装:

  • 通常,NumPy可以通过Python的包管理器pip来安装:
pip install numpy

(3)NumPy的使用示例:

import numpy as np

# 创建一个NumPy数组
arr = np.array([1, 2, 3, 4, 5])

# 数组的加法
arr2 = np.array([5, 4, 3, 2, 1])
result = arr + arr2

# 打印结果
print(result)

# 创建一个2x3的二维数组
matrix = np.array([[1, 2, 3], [4, 5, 6]])

# 打印矩阵
print(matrix)

# 矩阵转置
print(matrix.T)

运行结果: 

 二、ndarray对象:

   ndarray 是 NumPy 中的核心数据结构,它是一个多维数组对象,用于有效地存储和操作大规模数据集。ndarray 在内部由同类型数据的连续块组成,这使得它在执行数组操作时非常高效。

(1)ndarray 的主要特点包括:

  • 同质性:

    • ndarray 中的所有元素必须是相同类型的。这意味着数组中的数据类型是一致的,例如,一个数组可以包含整数、浮点数或布尔值,但不能同时包含多种类型。
  • 固定形状:

    • 一旦创建,ndarray 的形状(即维度大小)是固定的。如果需要改变形状,通常会创建一个新的数组。
  • 快速操作:

    • ndarray 支持快速的数组操作,包括元素级运算、切片、索引、广播等。
  • 广播:

    • 广播是一种强大的机制,它允许 NumPy 用不同形状的数组进行算术运算,而不需要显式地匹配维度。
  • 切片:

    • 可以通过切片来访问 ndarray 的子集,切片操作返回原始数组的视图,而不是副本。
  • 索引:

    • 可以通过索引来访问、修改或赋值 ndarray 中的单个元素或元素组。
  • 内存效率:

    • ndarray 在内存中紧凑地存储数据,这使得它在处理大型数据集时非常高效。

(2)创建 ndarray 的方法:

  • 直接从列表创建

    import numpy as np
    array = np.array([1, 2, 3, 4, 5])
  • 使用 np.zeros 创建全零数组

    zeros_array = np.zeros((3, 4))  # 创建一个3x4的全零数组
  • 使用 np.ones 创建全一数组

    ones_array = np.ones((2, 2))  # 创建一个2x2的全一数组
  • 使用 np.arange 创建范围数组

    range_array = np.arange(10)  # 创建一个包含0到9的数组
  • 使用 np.empty 创建未初始化的数组

    empty_array = np.empty((3, 3))  # 创建一个3x3的未初始化数组

(3)ndarray 的属性:

  • .shape:返回数组的形状,即每个维度的大小。
  • .size:返回数组中元素的总数。
  • .dtype:返回数组中元素的数据类型。
  • .ndim:返回数组的维度数。

(4)ndarray 的操作示例:

np.array 是 NumPy 库中用于创建数组的函数。

  • 函数原型:
numpy.array(object, dtype=None, copy=True, order='C', subok=False, ndmin=0)
  • 参数

  • object : array_like

    • 输入数据,可以是列表、元组、另一个数组或任何可迭代的对象。np.array 将这些数据转换成 ndarray。
  • dtype : data-type, optional

    • 数据类型。默认为 None,这意味着数组的数据类型将由输入数据自动决定。如果指定,数组将被转换为这个数据类型。
  • copy : bool, optional

    • 是否复制输入数据。默认为 True,意味着即使输入数据已经是一个 ndarray,也会创建数据的副本。如果设置为 False,而输入数据已经是一个 ndarray,并且不需要改变数据类型或不要求复制,那么将不会复制数据。
  • order : {'C', 'F', 'A', 'K'}, optional

    • 创建数组的内存布局。'C' 表示按行主序(C风格的数组),'F' 表示按列主序(Fortran风格的数组),'A' 表示任意顺序(实际是 'C' 或 'F' 中的第一个),'K' 表示保持输入数据的顺序。
  • subok : bool, optional

    • 默认为 False,意味着返回的数组将不是 numpy 子类。如果设置为 True,则允许创建 numpy 子类的实例。
  • ndmin : int, optional

    • 要创建的数组的最小维度。默认为 0,这意味着输入数据可以是标量。如果输入数据是标量,将创建一个零维数组。
  • 返回值:

  • 返回一个新的 ndarray 对象。
  • 示例:

import numpy as np

# 从列表创建数组
arr = np.array([1, 2, 3, 4, 5])

# 从元组创建数组
arr_tuple = np.array((1, 2, 3))

# 从另一个数组创建数组
arr_from_arr = np.array(arr)

# 指定数据类型
arr_dtype = np.array([1, 2, 3], dtype=np.float64)

# 指定数组的最小维度
arr_ndmin = np.array(1, ndmin=2)  # 结果是一个 1x1 的数组
  • np.array 是创建 NumPy 数组的基础函数,它非常灵活,可以接受多种类型的输入,并允许在创建时定制数组的多个方面。

 三、NumPy数据类型:

        NumPy 是 Python 中用于科学计算的核心库,它提供了高性能的多维数组对象和一系列用于操作这些数组的工具。NumPy 的数据类型(dtype)非常重要,因为它们决定了数组中元素的存储方式和操作方式。

(1)常用的 NumPy 数据类型:

  • 整数类型:

    • np.int8: 8位整数(-128到127)
    • np.int16: 16位整数(-32768到32767)
    • np.int32: 32位整数(-2^31到2^31-1)
    • np.int64: 64位整数(-2^63到2^63-1)
    • np.uint8: 8位无符号整数(0到255)
    • np.uint16: 16位无符号整数(0到65535)
    • np.uint32: 32位无符号整数(0到2^32-1)
    • np.uint64: 64位无符号整数(0到2^64-1)
  • 浮点数类型:

    • np.float16: 16位半精度浮点数
    • np.float32: 32位单精度浮点数
    • np.float64: 64位双精度浮点数
    • np.float128: 128位扩展精度浮点数(某些系统上可能不可用)
  • 复数类型:

    • np.complex64: 复数,由两个32位浮点数表示实部和虚部
    • np.complex128: 复数,由两个64位浮点数表示实部和虚部
    • np.complex256: 复数,由两个128位浮点数表示实部和虚部(某些系统上可能不可用)
  • 布尔类型:

    • np.bool_: 布尔类型(True或False)
  • 对象类型:

    • np.object: 用于存储任意Python对象
  • 字符串类型:

    • np.string_: 字符串类型
    • np.unicode_: 用于存储Unicode字符串
  • 无符号整数类型:

    • np.ubytenp.ushortnp.uintcnp.ulonglong: 这些类型的大小和范围取决于平台。
  • 时间类型:

    • np.datetime64: 用于存储日期和时间
    • np.timedelta64: 用于存储两个日期或时间之间的差值
  • 结构化数据类型:

    • 可以定义为一系列具有不同数据类型的字段。

(2)代码示例:

import cv2
import numpy as np
# C:\\Users\\86173\\Desktop\\TI\\image\\faves.png

# 整数类型
int8_array = np.array([1, 2, 3], dtype=np.int8)
int16_array = np.array([1, 2, 3], dtype=np.int16)
int32_array = np.array([1, 2, 3], dtype=np.int32)
int64_array = np.array([1, 2, 3], dtype=np.int64)
uint8_array = np.array([1, 2, 3], dtype=np.uint8)
uint16_array = np.array([1, 2, 3], dtype=np.uint16)
uint32_array = np.array([1, 2, 3], dtype=np.uint32)
uint64_array = np.array([1, 2, 3], dtype=np.uint64)

# 浮点数类型
float16_array = np.array([1.0, 2.0, 3.0], dtype=np.float16)
float32_array = np.array([1.0, 2.0, 3.0], dtype=np.float32)
float64_array = np.array([1.0, 2.0, 3.0], dtype=np.float64)
#float128_array = np.array([1.0, 2.0, 3.0], dtype=np.float128)  # 某些系统上可能不可用

# 复数类型
complex64_array = np.array([1+2j, 3+4j], dtype=np.complex64)
complex128_array = np.array([1+2j, 3+4j], dtype=np.complex128)
#complex256_array = np.array([1+2j, 3+4j], dtype=np.complex256)  # 某些系统上可能不可用

# 布尔类型
bool_array = np.array([True, False, True])

# 对象类型
object_array = np.array([1, 'a', 3.14], dtype=object)

# 字符串类型
string_array = np.array(['hello', 'world'], dtype='S5')  # 固定长度字符串
unicode_array = np.array(['你好', '世界'], dtype='U5')  # 固定长度Unicode字符串

# 无符号整数类型
ubyte_array = np.array([1, 2, 3], dtype=np.ubyte)
ushort_array = np.array([1, 2, 3], dtype=np.ushort)
uintc_array = np.array([1, 2, 3], dtype=np.uintc)
ulonglong_array = np.array([1, 2, 3], dtype=np.ulonglong)

# 时间类型
datetime_array = np.array(['2021-01-01', '2021-01-02'], dtype='datetime64[D]')
timedelta_array = np.array([1, 2], dtype='timedelta64[D]')

# 结构化数据类型
dtype = [('field1', 'int32'), ('field2', 'float64')]
structured_array = np.array([(1, 2.0), (3, 4.0)], dtype=dtype)

# 打印数组和它们的数据类型
print("int8_array:", int8_array, "dtype:", int8_array.dtype)
print("float32_array:", float32_array, "dtype:", float32_array.dtype)
print("complex128_array:", complex128_array, "dtype:", complex128_array.dtype)
print("bool_array:", bool_array, "dtype:", bool_array.dtype)
print("object_array:", object_array, "dtype:", object_array.dtype)
print("string_array:", string_array, "dtype:", string_array.dtype)
print("unicode_array:", unicode_array, "dtype:", unicode_array.dtype)
print("datetime_array:", datetime_array, "dtype:", datetime_array.dtype)
print("structured_array:", structured_array, "dtype:", structured_array.dtype)

 (3) np.dtype 类:

        NumPy 还允许用户定义自己的数据类型,这可以通过继承 np.dtype 类或使用 np.dtype 的构造函数来实现。例如,你可以定义一个包含多个字段的数据类型,每个字段都有自己的数据类型。

  • 定义和使用结构化数据类型的例子:
import numpy as np

# 定义一个结构化数据类型
dt = np.dtype([('name', 'S10'), ('height', 'f4'), ('age', 'i4')])

# 创建一个结构化数组
a = np.array([('Alice', 1.65, 25), ('Bob', 1.8, 30)], dtype=dt)

# 访问结构化数组的字段
print(a['name'])  # 输出名字
print(a['height'])  # 输出身高
print(a['age'])  # 输出年龄

(4)内建类型的字符: 

  • 整数类型:

    • 'i1': 8位有符号整数
    • 'i2': 16位有符号整数
    • 'i4': 32位有符号整数
    • 'i8': 64位有符号整数
    • 'u1': 8位无符号整数
    • 'u2': 16位无符号整数
    • 'u4': 32位无符号整数
    • 'u8': 64位无符号整数
  • 浮点数类型:

    • 'f2': 16位半精度浮点数(不常用)
    • 'f4': 32位单精度浮点数
    • 'f8': 64位双精度浮点数
    • 'f16': 128位扩展精度浮点数(某些系统上可能不可用)
  • 复数类型:

    • 'c8': 两个32位单精度浮点数的复数
    • 'c16': 两个64位双精度浮点数的复数
    • 'c32': 两个128位扩展精度浮点数的复数(某些系统上可能不可用)
  • 布尔类型:

    • 'b1': 布尔类型(True 或 False)
  • 对象类型:

    • 'O': 任意 Python 对象
  • 字符串类型:

    • 'S': 固定长度的字节字符串
    • 'U': 固定长度的 Unicode 字符串
  • 日期和时间类型:

    • 'datetime64': 64位日期和时间
    • 'timedelta64': 64位时间差
  • 无符号整数类型:

    • 'uint8': 8位无符号整数
    • 'uint16': 16位无符号整数
    • 'uint32': 32位无符号整数
    • 'uint64': 64位无符号整数
  • 其他类型:

    • 'bytes': 可变长度的字节字符串
    • 'str': 可变长度的 Unicode 字符串

四、数组属性:

        在 NumPy 中,数组对象具有多个属性,这些属性提供了关于数组的有用信息。

 (1)属性介绍:

  • ndarray.ndim:秩,表示数组的维度数(轴的数量)。

  • ndarray.shape:一个表示数组各维度大小的元组。

  • ndarray.size:数组中元素的总数。

  • ndarray.dtype:数组元素的数据类型。

  • ndarray.itemsize:数组中每个元素的字节大小。

  • ndarray.data::包含数组数据的缓冲区。

  • ndarray.strides:一个元组,表示为了跳到下一个元素需要在每个维度上移动的字节数。

  • ndarray.nbytes:数组所占用的总字节数。

  • ndarray.flags:一个包含多个布尔标志的对象,例如 C_CONTIGUOUS(数组在 C 语言风格上是连续的)、F_CONTIGUOUS(数组在 Fortran 风格上是连续的)、OWNDATA(数组拥有自己的数据)等。

  • ndarray.real:如果数组包含复数,则返回实部;否则,返回数组本身。

  • ndarray.imag:如果数组包含复数,则返回虚部;否则,返回一个全为零的数组。

  • ndarray.flat:返回一个迭代器,使得数组可以像一维数组一样迭代。

  • ndarray.T:返回数组的转置。

  • ndarray.ctypes:一个包含用于与 C 语言接口的数据类型的对象。

  • ndarray.base:如果数组是由另一个数组派生(切片或索引)而来,则返回原始数组;否则,返回 None

(2)示例访问属性:

import numpy as np

# 创建一个二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])

# 访问数组属性
print("ndim:", arr.ndim)  # 数组的维度数
print("shape:", arr.shape)  # 数组的形状
print("size:", arr.size)  # 数组中元素的总数
print("dtype:", arr.dtype)  # 数组元素的数据类型
print("itemsize:", arr.itemsize)  # 每个元素的字节大小
print("strides:", arr.strides)  # 每个维度的步长
print("nbytes:", arr.nbytes)  # 数组占用的总字节数
print("C_CONTIGUOUS:", arr.flags['C_CONTIGUOUS'])  # 是否是C风格连续
print("F_CONTIGUOUS:", arr.flags['F_CONTIGUOUS'])  # 是否是Fortran风格连续
print("OWNDATA:", arr.flags['OWNDATA'])  # 是否拥有自己的数据

 

 (3)ndarray对象的内存信息:

        在 NumPy 中,ndarray 对象的内存信息可以通过其 flags 属性来获取,这个属性是一个包含多个布尔值的字典,描述了数组在内存中的存储特性。

  • C_CONTIGUOUS (或 CONTIGUOUS):

    • 如果为 True,则表示数组在内存中是按 C 语言风格的连续存储的,即最后一个维度的元素是最先存储的。
  • F_CONTIGUOUS:

    • 如果为 True,则表示数组在内存中是按 Fortran 语言风格的连续存储的,即第一个维度的元素是最先存储的。
  • OWNDATA:

    • 如果为 True,则表示数组拥有自己的数据副本,即修改数组的数据不会影响原始数据。
  • WRITEABLE:

    • 如果为 True,则表示数组是可写的。
  • ALIGNED:

    • 如果为 True,则表示数组的数据在内存中是对齐的,这有助于提高性能。
  • WRITEBACKIFCOPY:

    • 如果为 True,则表示数组是一个拷贝,其数据最终需要写回到原始数组。

(4)代码示例:

import numpy as np

# 创建一个数组
arr = np.array([[1, 2, 3], [4, 5, 6]])

# 打印内存相关的属性
print("Array data type:", arr.dtype)
print("Array itemsize:", arr.itemsize)
print("Array size:", arr.size)
print("Array nbytes:", arr.nbytes)
print("Array is C contiguous:", arr.flags['C_CONTIGUOUS'])
print("Array is F contiguous:", arr.flags['F_CONTIGUOUS'])
print("Array owns its data:", arr.flags['OWNDATA'])
print("Array is writeable:", arr.flags['WRITEABLE'])
print("Array is aligned:", arr.flags['ALIGNED'])

五、新建数组:

在 NumPy 中,可以使用多种方法来创建新的数组。

(1)使用 np.array:

  • 将列表或其他序列转换为 NumPy 数组。
import numpy as np

# 从列表创建数组
arr = np.array([1, 2, 3, 4, 5])

(2)使用 np.zeros:

  • 创建一个由 0 组成的数组。
# 创建一个形状为 (3, 4) 的数组,所有元素都是 0
zeros_arr = np.zeros((3, 4))

(3)使用 np.ones:

  • 创建一个由 1 组成的数组。
# 创建一个形状为 (2, 2) 的数组,所有元素都是 1
ones_arr = np.ones((2, 2))

(4)使用 np.full:

  • 创建一个由指定填充值组成的数组。
# 创建一个形状为 (3, 3) 的数组,所有元素都是 7
full_arr = np.full((3, 3), 7)

(5)使用 np.arange:

  • 创建一个具有等间隔序列的一维数组。
# 创建一个从 0 到 9 的数组,步长为 1
arange_arr = np.arange(10)

(6)使用 np.linspace:

  • 创建一个在指定范围内具有等间隔的一维数组。
# 创建一个从 0 到 1 的 5 个元素的数组
linspace_arr = np.linspace(0, 1, 5)

(7)使用 np.eye:

  • 创建一个二维的单位矩阵(对角线上的元素为 1,其余为 0)。
# 创建一个 3x3 的单位矩阵
eye_arr = np.eye(3)

(8)使用 np.diag:

  • 创建一个以提供的一维数组为对角线元素的二维数组。
# 创建一个对角线上元素为 1 的 3x3 对角矩阵
diag_arr = np.diag([1, 2, 3])

(9)使用 np.random 模块:

  • 创建一个由随机数组成的数组。
# 创建一个形状为 (2, 3) 的随机数组
random_arr = np.random.rand(2, 3)

(10)使用 np.empty:

  • 创建一个未初始化的数组(其值是内存中当前的垃圾值)。
# 创建一个形状为 (2, 2) 的未初始化数组
empty_arr = np.empty((2, 2))
  • (11)使用 np.stacknp.concatenatenp.vstacknp.hstack:

    • 将多个数组堆叠或连接成一个新数组。
# 创建两个数组
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 垂直堆叠
vstack_arr = np.vstack((a, b))

# 水平堆叠
hstack_arr = np.hstack((a, b))

 六、从已有的数组创建数组:

 (1)np.asarray:

    np.asarray 是 NumPy 中的一个函数,它将输入的对象转换为 NumPy 数组。如果输入对象已经是一个 NumPy 数组,那么 np.asarray 会返回该数组的一个引用(除非 dtype 参数指定了不同的数据类型)。这个函数对于确保你拥有一个 NumPy 数组非常有用,尤其是在不确定输入数据类型的情况下。

a.函数原型:

numpy.asarray(a, dtype=None, order=None, device=None)

b.参数:

  • a : array_like

    • 输入的数据,可以是列表、元组、另一个 NumPy 数组,或者是任何其他形式的序列。
  • dtype : data-type, optional

    • 目标数组的数据类型。如果指定,数组的元素将被转换为该数据类型。
  • order : {'C', 'F'}, optional

    • 创建数组的内存布局。'C' 表示 C 风格的行主序(默认),'F' 表示 Fortran 风格的列主序。
  • device : {'cpu', 'cuda'}, optional

    • 指定数组应该在哪个设备上分配。默认为 'cpu'

c.返回:

  • 一个 NumPy 数组。

d.用法示例:

import numpy as np

# 从列表创建 NumPy 数组
list_data = [1, 2, 3]
array = np.asarray(list_data)
print(array)  # 输出: [1 2 3]

# 转换数据类型
array = np.asarray(list_data, dtype=float)
print(array)  # 输出: [1. 2. 3.]

# 保持原数组的顺序
array = np.asarray([[1, 2, 3], [4, 5, 6]], order='F')
print(array)  # 输出: [[1 2 3] [4 5 6]]

# 从另一个 NumPy 数组创建数组
existing_array = np.array([1, 2, 3])
new_array = np.asarray(existing_array)
print(new_array is existing_array)  # 输出: True,表明 new_array 是 existing_array 的引用

(2)np.frombuffer :

   np.frombuffer 是 NumPy 中的一个函数,它用于从缓冲区(如字节字符串或内存区域)创建一个一维数组。这个函数对于直接从内存中的数据创建数组非常有用,尤其是在处理二进制数据或与低级程序接口时。

a.函数原型:

numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)

b.参数:

  • buffer : buffer_like

    • 一个缓冲区对象,如 bytes 或 bytearray。
  • dtype : data-type, optional

    • 数组元素的数据类型。如果不指定,将自动推断数据类型。
  • count : int, optional

    • 要读取的元素数量。如果为 -1(默认),则读取整个缓冲区。
  • offset : int, optional

    • 缓冲区开始读取前的字节偏移量。

c.返回:

  • 一个一维 NumPy 数组。

d.用法示例:

import numpy as np

# 创建一个字节字符串
buffer = b'\x01\x02\x03\x04\x05\x06\x07\x08'

# 从缓冲区创建数组
array = np.frombuffer(buffer, dtype=np.uint8)
print(array)  # 输出: [ 1  2  3  4  5  6  7  8]

# 指定 count 参数
array = np.frombuffer(buffer, dtype=np.uint8, count=4)
print(array)  # 输出: [1 2 3 4]

# 指定 offset 参数
array = np.frombuffer(buffer, dtype=np.uint8, count=4, offset=2)
print(array)  # 输出: [3 4 5 6]
  • 创建了一个包含 8 个字节的字节字符串。然后,使用 np.frombuffer 从这个缓冲区创建了一个一维数组。使用 countoffset 参数来控制从缓冲区中读取的数据。
  • np.frombuffer 特别适用于处理二进制文件或网络数据流,因为它允许直接将原始字节数据转换为 NumPy 数组,从而进行进一步的数值处理。

 (3)np.fromiter

    np.fromiter 是 NumPy 中的一个函数,它用于从一个迭代器创建一个数组。这个函数对于从任何可迭代对象(如生成器、迭代器或其他序列)创建数组非常有用,特别是当需要将大量数据有效地转换为 NumPy 数组时。

a.函数原型:

numpy.fromiter(iterable, dtype, count=-1)

b.参数:

  • iterable : iterable

    • 一个迭代器或可迭代对象,其元素将被用来创建数组。
  • dtype : data-type

    • 数组元素的数据类型。
  • count : int, optional

    • 要读取的元素数量。如果为 -1(默认),则读取迭代器中的所有元素。

c.返回:

  • 一个一维 NumPy 数组。

d.用法示例:

import numpy as np

# 创建一个迭代器
iterable = (i * i for i in range(5))

# 从迭代器创建数组
array = np.fromiter(iterable, dtype=int)
print(array)  # 输出: [ 0  1  4  9 16]

# 使用 count 参数
array = np.fromiter(iterable, dtype=int, count=3)
print(array)  # 输出: [ 0  1  4]
  • 创建了一个生成器表达式,它生成一个数字的平方。然后,使用 np.fromiter 从这个迭代器创建了一个一维数组。使用 count 参数来控制从迭代器中读取的数据数量。
  • np.fromiter 是一个非常灵活的函数,它可以处理任何类型的迭代器,包括那些在迭代过程中动态生成数据的迭代器。这使得它成为处理流式数据或大型数据集时的一个强大工具。

七、从数值范围创建数组: 

在 NumPy 中,从数值范围创建数组通常涉及到生成一系列连续的数值

(1)np.arange:

  • 创建一个等差数列的一维数组。

(2)np.linspace:

  • 创建一个在指定范围内均匀分布的一维数组。
  • 参数:
    • start: 范围的起始值。
    • stop: 范围的终止值。
    • num: 要生成的等间隔样本数量。
    • endpoint: 布尔值,确定是否包括终止值(默认为 True)。
    • dtype: 数组的数据类型(可选)。
  • 用法:
    array = np.linspace(0, 1, 5)  # 从 0 到 1 生成 5 个数字
    print(array)  # 输出: [0.  0.25 0.5  0.75 1. ]

(3)np.logspace:

  • 创建一个对数等比数列的一维数组。
  • 参数:
    • start: 对数尺度的起始值的指数。
    • stop: 对数尺度的终止值的指数。
    • num: 要生成的等间隔样本数量。
    • endpoint: 布尔值,确定是否包括终止值(默认为 True)。
    • base: 对数的底数(默认为 10)。
    • dtype: 数组的数据类型(可选)。
  • 用法:
    array = np.logspace(1, 2, 5)  # 从 10^1 到 10^2 生成 5 个数字
    print(array)  # 输出: [ 10.  17.78  31.62  56.23 100.  ]

(4)np.fromfunction:

  • 从一个函数生成数组,该函数定义了数组中的元素值。
  • 参数:
    • function: 一个返回数组元素值的函数。
    • shape: 生成数组的形状。
    • dtype: 数组的数据类型(可选)。
  • 用法:
    def func(x, y):
        return x + y
    
    array = np.fromfunction(func, (3, 3), dtype=int)
    print(array)  # 输出: [[0 1 2] [1 2 3] [2 3 4]]

(5)np.tile:

  • 重复数组中的元素以创建更大的数组。
  • 参数:
    • a: 要重复的数组。
    • reps: 重复次数,可以是一个整数或形状为元组的数组。
  • 用法:
    array = np.array([1, 2, 3])
    repeated_array = np.tile(array, (2, 3))  # 重复 2 行 3 列
    print(repeated_array)
    # 输出:
    # [[1 2 3 1 2 3]
    #  [1 2 3 1 2 3]]

(6)np.repeat:

  • 重复数组中的每个元素多次。
  • 参数:
    • a: 要重复的数组。
    • repeats: 每个元素重复的次数,可以是一个整数或数组。
  • 用法:
    array = np.array([1, 2, 3])
    repeated_elements = np.repeat(array, 2)  # 每个元素重复 2 次
    print(repeated_elements)  # 输出: [1 1 2 2 3 3]

 八、切片和索引:

在 NumPy 中,切片和索引是访问和操作数组元素的基本方法。

(1)索引:

索引用于访问数组中的单个元素。在 NumPy 中,多维数组的索引是按行优先顺序进行的。

import numpy as np

# 创建一个二维数组
arr = np.array([[1, 2, 3], [4, 5, 6]])

# 访问第二行第一列的元素
element = arr[1, 0]  # 输出 4

(2)切片:

切片用于访问数组的一部分,即子数组。切片操作返回原数组的视图,而不是副本。

# 创建一个一维数组
arr = np.arange(10)

# 访问从第三个元素到第六个元素(不包括索引 6)
slice = arr[2:6]  # 输出 [3 4 5]

(4)切片语法:

  • 一维数组的切片:arr[start:stop:step]
  • 多维数组的切片:arr[x_start:x_stop:x_step, y_start:y_stop:y_step]

(5)省略和默认值:

  • 省略 start:默认从序列的开始位置取。
  • 省略 stop:默认取到序列的结束位置。
  • 省略 step:默认步长为 1。
# 访问从开始到索引 5 的所有元素
slice = arr[:5]  # 输出 [0 1 2 3 4]

# 访问从索引 5 到结束的所有元素
slice = arr[5:]  # 输出 [5 6 7 8 9]

# 访问整个数组
slice = arr[:]  # 输出 [0 1 2 3 4 5 6 7 8 9]

(6)负索引:

  • 负索引用于从数组的末尾开始计数。
# 访问最后一个元素
element = arr[-1]  # 输出 9

# 访问最后三个元素
slice = arr[-3:]  # 输出 [7 8 9]

(7)花式索引:

  • 花式索引允许通过提供一个索引数组来访问多个元素。
# 创建一个索引数组
indexes = np.array([0, 2, 4])

# 使用花式索引
fancy_slice = arr[indexes]  # 输出 [0 2 4 6 8]

(8)布尔索引:

  • 布尔索引允许基于条件表达式来索引数组。
# 选择所有大于 5 的元素
bool_index = arr[arr > 5]  # 输出 [6 7 8 9]

(9)切片与复制:

  • 使用切片时,返回的是原数组的视图,而不是副本。如果你需要修改切片内容而不影响原数组,可以使用 .copy() 方法创建副本。
# 创建一个副本
slice_copy = arr[2:6].copy()

(10)多维数组切片:

  • 在多维数组中,你可以通过为每个维度提供切片索引来获取子数组。
# 创建一个二维数组
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 获取第二行
row = arr_2d[1, :]  # 输出 [4 5 6]

# 获取第一列
column = arr_2d[:, 0]  # 输出 [1 4 7]

# 获取中间的子数组
sub_array = arr_2d[1:3, 1:3]  # 输出 [[5 6] [8 9]]

 九、迭代数组:

        在 NumPy 中,迭代数组通常指的是遍历数组中的元素或子数组。NumPy 提供了几种方法来迭代数组,包括使用 Python 的标准循环结构或 NumPy 的特定函数。以下是一些常用的迭代方法:

(1) 使用 Python 的 for 循环:

最直接的方法是使用 Python 的内置 for 循环直接迭代 NumPy 数组的元素。

import numpy as np

arr = np.array([1, 2, 3, 4, 5])

for element in arr:
    print(element)
  • 这种方法简单直观,适用于一维数组。对于多维数组,你可以通过嵌套循环来迭代。

(2)使用 np.nditer:

np.nditer 是一个更高级的迭代器,它支持多维数组和更复杂的迭代需求,如 C 或 Fortran 样式的迭代。

arr = np.array([[1, 2], [3, 4]])

for element in np.nditer(arr):
    print(element)
  • np.nditer 可以配置多个选项,例如避免复制、多数组迭代等。

(3)使用 np.flat 或 np.ravel:

  • 这两个方法返回数组的一维迭代器,允许以一维的方式迭代多维数组。
arr = np.array([[1, 2], [3, 4]])

# 使用 np.flat
for element in np.flatiter(arr):
    print(element)

# 使用 np.ravel 返回的数组迭代
for element in np.ravel(arr):
    print(element)

(4) 使用 np.ndenumerate:

  • 如果需要在迭代时同时获取索引,np.ndenumerate 是一个非常有用的工具。它返回数组的索引和值。
arr = np.array([[1, 2], [3, 4]])

for index, element in np.ndenumerate(arr):
    print(f"Index: {index}, Value: {element}")

(5)使用条件迭代:

有时你可能需要根据条件迭代数组中的元素。这可以通过结合条件语句和迭代方法来实现。

arr = np.array([1, 2, 3, 4, 5])

for element in arr:
    if element % 2 == 0:
        print(f"Even number: {element}")

(6)使用生成器表达式:

虽然这不是直接迭代数组的方法,但生成器表达式可以用来创建一个迭代器,这在处理大型数组时可以节省内存。

arr = np.array([1, 2, 3, 4, 5])

# 创建一个生成器表达式
gen = (x * 2 for x in arr)

# 迭代生成器
for element in gen:
    print(element)

 (7)np.nditer详细介绍:

   np.nditer 是 NumPy 提供的一个强大的多维数组迭代器对象,它提供了多种灵活的方法来访问一个或多个数组的所有元素。

a.函数原型:

numpy.nditer(op, flags=None, op_flags=None, 
op_dtypes=None, order='K', casting='safe', 
op_axes=None, itershape=None, buffersize=0)

b.参数:

  • op : 对象序列

    • 要迭代的对象序列,通常是 NumPy 数组。
  • flags : {'buffered', 'delay_bufalloc', 'external_loop', 'f_index', 'multi_index', 'c_index', 'refs_ok', 'zerosize_ok', 'copy_if_overlap', 'no_broadcast', 'no_subtype', 'remove_axis', 'writemasked', 'readwrite'}, optional

    • 控制迭代器行为的标志列表。
  • op_flags : 列表或对象序列,可选

    • 每个操作数的额外行为标志列表。
  • op_dtypes : 数据类型或数据类型序列,可选

    • 操作数期望的数据类型。
  • order : {'C', 'F', 'A', 'K'}, optional

    • 内存布局顺序:'C' 表示行主序(行优先),'F' 表示列主序(列优先),'A' 表示任意顺序(实际顺序),'K' 表示保持数组的原始顺序。
  • casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional

    • 类型转换规则。
  • op_axes : 列表或轴序列,可选

    • 每个操作数的轴到迭代器轴的映射。
  • itershape : 元组,可选

    • 迭代器的期望输出形状。
  • buffersize : 整数,可选

    • 当使用 'buffered' 标志时,控制缓冲区的大小。

c.返回:

  • 返回一个 nditer 对象,可以通过它迭代数组。

d.基本用法:

  • np.nditer 可以迭代单个或多个数组,提供对数组元素的访问。例如:
a = np.arange(6).reshape(2, 3)
for x in np.nditer(a):
    print(x, end=' ')

e.控制迭代顺序:

  • 可以通过 order 参数控制迭代的顺序,如 'C'(行序优先,默认)或 'F'(列序优先):
for x in np.nditer(a, order='F'):
    print(x, end=' ')

f.修改数组中的元素:

  • 使用 op_flags 参数可以修改数组中的元素,例如使用 'readwrite' 标志:
for x in np.nditer(a, op_flags=['readwrite']):
    x[...] = x * 2

g.外部循环:

  • 使用 flags 参数中的 'external_loop' 可以实现逐行或逐列的迭代:
for x in np.nditer(a, flags=['external_loop'], order='F'):
    print(x, end=' ')

h.广播迭代

  • np.nditer 支持广播机制,可以同时迭代多个可广播的数组:
b = np.array([1, 2, 3, 4])
for x, y in np.nditer([a, b]):
    print("%d:%d" % (x, y), end=", ")

(8)注意事项:

  • nditer 可以作为上下文管理器使用,确保在迭代完成后正确处理数据。
  • 如果使用 'writeonly' 或 'readwrite' 标志,操作数可能是原始数据的视图,需要特别注意数据的回写。
  • 迭代 NumPy 数组时,尽量避免修改迭代的数组,因为这可能会导致不可预测的结果。
  • 对于大型数组,考虑迭代效率和内存使用。

十、数组操作:

        在 NumPy 中,数组的形状、维度和元素可以进行多种操作。

(1) 修改数组形状:

np.reshape:
  • 函数原型: numpy.reshape(a, newshape, order='C')
  • 参数:
    • a: 输入数组。
    • newshape: 元组,新的数组形状。
    • order: {'C', 'F', 'A'},数组的内存顺序。
  • 作用: 返回一个具有新形状的数组,不改变数据。
import numpy as np
a = np.arange(6)
b = np.reshape(a, (2, 3))
print(b)
# 输出:
# [[0 1 2]
#  [3 4 5]]
numpy.ndarray.flat:
  • numpy.ndarray.flat 是 NumPy 中的一个属性,它返回一个迭代器,使得数组可以像一维数组一样迭代。这个迭代器允许访问数组中的每个元素,就好像它们在一维数组中一样。
  • 函数原型:
numpy.ndarray.flat
  • 参数:无参数。
  • 作用:返回一个迭代器,用于迭代多维数组中的所有元素,就好像它们在一维数组中一样。

  • 代码示例:

import numpy as np

# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])

# 使用 flat 迭代器
for element in a.flat:
    print(element, end=' ')
# 输出: 1 2 3 4 5 6

a.flat 返回的迭代器允许你对数组 a 进行迭代,而不需要关心它的维度。这在处理任意维度的数组时非常有用,因为你可以使用相同的迭代代码。

注意事项:

  • a.flat 返回的迭代器不支持索引操作,它只能用于迭代。
  • 如果你需要修改数组中的元素,可以使用 a.flat 迭代器,但更常见的做法是使用索引或者切片。
 numpy.ndarray.flatten:
  • numpy.ndarray.flatten 是一个方法,它返回一个折叠成一维的数组副本。这个方法对于将多维数组转换为一维数组非常有用,尤其是在你需要对数组元素进行顺序处理时。
  • 函数原型:

numpy.ndarray.flatten([order])
  • 参数:

  • order : {'C', 'F', 'A', 'K'}, optional
    • 'C' 表示返回的是类似 C 语言的行主序数组(默认)。
    • 'F' 表示返回的是类似 Fortran 语言的列主序数组。
    • 'A' 表示返回的是数组的任意顺序,与原数组的顺序相同。
    • 'K' 表示返回的是原数组的顺序。
  • 作用:返回一个折叠成一维的数组副本。

  • 代码示例:

import numpy as np

# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])

# 使用 flatten 方法
flattened_array = a.flatten()
print(flattened_array)
# 输出: [1 2 3 4 5 6]

注意事项:

  • flatten() 返回的是原数组的一个副本,对返回的数组进行修改不会影响原数组。
  • 如果需要一个不复制数据的迭代器,可以使用 .flat 属性,它返回一个迭代器,可以在不创建副本的情况下迭代数组中的每个元素。
numpy.ravel: 
  • numpy.ravel 函数是 NumPy 中用于将多维数组扁平化为一维数组的函数。与 flatten() 方法不同,ravel() 默认返回的是原数组的视图(view),而不是副本(copy)。如果可能,它不会复制数据,这意味着对返回数组的修改将影响原始数组。如果需要确保返回一个副本,可以设置 copy=True
  • 函数原型:
numpy.ravel(a, order='C')
  • 参数:
  • a : array_like

    • 输入的多维数组。
  • order : {'C', 'F', 'A'}, optional

    • 'C' 表示按行主序(默认)。
    • 'F' 表示按列主序。
    • 'A' 表示保持数组原来的顺序(只有当输入是数组时才有意义)。
  • 作用:返回一个一维数组,该数组是原始多维数组的扁平化版本。
  • 代码示例:

import numpy as np

# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])

# 使用 ravel 函数
flattened_array = np.ravel(a)
print(flattened_array)
# 输出: [1 2 3 4 5 6]

# 如果需要确保返回一个副本,可以设置 copy=True
flattened_array_copy = np.ravel(a, copy=True)

注意事项:

  • 当 order='C' 时,数组将按行主序扁平化,这意味着第一维度的元素会先被迭代。
  • 当 order='F' 时,数组将按列主序扁平化,这意味着最后一维度的元素会先被迭代。
  • 如果原始数组已经是一维的,ravel() 将返回原始数组本身(除非指定 copy=True)。
  • ravel() 通常比 flatten() 更有效率,因为它避免了不必要的数组复制。

(2)翻转数组:

np.flip:
  • 函数原型: numpy.flip(a, axis=None)
  • 参数:
    • a: 输入数组。
    • axis: 整数或整数数组,指定要翻转的轴。
  • 作用: 反转数组中的元素顺序。
a = np.arange(6)
b = np.flip(a)
print(b)
# 输出: [5 4 3 2 1 0]
numpy.transpose
  • numpy.transpose 函数是 NumPy 中用于交换数组轴的函数。这个函数可以重新排列多维数组的维度,使得可以轻松地从一个维度顺序转换到另一个维度顺序。
  • 函数原型:

numpy.transpose(a, axes=None)
  • 参数:

  • a : array_like

    • 输入的多维数组。
  • axes : tuple of ints, optional

    • 一个包含轴索引的元组,用于指定新的轴顺序。如果不提供,轴将被逆序排列。
  • 作用:返回一个新的数组,其轴顺序被重新排列。

  • 代码示例:

import numpy as np

# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])

# 使用 transpose 函数
transposed_array = np.transpose(a)
print(transposed_array)
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]

# 指定新的轴顺序
transposed_array_custom = np.transpose(a, axes=(1, 0))
print(transposed_array_custom)
# 输出:
# [[1 2 3]
#  [4 5 6]]

注意事项:

  • transpose 函数返回的是原数组的一个视图(view),除非指定了新的轴顺序,这种情况下它将返回一个副本。
  • 如果你只需要简单地反转数组的轴,可以使用 a.T,这是 transpose 的简写形式。
  • transpose 函数不会改变原始数组的数据,它只是重新排列了轴。
 numpy.rollaxis:
  • numpy.rollaxis 函数是 NumPy 中用于将数组中的轴滚动到指定位置的函数。这个函数可以用来改变数组的维度顺序,但不改变数组中元素的顺序。
  • 函数原型:

numpy.rollaxis(a, axis, start=0)
  • 参数:

  • a : ndarray

    • 输入的多维数组。
  • axis : int

    • 要滚动的轴的索引。
  • start : int, optional

    • 滚动的起始位置。默认为 0,表示将轴滚动到最前面。
  • 作用:将数组中的指定轴滚动到新的位置。

  • 代码示例:
import numpy as np

# 创建一个三维数组
a = np.array([[[ 0, 1], [ 2, 3]],
              [[ 4, 5], [ 6, 7]]])

# 将第一个轴滚动到最前面
rolled_array = np.rollaxis(a, 0, start=0)
print(rolled_array)
# 输出:
# [[[0 1]
#   [2 3]]
# 
#  [[4 5]
#   [6 7]]]

# 将第二个轴滚动到最后面
rolled_array = np.rollaxis(a, 1, start=2)
print(rolled_array)
# 输出:
# [[[0 2]
#   [1 3]]
# 
#  [[4 6]
#   [5 7]]]

注意事项:

  • rollaxis 函数返回的是原数组的一个视图(view),除非滚动操作涉及到数组的物理布局改变,这种情况下它将返回一个副本。
  • rollaxis 函数不会改变原始数组的数据,它只是改变了轴的顺序。
  • 如果 start 参数大于数组的维度数,轴将被滚动到数组的末尾。
numpy.swapaxes
  • numpy.swapaxes 函数是 NumPy 中用于交换数组的两个轴的函数。这个函数可以方便地改变数组的维度顺序。
  • 函数原型:

numpy.swapaxes(a, axis1, axis2)
  • 参数:

  • a : ndarray

    • 输入的多维数组。
  • axis1 : int

    • 第一个轴的索引。
  • axis2 : int

    • 第二个轴的索引。
  • 作用:返回一个新的数组,其中 axis1 和 axis2 被交换。

  • 代码示例:

import numpy as np

# 创建一个二维数组
a = np.array([[1, 2, 3], [4, 5, 6]])

# 交换数组的轴
swapped_array = np.swapaxes(a, 0, 1)
print(swapped_array)
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]

# 对于三维数组,交换前两个轴
a = np.array([[[ 0, 1], [ 2, 3]],
              [[ 4, 5], [ 6, 7]]])
swapped_array = np.swapaxes(a, 0, 1)
print(swapped_array)
# 输出:
# [[[0 4]
#   [2 6]]
# 
#  [[1 5]
#   [3 7]]]

注意事项:

  • swapaxes 函数返回的是原数组的一个视图(view),如果轴交换不涉及数据的物理重新排列,就不会创建数据的副本。
  • 交换轴的索引是从 0 开始的,例如,在二维数组中,0 代表行(第一个轴),1 代表列(第二个轴)。
  • 这个函数不会改变原始数组的数据,它只是返回一个新的视图,其中轴的顺序被交换。

(3)修改数组维度:

np.expand_dims:
  • 函数原型: numpy.expand_dims(a, axis)
  • 参数:
    • a: 输入数组。
    • axis: 要插入的新轴的索引。
  • 作用: 在指定轴位置插入一个新的轴。
a = np.arange(3)
b = np.expand_dims(a, axis=1)
print(b)
# 输出:
# [[0]
#  [1]
#  [2]]

(4)分割数组:

np.split:
  • 函数原型: numpy.split(ary, indices_or_sections, axis=0)
  • 参数:
    • ary: 输入数组。
    • indices_or_sections: 分割的索引或部分。
    • axis: 分割的轴。
  • 作用: 将数组分割成多个子数组。
a = np.arange(6)
b = np.split(a, 3)
print(b)
# 输出: [array([0, 1]), array([2, 3]), array([4, 5])]

(5) 数组元素的添加和修改:

np.append:
  • 函数原型: numpy.append(a, values, axis=None)
  • 参数:
    • a: 输入数组。
    • values: 要添加的值。
    • axis: 要添加值的轴。
  • 作用: 沿指定轴添加元素。
a = np.array([1, 2, 3])
b = np.append(a, [4, 5])
print(b)
# 输出: [1 2 3 4 5]
np.insert:
  • 函数原型: numpy.insert(ary, obj, values, axis=None)
  • 参数:
    • ary: 输入数组。
    • obj: 插入位置的索引。
    • values: 要插入的值。
    • axis: 要插入值的轴。
  • 作用: 在指定位置插入元素。
a = np.array([1, 2, 3])
b = np.insert(a, 1, 5)
print(b)
# 输出: [1 5 2 3]

十一、数组创建图像:

import cv2
import numpy as np

# 创建一个 100x100 的全黑图像
black_image = np.zeros((300, 300), dtype=np.uint8)

# 创建一个 100x100 的全白图像
white_image = np.ones((300, 300), dtype=np.uint8) * 255

# 显示图像
cv2.imshow('Black Image', black_image)
cv2.imshow('White Image', white_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

  • 36
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值