人工智能-数学基础-线性代数与仿射变换

深藏阁楼爱情的钟 2023-01-15 08:18 275阅读 0赞

此篇文章需要一些线性代数、矩阵分块和Numpy的基础,在文中对这些基础不再赘述

一. 坐标变换

1.1 一个点变换到另一个点

存 在 坐 标 点 ( x 1 , x 2 ) 需 要 变 换 到 ( y 1 , y 2 ) , 可 以 进 行 如 下 计 算 : 存在坐标点(x_1,x_2)需要变换到(y_1,y_2) ,可以进行如下计算: 存在坐标点(x1​,x2​)需要变换到(y1​,y2​),可以进行如下计算:

{ y 1 = a 11 x 1 + a 12 x 2 y 2 = a 21 x 1 + a 22 x 2 \begin{cases} y_1=a_{11}x_1+a_{12}x_2 \\ y_2=a_{21}x_1+a_{22}x_2 & \end{cases} { y1​=a11​x1​+a12​x2​y2​=a21​x1​+a22​x2​​​
以上代数计算关系可以写为矩阵运算关系:

[ y 1 y 2 ] = [ a 11 a 12 a 21 a 22 ] ⋅ [ x 1 x 2 ] \begin{bmatrix} y_1 \\ y_2 \\ \end{bmatrix} = \begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \\ \end{bmatrix} \cdot \begin{bmatrix} x_1 \\ x_2 \\ \end{bmatrix} [y1​y2​​]=[a11​a21​​a12​a22​​]⋅[x1​x2​​]

y → = A ⋅ x → \overrightarrow{y} = A \cdot \overrightarrow{x} y​=A⋅x
分量计算为:
y i = ∑ j = 1 2 a i j x j y_i = \sum_{j=1}^2a_{ij}x_j yi​=j=1∑2​aij​xj​
此为矩阵的点乘(内积)

1.2 n个点进行坐标变化

假 设 有 N 个 点 X ∈ R N × 2 , 多 有 点 均 进 行 矩 阵 预 算 : 假设有N个点 X \in \R^{N \times 2} ,多有点均进行矩阵预算: 假设有N个点X∈RN×2,多有点均进行矩阵预算:
注意:此时每一行代表了一个点
[ y 11 y 12 y 21 y 22 y 31 y 32 ] = [ x 11 x 12 x 21 x 22 x 31 x 32 ] ⋅ [ a 11 a 12 a 21 a 22 ] \begin{bmatrix} y_{11} & y_{12} \\ y_{21} & y_{22} \\ y_{31} & y_{32} \\ \end{bmatrix} = \begin{bmatrix} x_{11} & x_{12} \\ x_{21} & x_{22} \\ x_{31} & x_{32} \\ \end{bmatrix} \cdot \begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \\ \end{bmatrix} ⎣⎡​y11​y21​y31​​y12​y22​y32​​⎦⎤​=⎣⎡​x11​x21​x31​​x12​x22​x32​​⎦⎤​⋅[a11​a21​​a12​a22​​]
Y = X ⋅ A Y = X \cdot A Y=X⋅A
分量的形式:
y n i = ∑ j = 1 2 x n j a j i y_{ni} = \sum_{j=1}^2x_{nj}a_{ji} yni​=j=1∑2​xnj​aji​

1.3 M维空间数据

对 于 M 维 数 据 , X 为 n 行 m 列 数 据 X ∈ R n × m , A 为 m 行 k 列 数 据 A ∈ R m × k 对于M维数据, X为n行m列数据X \in \R^{n \times m},A为 m行k列数据A \in \R^{m \times k} 对于M维数据,X为n行m列数据X∈Rn×m,A为m行k列数据A∈Rm×k
Y = X ⋅ A Y = X \cdot A Y=X⋅A
Y 为 n 行 k 列 数 据 Y ∈ R n × k Y为 n行k列数据 Y\in \R^{n \times k} Y为n行k列数据Y∈Rn×k
分量的形式:
y i j = ∑ k m x i k a k m y_{ij} = \sum_k^mx_{ik}a_{km} yij​=k∑m​xik​akm​
所 以 , 如 果 需 要 对 n 维 空 间 中 的 点 进 行 变 换 , 则 需 要 A 满 足 m 行 m 列 , A ∈ R m × m 所以,如果需要对n维空间中的点进行变换,则需要 A满足m行m列,A \in \R^{m \times m} 所以,如果需要对n维空间中的点进行变换,则需要A满足m行m列,A∈Rm×m

二. 矩阵的仿射变换

2.1 我们先模拟一些点数据:

  1. """ 模拟点数据 """
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. plt.switch_backend("TkAgg")
  5. # 随机生成 1000 行, 2列的范围从 (0-1)的数据
  6. points = np.random.random([1000, 2])
  7. # 生成均匀的1000个 0到2的数字
  8. random_num = np.linspace(0, 2, 1000)
  9. # 将 line_x 重调为 1000行 1 列的矩阵
  10. line_x = np.reshape(random_num, [1000, 1])
  11. # 将 line_x进行列拼接. 得到 1000行两列的数据, 该数据类似于 斜率 0.5的直线
  12. line = np.concatenate([line_x, line_x], axis=1)
  13. # 将散点和线性数据进行 行拼接, 得到 2000行2列的数据
  14. join_point = np.concatenate([points, line], axis=0)
  15. plt.scatter(join_point[:, 0], join_point[:, 1], alpha=0.5, color="#ff0000")
  16. # 使横纵坐标等长
  17. plt.axis("equal")
  18. plt.show()

在这里插入图片描述

2.2 对点数据进行拉伸旋转平移:

a.仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。
b.仿射变换可以进行平移、旋转、放缩、镜像等变化。
c.仿射变换,可以保持原来的线共点、点共线的关系不变,保持原来相互平行的线仍然平行,保持原来的中点仍然是重点,保持原来在一直线上的几段线段的比例关系不变,但是仿射变换不能保持原来的线段长度不变,也不能保持原来夹角角度不变。

d.仿射变换公式:

[ x 1 y 1 1 ] = [ a 1 a 2 t x a 3 a 4 t y 0 0 1 ] ⋅ [ x y 1 ] \begin{bmatrix} x_1\\ y_1 \\ 1\\ \end{bmatrix} = \begin{bmatrix} a_1 & a_2 & t_x \\ a_3 & a_4 & t_y \\ 0 & 0 & 1\\ \end{bmatrix} \cdot \begin{bmatrix} x\\ y \\ 1\\ \end{bmatrix} ⎣⎡​x1​y1​1​⎦⎤​=⎣⎡​a1​a3​0​a2​a4​0​tx​ty​1​⎦⎤​⋅⎣⎡​xy1​⎦⎤​
其 中 ( t x , t y ) 表 示 平 移 量 , 而 参 数 a i 则 反 映 了 图 像 旋 转 、 缩 放 等 变 化 。 其中 (t_x,t_y)表示平移量,而参数a_i则反映了图像旋转、缩放等变化。 其中(tx​,ty​)表示平移量,而参数ai​则反映了图像旋转、缩放等变化。
例如:

  1. """ 仿射变换,拉伸,旋转, 平移 """
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. plt.switch_backend("TkAgg")
  5. # 随机生成 1000 行, 2列的范围从 (0-1)的数据
  6. points = np.random.random([1000, 2])
  7. # 生成均匀的1000个 0到2的数字
  8. random_num = np.linspace(0, 2, 1000)
  9. # 将 line_x 重调为 1000行 1 列的矩阵
  10. line_x = np.reshape(random_num, [1000, 1])
  11. # 将 line_x进行列拼接. 得到 1000行两列的数据, 该数据类似于 斜率 0.5的直线
  12. line = np.concatenate([line_x, line_x], axis=1)
  13. # 将散点和线性数据进行 行拼接, 得到 2000行2列的数据
  14. join_point = np.concatenate([points, line], axis=0)
  15. # 设置一个转换器(2行2列的矩阵), 该变换是 x 轴方向拉伸
  16. # 该矩阵的行列式也代表了面积的变化, 比如该行列式的为2,则代表变化后, 面积扩大了一倍
  17. A1 = np.array([[2, 0],
  18. [0, 1]])
  19. # 进行仿射变换, 以下三种均为矩阵的点乘
  20. # affine_point = join_point.dot(A)
  21. # affine_point = np.dot(join_point, A)
  22. affine_point1 = join_point @ A1
  23. # 设置一个转换器(2行2列的矩阵),该变换是斜向拉伸
  24. A2 = np.array([[1, 0.5],
  25. [0.5, 1]])
  26. affine_point2 = join_point @ A2
  27. # 单位矩阵, 做乘法保持以前大小形状角度不变
  28. A3 = np.array([[1, 0],
  29. [0, 1]])
  30. # 平移矩阵, 标识向右平移1, 向上平移2
  31. B = np.array([1, 2])
  32. affine_point3 = join_point @ A3 + B
  33. # 将原图形旋转90度
  34. theta = np.pi/2
  35. A4 = np.array([[np.cos(theta), np.sin(theta)],
  36. [-np.sin(theta), np.cos(theta)]])
  37. affine_point4 = join_point @ A4
  38. plt.scatter(join_point[:, 0], join_point[:, 1], alpha=0.2, color="#ff0000")
  39. plt.scatter(affine_point1[:, 0], affine_point1[:, 1], alpha=0.2, color="#0000ff")
  40. plt.scatter(affine_point2[:, 0], affine_point2[:, 1], alpha=0.2, color="#00ff00")
  41. plt.scatter(affine_point3[:, 0], affine_point3[:, 1], alpha=0.2, color="#000000")
  42. plt.scatter(affine_point4[:, 0], affine_point4[:, 1], alpha=0.2, color="#800080")
  43. # 使横纵坐标等长
  44. plt.axis("equal")
  45. plt.show()

在这里插入图片描述

三. 利用仿射变换可以对图像进行操作

还是拿我们喜爱的姚明同学举例:
在这里插入图片描述
将姚明同学逆过来:

  1. """ 将姚明同学逆过来 """
  2. import cv2
  3. import numpy as np
  4. # 获取图片并获取宽高信息
  5. img = cv2.imread("ym.png")
  6. h, w, c = img.shape
  7. # openCV的参数设置中, A和B写在了一起
  8. # 以y轴为标准做镜像, 并平移宽度 w的长度
  9. A = np.array([[-1., 0., w],
  10. [0., 1, 0]])
  11. img = cv2.warpAffine(img, A, (w, h))
  12. cv2.imshow("img", img)
  13. cv2.waitKey(0)

在这里插入图片描述

四.对视频进行仿射变换

例如:

  1. import cv2
  2. import numpy as np
  3. # 读取摄像的句柄,调去第一个摄像头
  4. cap = cv2.VideoCapture(0)
  5. # 构建读取循环
  6. while True:
  7. ret, img = cap.read()
  8. h, w, c = img.shape
  9. # 对影像做仿射变换
  10. A = np.array([[-1., 0., w],
  11. [0., 1, 0]])
  12. img = cv2.warpAffine(img, A, (w, h))
  13. cv2.imshow("img", img)
  14. # 每隔100ms没响应则继续读取
  15. ret = cv2.waitKey(100)
  16. if ret == 97:
  17. break
  18. cv2.destroyAllWindows()

发表评论

表情:
评论列表 (有 0 条评论,275人围观)

还没有评论,来说两句吧...

相关阅读

    相关 仿变换

    仿射变换是平移、缩放、旋转、对称、错切五种变换的组合,其数学表达形式如下: ⎧⎩⎨⎪⎪x′=a11x\+a12y\+x0y′=a12x\+a22y\+y0 采用

    相关 GDAL仿变换

    一、仿射变换(Affine GeoTransform)有六个参数,描述的是栅格行列号和地理坐标之间的关系。 在GDAL中可以通过函数GDALDataset::GetGeoTr

    相关 pytorch---仿变换

    一、仿射变换 图片的旋转、平移、缩放等可以看做一个像素的重采样过程。将原图的像素映射到目标图像的对应位置上,可以