- 矩阵乘法
- np.dot(A,B):真正的矩阵乘法
- np.multiply(A,B) & np重载的*:element-wise product,矩阵中对应元素相乘
- cv的A.dot(B) & cv重载的*:真正的矩阵乘法
- cv的A.mul(B) :element-wise product,矩阵中对应元素相乘
图像旋转
通过仿射矩阵
cv2.getRotationMatrix2D
和仿射变换函数cv2.warpAffine
来实现src:输入图像
M:变换矩阵
dsize:输出图像的大小(基于图像原点裁剪)
flags:插值方法
borderMode:边界像素模式
borderValue:边界填充值,默认为0
cv2.getRotationMatrix2D(center, angle, scale):返回一个2x3的变换矩阵
center:旋转中心
- angle:旋转角度,正值是逆时针旋转
scale:缩放因子
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])):返回变换后的图像
src:输入图像
M:变换矩阵
dsize:输出图像的大小(基于图像原点裁剪)
flags:插值方法
borderMode:边界像素模式
borderValue:边界填充值,默认为0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def rotate_img(angle, img, interpolation=cv2.INTER_LINEAR, points=[]):
h, w = img.shape
rotataMat = cv2.getRotationMatrix2D((w/2, h/2), math.degrees(angle), 1)
# rotate_img1: 输出图像尺寸不变,超出原图像部分被cut掉
rotate_img1 = cv2.warpAffine(img, rotataMat, dsize=(w, h), flags=interpolation, borderMode=cv2.BORDER_CONSTANT, borderValue=0)
# rotate_img2: 输出图像尺寸变大,保留超出原图像部分,新的坐标原点保证旋转中心仍旧位于图像中心
new_h = int(w*math.fabs(math.sin(angle)) + h*math.fabs(math.cos(angle)))
new_w = int(h*math.fabs(math.sin(angle)) + w*math.fabs(math.cos(angle)))
rotataMat[0, 2] += (new_w - w) / 2
rotataMat[1, 2] += (new_h - h) / 2
rotate_img2 = cv2.warpAffine(img, rotataMat, dsize=(new_w, new_h), flags=interpolation, borderMode=cv2.BORDER_CONSTANT, borderValue=0)
# 坐标点的变换
rotated_points = []
for point in points:
point = rotataMat.dot([[point[0]], [point[1]], [1]])
rotated_points.append((int(point[0]), int(point[1])))
return rotate_img2, rotated_points使用tips:
如果不修改仿射变换矩阵的平移参数,坐标原点的位置不发生改变
dsize指定的输出图像是从原点位置开始裁剪
坐标点的变换满足公式:
np.meshgrid(*xi,**kwargs)
这个函数神他妈坑,作用是Return coordinate matrices from coordinate vectors. Make N-D coordinate arrays for vectorized evaluations of N-D scalar/vector fields over N-D grids, given one-dimensional coordinate arrays x1, x2,…, xn. 但是尝试一下会发现:
1
2
3
4
5x = np.arange(0,10,1)
y = np.arange(0,20,1)
z = np.arange(0,30,1)
x, y, z= np.meshgrid(x, y, z)
print(x.shape) # (20, 10, 30)xy轴坐标是反过来的,这是因为optional args里面有一个indexing:
indexing : {‘xy’, ‘ij’}, Cartesian (‘xy’, default) or matrix (‘ij’) indexing of output.
我们想要得到的坐标系和输入的轴一一对应,得指定参数
indexing='ij'
1
2
3
4
5x = np.arange(0,10,1)
y = np.arange(0,20,1)
z = np.arange(0,30,1)
x, y, z= np.meshgrid(x, y, z, indexing='ij')
print(x.shape) # (10, 20, 30)还有一个参数sparse,因为每根轴的坐标都是复制的,所以可以稀疏存储,此时函数返回值变化:
sparse : bool, If True a sparse grid is returned in order to conserve memory. Default is False.
1
2
3
4
5
6
7
8
9
10x = np.arange(0,10,1)
y = np.arange(0,20,1)
xx, yy = np.meshgrid(x, y)
print(xx) # a 20x10 list
xx, yy = np.meshgrid(x, y, sparse=True)
print(xx) # a 1*10 list
print(yy) # a 20*1 list
# 所以整体上还是个20*10的矩阵二维可视化:
1
2
3
4
5import matplotlib.pyplot as plt
z = xx**2 + yy**2 # xx和yy既可以是dense convervation也可以是sparse convervation
h = plt.contourf(x,y,z)
plt.show()
np.tile(A,reps)
这个函数挺有用的,把数组沿着指定维度复制,比stack、concat啥的都优雅,能自动创建新的维度
- A:array_like, The input array.
- reps:array_like, The number of repetitions of A along each axis.
np.reshape(a, newshape, order=’C’)
这个函数贼常用,但是一般用于二维的时候没考虑重组顺序这件事
order: {‘C’, ‘F’, ‘A’}, optional,简单理解,reshape的通用实现方式是先将真个array拉直,然后依次取数据填入指定维度,C是从最里面的维度开始拉直&构造,F是从最外面的维度开始拉直&构造,A for auto
1
2
3
4
5
6
7
8
9
10
11
12a = np.arange(6)
array([0, 1, 2, 3, 4, 5])
# C-like index ordering
np.reshape(a, (2, 3))
array([[0, 1, 2],
[3, 4, 5]])
# Fortran-like index ordering
np.reshape(a, (2, 3), order='F')
array([[0, 4, 3],
[2, 1, 5]])tf和keras里面也有reshape,是没有order参数的,默认是’C’