python 线性变换

线性代数仅仅围绕向量加法和数乘。

前言

距离上一篇博客已经好长时间没有写啦,前段时间也没有整天在摸鱼,可能学习的知识太过零散,没法总结。
最近三天猛接触向量,终于把线性代数的一些知识搞明白了,用python进行了验证。
之前也写过一篇关于向量的:python 求点和点之间的距离;向量之间的余弦距离、欧式距离;点到向量的距离

需要理清的概念

  • 矩阵变换
  • 线性变换
  • 基变换
  • 坐标变换
  • 矩阵右乘和左乘
  • 坐标旋转方程
  • 跟随坐标变换后的点与原坐标下点的位置关系
  • 旋转方程和欧拉角
  • 仿射变换

目录

  • 前言
  • 1. 什么是线性变换
    • 1.1 例1:向量变换
    • 1.2 例2:坐标旋转
    • 1.3 总结
    • 1.4 参考链接
  • 2. 线性变换实现
    • 2.1 矩阵变换
    • 2.2 基变换
    • 2.3 坐标变化
    • 2.4 位置不变
  • 3. 旋转方程和欧拉角
  • python实践:计算x轴坐标变换对向量夹角的影响

1. 什么是线性变换

特征:

  1. 直线变换后仍为直线;2. 原点保持固定。

特性:

变换后的向量仍旧是相同的线性组合,不过使用的是新的基向量。(这个理解很重要,对应与1.1 坐标旋转图中右上角的定理部分)
那么,只需要知道两个基向量(i向量和j向量)转换之后的的结果,而不用知道转换本身,我们就能推导出二维空间中所有向量转换之后的结果。

定义:

变换(或映射)T称为线性变换的,若:

  • 对定义域内的一切u,vu,v,T(u+v)=T(u)+T(v)T(u+v)=T(u)+T(v)。
  • 对定义域内的一切uu; 和任何标量c,T(T(cu)=u)=cT(u)T(u)。
    可以证明,每一个矩阵变换都是线性变换,反正则不成立。(矩阵变换就是线性变换)

1.1 例1:向量变换

python 线性变换_第1张图片

1.2 例2:坐标旋转

解法1:
参考链接:利用向量推导坐标旋转公式(方案一)
python 线性变换_第2张图片
解法2(线性变换的思路,推荐):
python 线性变换_第3张图片

1.3 总结

  1. 坐标系变换前后使用相同的线性组合;
  2. 原坐标系去表达变换后的坐标。

1.4 参考链接

矩阵与线性变换

2. 线性变换实现

参考链接:坐标变换与基变换——左乘与右乘

可以先思考两个问题:

  1. A坐标系上的点P,通过坐标变换到B坐标系,P是跟着动的,此时P点的坐标在A坐标系中应该如何表示?
    此题的解即为“1.2 例2:坐标旋转”,这是一个线性变换。
  2. A坐标系上的点P,通过坐标变换到B坐标系,P是不动的,此时P点的坐标在B坐标系中应该如何表示?

2.1 矩阵变换

解决上述两个问题,共同点就是坐标系发生了变换,而坐标系的变换要用矩阵变换来表述。可以先理解一下下面这两句话,后面会对这两句话例子描述。用什么方法来求解矩阵变换的这个矩阵就可以用基变换来求解。

  • 矩阵变换之于同一个坐标系,可以理解为坐标系不变,点的位置改变。
  • 矩阵变换之于不同坐标系,可以理解为点的绝对位置不变,坐标系改变。

2.2 基变换

每当我们用数字描述向量时,它都依赖于我们使用的基。

变换中需要满足以下条件,下面的变换矩阵理解为上文“1.2 例2:坐标旋转”中最终答案的橙色矩阵,在基变换中这个矩阵也被称为过渡矩阵

  • 坐标系A和坐标系B原点均为(0,0)
  • 变换矩阵的各个列向量分别对应B坐标系的各个基向量
  • 变换矩阵的各个列向量都是坐标系A中的向量

