OpenCV 自带大量矩阵处理函数,本文记录相关内容。
简介
- OpenCV 矩阵类的成员函数可以进行很多基本的矩阵操作,本文基于 《学习 OpenCV3 》中第五章的内容整理 Python OpenCV 矩阵操作函数。
内容列表
序号 | 函数 | 描述 |
---|---|---|
1 | cv2.phase() | 计算二维向量的方向 |
2 | cv2.polarToCart() | 已知角度和幅度,求出对应的二维向量 |
3 | cv2.pow() | 对矩阵内的每个元素求幂 |
4 | cv2.randu() | 用均匀分布的随机数填充给定的矩阵 |
5 | cv2.randn() | 用正态分布的随机数填充给定的矩阵 |
6 | cv2.randShuffle() | 随机打乱矩阵元素 |
7 | cv2.reduce() | 通过特定的操作将二维矩阵缩减为向量 |
8 | cv2.repeat() | 将一个矩阵的内容复制到另一个矩阵 |
9 | cv2.setIdentity() | 将矩阵中对角线上的元素设为1,其他置0 |
10 | cv2.solve() | 求出线性方程组的解 |
11 | cv2.solveCubic() | 找到三次方程的实根 |
12 | cv2.solvePoly() | 找到多项式方程的复根 |
13 | cv2.sort() | 在矩阵中排序任意行或列的元素 |
14 | cv2.sortIdx() | 与 cv2.sort() 的目的相同,除了矩阵是未修改的,并返回索引 |
15 | cv2.split() | 将一个多通道矩阵分割成多个单通道矩阵 |
16 | cv2.sqrt() | 计算矩阵逐元素的平方根 |
17 | cv2.subtract() | 实现两个矩阵逐元素相减 |
18 | cv2.trace() | 计算一个矩阵的迹 |
19 | cv2.transform() | 在矩阵的每个元素上应用矩阵变换 |
20 | cv2.transpose() | 矩阵的转置运算 |
矩阵操作
0. 基础引用
- 之后对上述函数进行示例演示
- 所有代码默认引用如下包
import cv2
import numpy as np
import mtutils as mt
from mtutils import PIS
- 示例图片
img1.jpg
和img2.jpg
- 查看 opencv 某函数
func
文档可以运行:
print(cv2.<func>.__doc__)
1. cv2.phase()
计算二维向量的方向
- 函数使用
cv2.phase(x, y) --> dst
对二维矢量场计算笛卡尔一极坐标转换的方位角(角度)部分。该矢量场是由两个独立的单通道矩阵组成。当然这两个输入矩阵的尺寸相同。(如果你有一个二通道的矩阵,那么调用cv2.phase()
将会做你所需要的。)然后,dst
中的每一个元素都从x
和y
的相应元素中计算两者的反正切值得到。
- 代码示例
x = np.array([1, 0, -1], dtype='float32')
y = np.array([1, -1, 1], dtype='float32')
res = cv2.phase(x, y)
-->
res
array([[0.7852316],
[4.712389 ],
[2.3563612]], dtype=float32)
上述结果分别为 frac{pi}{4}, frac{3pi}{2}, frac{3pi} { 4 }
2. cv2.polarToCart()
已知角度和幅度,求出对应的二维向量
- 函数使用
cv2.polarToCart(magnitude, angle, angleInDegrees=False)
cv2.polarToCart()
从向量场的极坐标中计算笛卡尔坐标(x,y)
。输入具有相同尺寸和类型的两个矩阵:幅度和角度,指定每个点处向量的幅度和角度。输出类似的两个矩阵,它们与输入具有相同的尺寸和类型,并且将包含每个点处向量的x
和y
投影。附加标志angleInDegrees
将使角度矩阵中的数值以度为单位,而不是弧度。
- 代码示例
mag = np.array(2**0.5)
angle = np.array(np.pi/4)
res = cv2.polarToCart(mag, angle)
-->
res
(array([[1.]]), array([[1.]]))
3. cv2.pow()
代码语言:javascript复制对矩阵内的每个元素求幂
data = np.reshape(np.arange(20), [4, 5])
res = cv2.pow(data, 2)
-->
res
array([[ 0, 1, 4, 9, 16],
[ 25, 36, 49, 64, 81],
[100, 121, 144, 169, 196],
[225, 256, 289, 324, 361]], dtype=int32)
4. cv2.randu()
用均匀分布的随机数填充给定的矩阵 注意: 该函数内联修改,输入数据会直接变为随机矩阵
- 函数使用
cv2.randu(data, low, high)
内联产生 low
high
之间的均匀分布随机数矩阵
- 示例代码
data = np.zeros([5, 5])
cv2.randu(data, low=2, high=3)
-->
data
array([[2.16117805, 2.03818934, 2.42586133, 2.84612762, 2.88760448],
[2.26471239, 2.27078305, 2.95266639, 2.6751313 , 2.81021636],
[2.18396021, 2.0944562 , 2.81590329, 2.52451766, 2.38083885],
[2.41199476, 2.25553534, 2.9448959 , 2.90012348, 2.45789156],
[2.84130697, 2.28030013, 2.3854357 , 2.45190146, 2.87543355]])
5. cv2.randn()
用正态分布的随机数填充给定的矩阵 注意: 该函数内联修改,输入数据会直接变为随机矩阵
- 函数使用
cv2.randn(data, mean, stddev)
内联产生以mean
为均值,stddev
为标准差的正态分布随机数矩阵
- 示例代码
data = np.zeros([5, 5])
cv2.randn(data, mean=5, stddev=1)
-->
data
array([[6.27751625, 6.43329835, 4.49584228, 3.92785478, 6.10956049],
[5.49447021, 4.10116905, 4.46068269, 4.88458967, 4.05134571],
[5.52288508, 5.11468363, 5.03454646, 4.02846879, 5.8627224 ],
[6.25682068, 4.23800135, 5.5566175 , 7.2824192 , 7.58638453],
[6.67061222, 4.90155111, 6.18168759, 3.01809192, 6.19408202]])
6. cv2.randShuffle()
代码语言:javascript复制随机打乱矩阵元素
data = np.reshape(np.arange(25), [5, 5])
cv2.randShuffle(data)
-->
data
array([[14, 5, 1, 13, 2],
[23, 20, 21, 3, 8],
[22, 4, 16, 7, 6],
[18, 17, 19, 24, 15],
[10, 11, 9, 12, 0]])
7. cv2.reduce()
通过特定的操作将二维矩阵缩减为向量
- 函数使用
cv2.reduce(src, dim, reduceOp=cv2.REDUCE_SUM) --> vec
简化是指使用一些reduceOp
所代表的组合规则,对输入矩阵src
的每一行(或列)进行系统的转化,直到只剩一行(或列)为止,使之成为向量vec
。参数dim
决定如何进行简化。
- 参数说明
src
接受参数为 float 类型的一维、二维数据
reduceOp
参数 | 含义 |
---|---|
cv2.REDUCE SUM | 计算向量的总和 |
cv2.REDUCE AVG | 计算向量的平均值 |
cv2.REDUCE MAX | 计算向量中的最大值 |
cv2.REDUCE MIN | 计算向量中的最小值 |
dim
参数 | 含义 |
---|---|
0 | 合并为1行 |
1 | 合并为1列 |
- 示例代码
data = np.reshape(np.arange(25, dtype='float32'), [5, 5])
res = cv2.reduce(data, 0, rtype=cv2.REDUCE_SUM)
-->
res
array([[50., 55., 60., 65., 70.]], dtype=float32)
8. cv2.repeat()
将一个矩阵的内容复制到另一个矩阵
- 函数使用
cv2.repeat(src, nx, ny)
将src 数据 x 方向重复 nx 次, y 方向重复 ny 次
- 示例代码
data = np.reshape(np.arange(4, dtype='float32'), [2, 2])
res = cv2.repeat(data, 2, 3)
-->
res
array([[0., 1., 0., 1., 0., 1.],
[2., 3., 2., 3., 2., 3.],
[0., 1., 0., 1., 0., 1.],
[2., 3., 2., 3., 2., 3.]], dtype=float32)
9. cv2.setIdentity()
代码语言:javascript复制将矩阵中对角线上的元素设为1,其他置0
mtx = np.random.random([5,6])
res = cv2.setIdentity(mtx)
-->
res
array([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1., 0.]])
10. cv2.solve()
求出线性方程组的解
- 函数用法
cv2.solve(src1, src2, flags)
- 其中 src1 为 A, src2 为 B
- flags
取值 | 含义 |
---|---|
cv2.DECOMP_LU | 高斯消元法(LU分解) |
cv2.DECOMP_SVD | 奇异值分解(SVD) |
cv2.DECOMP_CHOLESKY | 对于对称正定矩阵 |
cv2.DECOMP_EIG | 特征值分解,只用于对称矩阵 |
cv2.DECOMP_OR | QR因式分解 |
cv2.DECOMP_NORMAL | 可选附加标志;表示要求解标准方程 |
表中的前五个参数是互斥的,但最后一个参数cv2.DECOMP_NORMAL可以与前五个中的任何一个组合(例如,通过逻辑OR)。如果使用该参数,那么cv2.solve() 将尝试解决标准方程:hsT·Ihs·dst=lhsT·rhs, 而不是一般方程Ihs·dst=rhs。
- 示例代码
A = np.array([[1,2], [2,1]], dtype='float32')
B = np.array([[0], [1]], dtype='float32')
res = cv2.solve(A, B)
-->
res
(True, array([[ 0.6666667 ]...e=float32))
special variables
function variables
0:True
1:array([[ 0.6666667 ],
[-0.33333334]], dtype=float32)
special variables
[0:2] :[array([0.6666667], d...e=float32), array([-0.33333334],...e=float32)]
dtype:dtype('float32')
解方程成功, x = frac {2}{3}, y=-frac{1}{3}
11. cv2.solveCubic()
找到三次方程的实根
- 函数用法
cv2.solveCubic(coeffs)
给定由三或四个元素向量系数表示的三次多项式,cv2.solveCubic()
将计算该多项式的实根。如果coeffs有四个元素,则计算以下多项式的根:
如果coeffs只有三个元素,则计算以下多项式的根:
返回结果将具有一个或三个元素,具体取决于多项式具有多少个实根。
- 示例代码
coeffs = np.array([1,1,-12,0], dtype='float32')
res = cv2.solveCubic(coeffs)
-->
res
(3, array([[-4.0000000e ...e=float32))
special variables
function variables
0:3
1:array([[-4.0000000e 00],
[ 3.0000000e 00],
[ 8.3266727e-16]], dtype=float32)
special variables
[0:3] :[array([-4.], dtype=float32), array([3.], dtype=float32), array([8.3266727e-16...e=float32)]
special variables
function variables
得到 x3 x2-12x=0 的三个解 {-4, 3, 0}
12. cv2.solvePoly()
找到多项式方程的复根
- 函数使用
cv2.solvePoly(coeffs)
给定以系数向量表示的任意阶数的多项式,cv2.solvePoly()
将尝试计算该多项式的根。给定系数矩阵,计算以下多项式的根:
- 示例代码
coeffs = np.array([4, 0, 1], dtype='float32')
res = cv2.solvePoly(coeffs)
-->
res
(0.0, array([[[ 0., -2.]],...e=float32))
special variables
function variables
0:0.0
1:array([[[ 0., -2.]],
[[ 0., 2.]]], dtype=float32)
special variables
[0:2] :[array([[ 0., -2.]], ...e=float32), array([[0., 2.]], dt...e=float32)]
special variables
解得 x^2 4=0 方程的解为虚数 2j,-2j
13. cv2.sort()
在矩阵中排序任意行或列的元素
- 函数使用
cv2.sort(src, flags)
可以通过使用cv2.SORT_EVERY_ROW
或cv2.SORT_EVERY_COLUMN
标志对每一行或每一列进行排序。排序可以是升序或者降序,分别由cv2.SORT_ASCENDING
或cv2.SORT_DESCENDING
标志指定。需要从每一组中各选一个标志。
- 示例代码
data = cv2.randShuffle(np.reshape(np.arange(36), [6,6]))
res = cv2.sort(data, flags=cv2.SORT_EVERY_ROW)
-->
res
array([[ 1, 4, 8, 12, 30, 35],
[ 0, 5, 10, 11, 15, 22],
[ 3, 7, 16, 20, 25, 29],
[19, 21, 23, 24, 31, 34],
[ 9, 14, 18, 28, 32, 33],
[ 2, 6, 13, 17, 26, 27]], dtype=int32)
14. cv2.sortIdx()
代码语言:javascript复制与
cv2.sort()
的目的相同,除了矩阵是未修改的,并返回索引
data = cv2.randShuffle(np.reshape(np.arange(36), [6,6]))
res = cv2.sortIdx(data, flags=cv2.SORT_EVERY_ROW)
-->
res
array([[0, 1, 3, 2, 5, 4],
[3, 2, 4, 5, 1, 0],
[0, 2, 4, 5, 3, 1],
[1, 5, 3, 2, 0, 4],
[4, 1, 3, 0, 2, 5],
[1, 2, 0, 5, 4, 3]], dtype=int32)
15. cv2.split()
代码语言:javascript复制将一个多通道矩阵分割成多个单通道矩阵
image = mt.cv_rgb_imread('img1.jpg')
res = cv2.split(image)
PIS(image, *res)
16. cv2.sqrt()
代码语言:javascript复制计算矩阵逐元素的平方根
data = cv2.randShuffle(np.reshape(np.arange(16, dtype='float32'), [4, 4]))
res = cv2.sqrt(data)
-->
res
array([[3.3166249, 3. , 2.6457512, 1.4142135],
[2.4494898, 3.6055512, 2. , 1.7320508],
[3.4641016, 1. , 0. , 3.1622777],
[2.828427 , 3.7416575, 2.236068 , 3.8729835]], dtype=float32)
17. cv2.subtract()
代码语言:javascript复制实现两个矩阵逐元素相减
mat_1 = np.ones([3,3])
mat_2 = np.zeros([3,3])
cv2.setIdentity(mat_2)
res = cv2.subtract(mat_1, mat_2)
-->
res
array([[0., 1., 1.],
[1., 0., 1.],
[1., 1., 0.]])
18. cv2.trace()
代码语言:javascript复制计算一个矩阵的迹
mat_1 = np.ones([3,4], dtype='float32')
res = cv2.trace(mat_1)
-->
res
(3.0, 0.0, 0.0, 0.0)
19. cv2.transform()
在矩阵的每个元素上应用矩阵变换
- 函数使用
cv2.transform(src, mtx)
函数cv2.transform()
可用于计算任意线性图像变换。它将多通道输入矩阵src
视为向量的集合,你可以将其视为“通道空间”,然后将这些向量乘以“小”矩阵mt
×,以实现此通道空间中的转换。
- 示例代码
image = mt.cv_rgb_imread('img1.jpg')
mtx = cv2.flip(cv2.setIdentity(np.zeros([3, 3], dtype='float32')), flipCode=0)
gbr = cv2.transform(image, mtx)
PIS(image, gbr)
20. cv2.transpose()
代码语言:javascript复制矩阵的转置运算
mat = np.reshape(np.arange(16, dtype='float32'), [4, 4])
res = cv2.transpose(mat)
-->
res
array([[ 0., 4., 8., 12.],
[ 1., 5., 9., 13.],
[ 2., 6., 10., 14.],
[ 3., 7., 11., 15.]], dtype=float32)
示例源码
- https://github.com/zywvvd/Python_Practise
参考资料
- 《学习 OpenCV3》 第五章