opencv提供相当丰富的函数功能。python的numpy库与C++的Eigen库兼容其图像矩阵格式。多数操作可在两者之间互相切换。
opencv提供很多矩阵操作如cv2.add()
,但我认为不如使用numpy库的矩阵运算,已经对运算做重载操作,如mat = img1 + img2
,速度快于opencv。
这里补一下常用numpy函数。我自己认为的,如果有其他的,可以在评论留言,我看时间添加。参考numpy官方文档。
- 矩阵变形
- 可代替
numpy.ravel()
,numpy.squeeze()
,numpy.flatten()
,不改变元素个数下对矩阵或向量变形。a = numpy.arange(6).reshape((3, 2)) a array([[0, 1], [2, 3], [4, 5]])
- 矩阵切片
- 取出子向量或者子矩阵,相当常用。如目标识别,语义分割。
x = numpy.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) x[1:7:2] #Out: #array([1, 3, 5]) x[-2:10] array([8, 9]) x[-3:3:-1] #Out: #array([7, 6, 5, 4])
- 矩阵拼接
- 常用于对数据做批处理。例如,将多个数据拼接,1维信号变为2维矩阵通过分类器。多张图片叠为3维tensor,通过深度网络。具体查阅批处理操作。
numpy.concatenate((a1, a2, ...), axis=0, out=None, dtype=None, casting="same_kind")
- (a1, a2, …): 待拼接矩阵或向量元组。
- axis: 选中希望拼接的维度,默认为0。
元组中矩阵的其他维度必须一致,不然返回维度不一致- 其他为可选项,不多做介绍,至少我不用。
- 当 axis为 0,1,2时,分别对应
numpy.hstack()
,numpy.vstack()
,numpy.dstack()
。a0 = numpy.linspace(1,10,10).reshape(2,5) a1 = numpy.linspace(1,15,15).reshape(3,5) a2 = numpy.concatenate((a0,a1),axis=0) #Out: #array([[ 1., 2., 3., 4., 5.], # [ 6., 7., 8., 9., 10.], # [ 1., 2., 3., 4., 5.], # [ 6., 7., 8., 9., 10.], # [11., 12., 13., 14., 15.]]) a2 = numpy.concatenate((a0,a1),axis=1) # ValueError: all the inumpyut array dimensions for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 2 and the array at index 1 has size 3
- 矩阵分割
- 常用于获取批处理结果。
numpy.split(array, indices_or_sections, axis=0)
- array: 待分割矩阵或向量
- indices_or_sections: 整数N或者1维向量
若为整数N,尝试返回N等分矩阵,若不能,则产生error
若为1维向量。根据向量元素,在axis(默认为0)上,按照索引分割array- axis: 选中希望分割的维度,默认为0。
- 当 axis为 0,1,2时,分别对应
numpy.hsplit()
,numpy.vsplit()
,numpy.dsplit()
。numpy.matlib.eye(3, k=1, dtype=float) # matrix([[0., 1., 0.], # [0., 0., 1.], # [0., 0., 0.]])
- 矩阵轴转置
- 常用于通道变换,如bgr到rgb,图片数据集(H,W,C,batch)位置变换
numpy.transpose(array, axes=None)
- array: 带变换向量或矩阵
- axes: 元组 , 新的轴顺序
x = numpy.ones((1, 2, 3)) numpy.transpose(x, (1, 0, 2)).shape # (2, 1, 3)
主要有1维:numpy.array
,2维:numpy.matrix
,n维:numpy.ndarray
- 创建新矩阵
numpy.array()
用给定元素创建新的矩阵和向量
- 以特定值创建矩阵
- 一般使用
numpy.ones()
乘以特定值来创建新矩阵
- 随机初始化矩阵
numpy.random
模块提供多种随机初始化的方法,有依据统计学分布来生成矩阵。
随机采样模块名 分布 numpy.random.rand() 生成均匀分布的随机小数。 numpy.random.uniform() 生成[a, b)的均匀分布 numpy.random.random() 与numpy.random.rand() 基本一致,生成均匀分布的随机小数。 numpy.random.randint() 返回均匀分布的随机整数。 numpy.random.randn() 返回一个或一组样本,具有标准正态分布。标准正态分布是以0为均值、以1为标准差的正态分布,记为N(0,1)。 numpy.random.binomial() 二项分布(伯努利分布)硬币问题 numpy.random.exponential() 指数分布 (出现次数的时间分布) numpy.random.normal() 正态分布(常用数据分布) numpy.random.poisson 柏松分布 (出现次数,到达强度))
- 对角阵初始化
- 该方法常用于初始化协方差矩阵。
numpy.matlib.eye(m,n,k)
ornumpy.eye(M, N=None, k=0, dtype=
, order='C')
- m: 选定矩阵行数为m
- n: 可选 选定矩阵列数为n,默认等同于行数
- k: 对角偏移量。0为对角线 ,k>0为向上偏移量,<0 相反。
numpy.matlib.eye(3, k=1, dtype=float) # matrix([[0., 1., 0.], # [0., 0., 1.], # [0., 0., 0.]])
- 重复子矩阵
numpy.matlib.repmat(array,m,n)
- array: 需要复制的矩阵,矩阵维度dim≤2
- m: 沿行方向复制m次
- n: 沿列方向复制n次
a = numpy.arange(4) numpy.matlib.repmat(a, 2, 2) #array([[0, 1, 2, 3, 0, 1, 2, 3], # [0, 1, 2, 3, 0, 1, 2, 3]])
- 条件过滤
- 很重要!只要希望过滤掉异常值,这个函数就很有用。在立体视觉中,opencv的双目立体视觉空洞区域会计算出
nan
值。使用这个函数可以轻松设置最大深度以及最小深度阈值
numpy.where(condition[, x, y])
# 1-d numpy.where 等价于下面 [xv if c else yv for c, xv, yv in zip(condition, x, y)] a = np.array([[0, 1, 2], [0, 2, 4], [0, 3, 6]]) np.where(a < 4, a, -1) # array([[ 0, 1, 2], # [ 0, 2, -1], # [ 0, 3, -1]])
- 最大\最小搜索
- 常用于深度学习最后一层选取最大概率为输出结果。
numpy.argmax(array,axis=None)
- array : 输入向量
- axis: 按照指定轴方向返回索引,默认为向量铺平返回索引。
a = np.arange(6).reshape(2,3) + 10 a # array([[10, 11, 12], # [13, 14, 15]]) np.argmax(a) #5 np.argmax(a, axis=0) # array([1, 1, 1]) np.argmax(a, axis=1) # array([2, 2])
这里是经常容易搞混的地方。numpy里
*
代表两向量对应元素相乘,@
代表矩阵乘.维度>2时,容易出错,请小心使用。
- 矩阵求逆
- 适用于维度为 R N ∗ N R^{N*N} RN∗N的方阵或至少两个维度大小一致,返回的矩阵维度为 R N ∗ N R^{N*N} RN∗N,且两矩阵点积为单位对角阵。该函数计算array 逆矩阵。返回
ainv
满足dot(a, ainv) = dot(ainv, a) = eye(a.shape[0])
.
numpy.linalg.inv(array)
- array: 待求解矩阵。
- 矩阵求伪逆
- 适用于维度为 R M ∗ N R^{M*N} RM∗N的矩阵,返回的矩阵维度为 R N ∗ M R^{N*M} RN∗M。具体分析可查看矩阵论或者矩阵分析。
numpy.linalg.pinv(array)
- array: 待求解矩阵。
- 奇异值分解
- 返回 三个向量 U, sigma, V。U,V 为酉阵,sigma为特征值。 这里注意sigma为
numpy.array
,实际使用需要nunmpy.linag.diag(sigma)
转换为对角矩阵。
U ∗ Σ − 1 ∗ V T U*\Sigma^{-1}*V^T U∗Σ−1∗VT等价于伪逆numpy.pinv
。In [1]: A = np.linspace(1,10,9).reshape(3,3) In [2]: A Out[2]: array([[ 1. , 2.125, 3.25 ], [ 4.375, 5.5 , 6.625], [ 7.75 , 8.875, 10. ]]) In [3]: Sinv = np.pad(np.linalg.inv(np.diag(sigma)),((0,0),(0,2)),constant_values =0) In [4]: Ainv = np.linalg.pinv(A) In [5]: np.allclose(V.T@Sinv@U.T,Ainv) Out[5]: True In [6]: Ainv@A Out[6]: array([[ 1.00000000e+00, 2.22044605e-16], [-1.99840144e-15, 1.00000000e+00]])
numpy.allclose(array1,array2)
可以衡量两个向量的距离。
numpy.pad()
用于填充数据,这里我填充数据,diag
后(2,2)
被填充为(2,4)
。使用np.zeros()
再相加会因不符合boardcast规则报错。