坐标系B的基向量是坐标系A的基向量的一个线性变换 ,确定坐标系B的基向量在A坐标系中的表示的过程叫做B坐标系的定位(landed)。将B坐标系的基向量定位在A坐标系中确定了一种关系,我们暂且把这种关系称为追溯关系,把A坐标系称为B坐标系的上游坐标系。反过来,如果把坐标系A的基向量定位在B坐标系中,那么B坐标系就成了A坐标系的上游坐标系。
得到了过渡矩阵之后就可以实现坐标变化。

2.3 坐标变化

坐标变换是空间实体的位置描述,是从一种坐标系统变换到另一种坐标系统的过程。通过建立两个坐标系统之间一一对应关系来实现。是各种比例尺地图测量和编绘中建立地图数学基础必不可少的步骤。两个及以上的坐标转换时由极坐标相对参照确定维数空间。

坐标变换就是原坐标系上的点跟随左边变换全部进行移动,比如在二维平面上的旋转、齐次坐标系与平移等。
坐标变换必定发生基变换(这句话是我自己理解的),这两个都属于矩阵变换,而矩阵变换都是线性变换,变换后的向量仍旧是相同的线性组合。比如P在A坐标系下的表示是(2, 1),在B坐标系下的表示仍旧是(2, 1),而A坐标系和B坐标系的基不同。
参考链接:坐标系变换

2.4 位置不变

这个就是第二个问题的解决方案,可以看这个链接的“P13"-UP主汉语配音-【线性代数的本质】合集-转载于3Blue1Brown官方双语】(图片就是这个教程中来的)。
下图是对以上内容的总结和对第二个问题的示意解法。
python 线性变换_第4张图片

3. 旋转方程和欧拉角

参考:
Computing Euler angles from a rotation matrix
旋转(Rotation)矩阵转欧拉角(euler).

一句话总结:

  1. 明白旋转矩阵的组成部分;
  2. 欧拉角是由旋转矩阵推导来的;
  3. 欧拉角有两解和无穷多解。

python实现
欧拉角中的偏航角(Yaw)、俯仰角(Pitch)和横滚角(Roll)概念个人感觉是比较难分清的,但是真正在求解的过程中只需要记住绕x轴,绕y轴,绕z轴旋转就可以了,以下几个链接的计算方式主要分为两种,一种是用到了cv2.decomposeProjectionMatrix函数,另一种是通过推导公式计算,两者的结果是一样的。

https://blog.csdn.net/loveliuzz/article/details/102716290
https://blog.csdn.net/weixin_41856614/article/details/107488878
https://blog.csdn.net/ZHUO__zhuo/article/details/124634228
https://blog.csdn.net/u014090429/article/details/100762308
https://github.com/yuenshome/yuenshome.github.io/issues/9
https://stackoverflow.com/questions/15022630/how-to-calculate-the-angle-from-rotation-matrix

python实践:计算x轴坐标变换对向量夹角的影响

import numpy as np
import math
def get_angle(v1, v2):
    # 余弦距离计算角度[0-180)
    if np.count_nonzero(v1) == 0 or np.nonzero(v2) == 0:
        return np.nan
    angle = np.dot(v1, v2) / (np.sqrt(np.sum(v1 * v1)) * np.sqrt(np.sum(v2 * v2)))
    angle = np.arccos(angle) / np.pi * 180

    return angle

a = np.array([2, 1])
b = np.array([2, -3])
c = np.array([-2, 2])
print(get_angle(a, b))
print(get_angle(c, b))
ang = 30
ang = ang / 180 * np.pi

trans = np.array([[math.cos(ang), 0],
                  [math.sin(ang), 1]])

ta = np.dot(trans, a)
tb = np.dot(trans, b)
tc = np.dot(trans, c)
print(get_angle(ta, tb))
print(get_angle(tc, tb))

你可能感兴趣的:(Python里的碰撞,python,线性代数,矩阵)