当前位置: 首页 > news >正文

游戏引擎学习第101天

回顾当前情况

昨天的进度基本上完成了所有内容,但我们还没有进行调试。虽然我们在运行时做的事情大致上是对的,但还是存在一些可能或者确定的bug。正如昨天最后提到的,既然现在时间晚了,就不太适合开始调试,所以今天我们将专门花时间逐步调试。

记得之前提到过几个bug问题。首先,我们没有正确地转换法线,因此在物体旋转时法线没有得到正确的调整。我们需要检查一下这个问题。其次,当我们使用球形法线贴图时,发现它似乎没有按照我们预期的方式弯曲,所以我们可能在这方面有个小bug。虽然离正确的法线贴图功能已经很近,但细节上还没有完全搞定。我们接下来的工作将集中在这些问题上,逐步修复。

开始思考如何转换法线

我们可以先考虑如何解决法线转换的问题。现在,我们已经设置好进行转换了。虽然在旋转时,法线始终指向上下方向,而这并不是我们真正想要的效果。我们已经准备好进行调试和修改,接下来需要处理的是法线的旋转,确保它们正确地朝向旋转后的位图方向。

首先,如果位图没有旋转,这个问题就不大,因为法线已经是朝着正确的方向。问题出现在位图旋转时,法线没有相应地进行旋转。为了支持这种情况,我们需要先构建一个路径,处理所有可能的情况,并确保法线旋转符合预期。随后,我们可以根据实际情况进行优化,去除不必要的处理步骤。例如,许多时候,位图并不会旋转,保持静止,因此没有必要每次都进行旋转法线的计算,这样的优化可以减少性能开销。

接下来,计划是构建一个旋转法线的路径,确保法线能随着位图旋转正确变换,之后再根据需要优化不必要的计算。

黑板:旋转法线(相当简单)

这个问题的关键在于正确地处理法线的旋转。可以把它看作是一个比较简单的数学问题。我们有一个贴图,其中包含了一些向量。当从贴图中提取出这些向量时,我们默认它们是按照贴图的原始方向来处理的,通常是按着贴图的坐标系(x轴和y轴)进行的。

假设贴图没有旋转的话,提取出的向量方向就是正常的。但是,如果图旋转贴了,比如旋转了45度,那么贴图中的向量方向应该也随之发生变化。简单来说,即使我们对贴图进行了旋转,提取出的贴图像素(Texel)仍然会按照原始的坐标系方向来显示,导致向量的方向不正确。为了纠正这一点,我们需要对这些法线向量进行旋转,使其与贴图的实际旋转保持一致。

因此,旋转法线的本质是利用贴图的坐标系来更新法线的方向,确保它们与贴图的旋转一致。

黑板:非均匀缩放有点复杂

当进行非均匀缩放时,X 和 Y 轴的缩放会有不同的变化,这种情况需要特别注意。具体来说,问题在于法线的变化。假设我们有一个向量,表示两个物体之间的关系。如果对 Y 轴进行缩放,想象法线会发生怎样的变化?法线会像被拉伸一样变长,就像如果它是一个点被缩放时一样,法线会沿着 Y 轴的方向进行伸展。

这就引出了一个问题:如果我们缩放一个表示表面的物体,法线是否应该按这种方式变化?这不仅仅是缩放表面的问题,还涉及如何处理法线方向和缩放比例的关系。法线的缩放需要根据具体的应用需求进行调整,而不是单纯地按比例伸缩。

黑板:假设我们有宝石的边缘

假设有一个形状,类似于一个宝石的边缘,法线大约指向45度的角度。如果对 Y 轴进行缩放,使其变长,那么原本代表法线的形状也会发生变化,变得拉长。也就是说,整体的形状会发生剪切,某些部分会被拉伸。

如果将法线按照相同的比例进行缩放,法线也会沿着 Y 轴方向伸展,但实际上,这种处理并不符合表面应有的变化。因为表面本身的法线,随着形状的拉伸,应该朝着相反的方向偏移。也就是说,表面的法线应该更多地指向下方,而不是继续沿着原先的方向。

因此,在支持非均匀缩放时,不能简单地将法线按与物体相同的方式进行缩放。要正确处理法线,需要考虑线性代数的知识,特别是在进行非均匀缩放时,法线的计算并不是直观的。对于没有线性代数背景的人来说,这种调整可能不容易理解,但它是必要的。
在这里插入图片描述

黑板:向量并不全是相同的

向量并非都是相同的,且有许多原因使得向量之间的行为不同。以 RGB 颜色值为例,特别是有预乘 alpha 的 RGBa 颜色值,它与非预乘 alpha 的 RGBa 颜色值在操作上就有所不同。预乘 alpha 允许进行线性操作,并且能够正常工作,而非预乘 alpha 则无法直接进行线性操作。这表明,向量不仅仅是将数字组合在一起的工具,它们的行为会根据具体的应用或操作不同而变化。

在更基础的层面,向量被视为一种处理数字的方式,但从理论角度来看,向量的行为可能因所做的操作类型不同而变化。预乘 alpha 可以被视作一个符合线性操作的向量,而非预乘的颜色值则不是这样,它们的行为和性质不一样,属于不同类型的数学对象,而不仅仅是编程对象。

在几何学中,构成形状的点可以看作是一种向量,它从原点指向特定的点,并且在坐标系变化时具有特定的行为。然而,法线是另一种类型的向量,它们的变换规则与点的向量不同,甚至有专门的术语来区分这两种向量类型,例如协变向量和逆变向量。对于法线来说,当应用变换时,它们的处理方式与点的向量不同,必须使用与点不同的变换规则。

如果有一个变换(例如伸长变换),当将点应用到该变换时,它们会按照预期进行变换,但法线的变换则需要使用不同的规则,以确保它们仍然符合法线的行为特性。因此,法线和点向量在处理变换时的行为不同,理解这一点对于正确处理非均匀缩放和其他变换非常重要。

协变向量(Covariant vector)和逆变向量(Contravariant vector)是描述向量如何在坐标变换下变化的两种不同类型的向量。它们的区别主要在于它们如何响应坐标系的变化。

1. 逆变向量(Contravariant Vector)

  • 定义:逆变向量是最常见的向量类型,通常是我们所说的普通向量。它们在坐标变换时会“反向”地变化。
  • 变化规则:如果进行坐标变换(例如旋转或缩放),逆变向量会按照坐标变换矩阵的逆来变化。换句话说,坐标系的基向量发生变化时,逆变向量会与基向量的变化方向相反。
  • 例子:在三维空间中,一个位于原点到点 P 的向量(例如位置向量)通常是逆变向量。它会随坐标系的变化(比如旋转)而变化。

2. 协变向量(Covariant Vector)

  • 定义:协变向量通常被用来表示梯度、法线等类型的量。它们的行为与逆变向量不同,当坐标系发生变化时,它们会“跟随”坐标系的变化。
  • 变化规则:协变向量在坐标变换时会直接按照坐标变换矩阵的方式变化。也就是说,协变向量的变化方式与基向量的变化方向一致。
  • 例子:法线向量就是一个协变向量的例子。如果一个表面发生变换(比如旋转或缩放),法线向量会随之变化,使得它始终与表面保持垂直。

总结区别

  • 逆变向量:变换时反向调整,通常用于描述位置、速度等物理量。
  • 协变向量:变换时直接调整,通常用于描述梯度、法线等方向性量。

直观解释

  • 想象一下在三维空间中有两个坐标系,A 和 B。假设 B 系统是经过 A 系统旋转或缩放得到的。在 B 系统中,如果你有一个逆变向量(比如位置向量),它会按反向变化来适应 B 系统的变化。而如果你有一个协变向量(比如法线向量),它会随坐标变换直接变化,以保持其在 B 系统中的正确方向。

这种区别在几何变换和物理学中很重要,尤其是在考虑如何处理变换时(如非均匀缩放和旋转)。

黑板:法线在线性代数中是不同的

在处理法线和点时,它们在数学上的处理方式不同,尤其是在向量的表示和变换上。点通常被表示为列向量(例如,px, py, pz),而法线则通常被表示为行向量。这种差异源于它们在坐标变换中的不同表现方式。

当处理变换时,点的变换通常使用变换矩阵直接进行,而法线的变换则需要使用变换矩阵的逆转置(inverse transpose)。也就是说,如果有一个作用于点的变换矩阵,要想正确地变换法线,必须使用该矩阵的逆转置。

这一点在线性代数中是非常常见的,尽管随着时间的推移,可能会忘记一些细节,但这种变换的规则对于正确处理法线和点在变换下的行为非常重要。

黑板:有时你得钻进数学的深坑α

可能需要深入探讨一些数学内容。虽然这可能会带来一些数学方面的挑战,但有时确实需要走出舒适区进行探索,因此可以尝试引入这个概念,并进行一些思考和讨论。

黑板:构造P向量

在构造这些P向量时,最初的情况是在二维空间中,有两个分量:px和py。这些是空间中的点,目的是将这些点转化为某种坐标系统中的点。为了实现这一点,构建了一个方法,将这些点的两个分量分别乘以x轴和y轴的向量,这样就得到了所谓的“屏幕空间点”。

这个方法的核心在于坐标系统的设定,其中x轴和y轴向量是二维向量,可以变化,并且通过旋转这些向量,可以使所有相关点的值随着旋转一起改变。这个旋转操作是通过旋转这些二维向量来实现的,形成了一个动态的网格,可以在其中进行缩放和旋转。这个系统的基础是支持纹理映射中的旋转和缩放的基础框架。

黑板:矩阵乘法

在矩阵形式中,首先要回顾一下矩阵乘法的基本操作。矩阵和向量是类似的,都是由数字组成的数组。通过回顾向量的点积,理解矩阵乘法其实是类似的过程。点积的计算方式是将对应的元素相乘后相加,这同样适用于矩阵乘法。

在矩阵与向量的乘法中,计算的基本步骤是对矩阵的每一行和向量的每一列进行点积。假设有一个2x2的矩阵,我们可以通过逐行逐列地进行点积,最终得到一个新的结果矩阵。这个过程对于任何矩阵乘法都适用,无论是矩阵与矩阵,还是矩阵与向量的乘法。

通过对矩阵的乘法理解,可以看到矩阵中的每一列代表一个坐标轴,进行矩阵运算时,实际上就是对这些坐标轴进行变换,比如旋转或缩放。矩阵允许以一种简洁的方式表示这些变换,而无需手动处理所有的标量量。

矩阵乘法的优势在于可以轻松地组合多个变换。例如,若有多个旋转和缩放操作,可以通过矩阵相乘来组合这些变换,从而得到一个新的变换矩阵,避免手动存储和操作多个变换。

此外,矩阵不仅支持乘法,还有逆运算、加法等操作。逆矩阵的计算比较复杂,但矩阵乘法本身是相对简单的,按照上述的点积方法就能完成。

总之,通过矩阵运算,可以高效地处理变换和操作,避免了手动管理多个标量量的麻烦。理解这些矩阵操作为后续处理更复杂的变换提供了基础。

矩阵的逆运算是线性代数中一个非常重要的概念。对于一个方阵 A A A,它的逆矩阵 A − 1 A^{-1} A1 满足以下关系:

A × A − 1 = A − 1 × A = I A \times A^{-1} = A^{-1} \times A = I A×A1=A1×A=I

其中, I I I 是单位矩阵。单位矩阵是一个对角线上全是 1,其他位置全是 0 的方阵。

1. 什么矩阵有逆矩阵?

并不是所有的矩阵都有逆矩阵。只有非奇异矩阵(即行列式不为零的矩阵)才有逆矩阵。如果矩阵的行列式 det ( A ) = 0 \text{det}(A) = 0 det(A)=0,那么该矩阵是奇异矩阵,没有逆矩阵。

2. 如何计算矩阵的逆?

对于一个 2 × 2 2 \times 2 2×2 矩阵:

A = [ a b c d ] A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} A=[acbd]

其逆矩阵可以通过以下公式计算:

A − 1 = 1 det ( A ) [ d − b − c a ] A^{-1} = \frac{1}{\text{det}(A)} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} A1=det(A)1[dcba]

其中,行列式 det ( A ) \text{det}(A) det(A) 是:

det ( A ) = a d − b c \text{det}(A) = ad - bc det(A)=adbc

如果 det ( A ) = 0 \text{det}(A) = 0 det(A)=0,则矩阵没有逆矩阵。

对于更高维的矩阵,求逆的过程稍微复杂一些,通常通过高斯-约旦消元法或者伴随矩阵法来计算。

3. 高斯-约旦消元法(Gauss-Jordan Elimination)

高斯-约旦消元法是一种常用的求逆矩阵的算法,基本步骤如下:

  1. 将矩阵 A A A 和单位矩阵 I I I 拼接成一个增广矩阵:

    [ A ∣ I ] \left[ A | I \right] [AI]

  2. 通过一系列的行变换(行交换、行倍加、行线性组合等)将矩阵 A A A 化为单位矩阵 I I I,同时对单位矩阵 I I I 进行相应的变换。

  3. 最终增广矩阵的右半部分将是矩阵 A A A 的逆矩阵 A − 1 A^{-1} A1

4. 伴随矩阵法

伴随矩阵法通过求解矩阵的伴随矩阵(即矩阵的伴随矩阵是由矩阵的代数余子式构成的矩阵)来计算逆矩阵。具体步骤如下:

  1. 计算矩阵 A A A代数余子式矩阵 C C C

  2. 计算矩阵 C C C伴随矩阵 A ∗ A^* A,即将代数余子式矩阵进行转置。

  3. 计算矩阵 A A A 的行列式 det ( A ) \text{det}(A) det(A)

  4. 逆矩阵为:

    A − 1 = 1 det ( A ) A ∗ A^{-1} = \frac{1}{\text{det}(A)} A^* A1=det(A)1A

5. 数值求解

对于大矩阵,通常采用数值方法来计算逆矩阵,例如LU分解、QR分解等,这些方法更适合处理高维矩阵的求逆问题。

6. 逆矩阵的性质

  • 逆矩阵的唯一性:如果矩阵 A A A 有逆矩阵,则它的逆矩阵是唯一的。
  • 矩阵乘法的逆 ( A B ) − 1 = B − 1 A − 1 (AB)^{-1} = B^{-1}A^{-1} (AB)1=B1A1
  • 转置矩阵的逆 ( A T ) − 1 = ( A − 1 ) T (A^T)^{-1} = (A^{-1})^T (AT)1=(A1)T
  • 可逆性与行列式:矩阵可逆的充要条件是其行列式不为零,即 det ( A ) ≠ 0 \text{det}(A) \neq 0 det(A)=0

总之,矩阵的逆运算是解决线性方程组、进行几何变换等问题中的核心操作。掌握其计算方法对于理解和应用矩阵变换非常重要。

黑板:转置操作

转置和逆矩阵是两个常见的矩阵操作。我们先讨论转置操作和逆矩阵操作的区别及其意义。

1. 转置操作(Transpose)

转置是指将矩阵的行和列互换。具体来说,假设我们有一个矩阵 A A A

A = [ a b c d e f g h i ] A = \begin{bmatrix} a & b & c \\ d & e & f \\ g & h & i \end{bmatrix} A= adgbehcfi

它的转置 A T A^T AT 就是将矩阵中的行和列交换:

A T = [ a d g b e h c f i ] A^T = \begin{bmatrix} a & d & g \\ b & e & h \\ c & f & i \end{bmatrix} AT= abcdefghi

转置操作的核心是“镜像反射”沿着矩阵的主对角线(从左上到右下的对角线)。换句话说,矩阵 A A A 中的元素 A [ i ] [ j ] A[i][j] A[i][j] 在转置后会变为 A T [ j ] [ i ] A^T[j][i] AT[j][i]

转置操作的计算过程非常简单,可以通过重新排列矩阵元素实现。这种操作在矩阵计算中非常重要,因为它能够改变矩阵的排列结构,有助于在一些数学和物理问题中产生所需的变换。

例如,如果我们有一个矩阵表示了某些数据,转置操作可能会帮助我们从不同的角度理解这些数据或将其转换为适合进一步操作的形式。

2. 逆矩阵操作(Inverse Matrix)

逆矩阵是与矩阵相乘得到单位矩阵的矩阵。如果矩阵 A A A 有逆矩阵 A − 1 A^{-1} A1,则满足:

A × A − 1 = A − 1 × A = I A \times A^{-1} = A^{-1} \times A = I A×A1=A1×A=I

其中 I I I 是单位矩阵。并不是所有矩阵都有逆矩阵,只有当矩阵的行列式不为零时,矩阵才有逆矩阵(即非奇异矩阵)。如果行列式为零,矩阵就是奇异矩阵,不能计算其逆矩阵。

求逆矩阵的过程相对复杂,通常有两种常见方法:高斯-约旦消元法和伴随矩阵法。

  • 高斯-约旦消元法:通过对增广矩阵(原矩阵与单位矩阵拼接在一起)进行行变换,最终得到矩阵的逆。
  • 伴随矩阵法:先计算矩阵的代数余子式矩阵,然后取其转置得到伴随矩阵,最后通过行列式的倒数与伴随矩阵相乘得到逆矩阵。

逆矩阵在数学和工程应用中非常重要,尤其是在求解线性方程组、进行坐标变换、图形学中的变换等方面。

小结

  • 转置操作通过交换矩阵的行和列来改变矩阵的结构,简单易懂且易于实现。它的作用主要体现在矩阵的重排列,可以帮助我们在不同的坐标系之间进行转换。
  • 逆矩阵操作则是寻找一个矩阵,使得与原矩阵相乘得到单位矩阵。它通常用于解线性方程组或在多次变换的复合运算中恢复原始状态。

黑板:逆操作

逆矩阵的定义是:对于一个矩阵 A A A,它的逆矩阵 A − 1 A^{-1} A1 是一个矩阵,使得当 A A A A − 1 A^{-1} A1 相乘时,得到的是单位矩阵 I I I。单位矩阵是一个特殊的矩阵,其对角线上的元素为 1,其余元素为 0。单位矩阵有一个重要特性,它在与其他矩阵或向量相乘时,不会改变它们的值,即它是乘法中的“恒等元素”。

1. 单位矩阵

单位矩阵是一个非常特殊的矩阵,其结构如下:

I = [ 1 0 0 0 1 0 0 0 1 ] I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} I= 100010001

单位矩阵的作用类似于数字 1 在数值乘法中的作用。当一个矩阵与单位矩阵相乘时,它的值不会发生变化。例如,假设有一个向量 v = [ x y ] \mathbf{v} = \begin{bmatrix} x \\ y \end{bmatrix} v=[xy],如果将这个向量与单位矩阵相乘,结果就是:

I × v = [ x y ] I \times \mathbf{v} = \begin{bmatrix} x \\ y \end{bmatrix} I×v=[xy]

同样,矩阵乘法中的单位矩阵具有类似的性质,它不会改变与其相乘的矩阵或向量的值。

2. 逆矩阵的求解

逆矩阵的核心在于它能够“反转”一个矩阵的作用,使得矩阵与其逆矩阵相乘得到单位矩阵。假设有一个矩阵 A A A,其逆矩阵 A − 1 A^{-1} A1 满足:

A × A − 1 = A − 1 × A = I A \times A^{-1} = A^{-1} \times A = I A×A1=A1×A=I

为了找到矩阵 A A A 的逆矩阵,可以通过解方程的方式,利用矩阵的已知元素(如 A A A 中的元素)来推导出逆矩阵的元素。这就意味着需要解决一个方程组,其中包含了矩阵 A A A 中的元素和未知的逆矩阵元素。求解这个方程组的过程就是求逆矩阵的过程。

3. 乘法恒等元素和加法恒等元素

  • 乘法恒等元素:单位矩阵就是矩阵乘法中的恒等元素,它对其他矩阵或向量没有任何影响。
  • 加法恒等元素:与乘法恒等元素不同,加法恒等元素是一个全零矩阵,它在矩阵加法中充当类似角色,即与任何矩阵相加不会改变原矩阵。

小结

逆矩阵是矩阵运算中的一个重要概念,它使得矩阵能够“反转”其作用。通过逆矩阵和单位矩阵的性质,可以解决很多线性代数中的问题。求逆矩阵的过程通常涉及解方程组,计算复杂度较高,但它对于许多应用场景,如求解线性方程组、图形学中的变换等,都非常重要。

黑板:高斯消元法登场

解四个联立方程的过程通常被认为是一个麻烦的任务,尤其当需要处理多个方程时,可能会导致计算错误,因此很多人都会感到头疼。幸运的是,有一种方法叫做高斯消元法(Gaussian Elimination),它提供了一种相对简单的方式来求解方程组或计算矩阵的逆矩阵,尤其是在矩阵规模较小的情况下。

高斯消元法实际上不是用于计算大规模矩阵的逆或求解大规模方程组的理想选择。对于科学计算来说,矩阵的规模可能非常庞大,甚至达到数千、数万,甚至数百万个元素,这样的情况下使用高斯消元法就显得不切实际,因为它的时间复杂度是 O ( n 3 ) O(n^3) O(n3),处理大型矩阵时效率较低,并且在处理浮点数时存在数值不稳定性。

尽管如此,高斯消元法在解决简单的、规范化的 2x2 或更小规模的矩阵问题时仍然非常有效。在这种情况下,可以使用高斯消元法来进行矩阵求逆和方程求解。

矩阵最初并不是为计算机图形学而发明的,实际上它们是为了解决线性方程组而设计的。高斯消元法的出现正是为了解决含有多个未知数和方程的系统。在这种方法中,首先将方程的系数整理成一个矩阵,然后通过一系列的步骤(如消元)来求解未知数。每个方程中的系数可以视为矩阵中的元素,未知数则形成一个向量。这样,通过矩阵的乘法运算,就可以将原始的线性方程组转化为矩阵方程 A x = b Ax = b Ax=b,其中 A A A 是系数矩阵, x x x 是未知数向量, b b b 是常数向量。

这种方法大大简化了求解过程,使得解决复杂的方程组变得更加系统化和高效。高斯消元法通过逐步消元,将矩阵转化为上三角矩阵或对角矩阵,从而轻松求解未知数。
高斯消元法通过一系列的行变换,将矩阵转化为上三角矩阵或对角矩阵,最终求解线性方程组。下面通过一个简单的例子来演示高斯消元法的过程。

举例

让我们一步步进行高斯-乔丹消元法的求解。给定的方程组是:

3 x + y + z = 10 x + 2 y − 3 z = 10 x + y − z = 6 \begin{aligned} 3x + y + z &= 10 \\ x + 2y - 3z &= 10 \\ x + y - z &= 6 \end{aligned} 3x+y+zx+2y3zx+yz=10=10=6

第一步:将方程组写成增广矩阵

增广矩阵为:

[ 3 1 1 ∣ 10 1 2 − 3 ∣ 10 1 1 − 1 ∣ 6 ] \begin{bmatrix} 3 & 1 & 1 & | & 10 \\ 1 & 2 & -3 & | & 10 \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 31112113110106

第二步:交换行,使得左上角为1

我们交换第1行和第2行,以便左上角为1:

[ 1 2 − 3 ∣ 10 3 1 1 ∣ 10 1 1 − 1 ∣ 6 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 3 & 1 & 1 & | & 10 \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 13121131110106

第三步:消去第一列中的其他数值

  1. 第2行:用第2行减去第1行的3倍得第二行,使得第2行第一列变为0:
    R 2 → R 2 − 3 R 1 R_2 \rightarrow R_2 - 3R_1 R2R23R1
    [ 1 2 − 3 ∣ 10 3 − 3 ∗ 1 1 − 3 ∗ 2 1 − 3 ∗ ( − 3 ) ∣ 10 − 3 ∗ ( 10 ) 1 1 − 1 ∣ 6 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ \textcolor{red}{3-3*1} & \textcolor{red}{1-3*2} & \textcolor{red}{1-3*(-3)} & | & \textcolor{red}{10 - 3*(10)} \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 1331121321313(3)110103(10)6
    得到:
    [ 1 2 − 3 ∣ 10 0 − 5 10 ∣ − 20 1 1 − 1 ∣ 6 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & -5 & 10 & | & -20 \\ 1 & 1 & -1 & | & 6 \end{bmatrix} 101251310110206

  2. 第3行:用第1行减去第3行,使得第3行第一列变为0:
    R 3 → R 3 − R 1 R_3 \rightarrow R_3 - R_1 R3R3R1
    [ 1 2 − 3 ∣ 10 0 − 5 10 ∣ − 20 1 − 1 1 − 2 − 1 − ( − 3 ) ∣ 6 − 10 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & -5 & 10 & | & -20 \\ \textcolor{red}{1-1} & \textcolor{red}{1-2} & \textcolor{red}{-1-(-3)} & | & \textcolor{red}{6 - 10} \end{bmatrix} 101125123101(3)1020610
    得到:
    [ 1 2 − 3 ∣ 10 0 − 5 10 ∣ − 20 0 − 1 2 ∣ − 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & -5 & 10 & | & -20 \\ 0 & -1 & 2 & | & -4 \end{bmatrix} 100251310210204

第四步:将第2行的主元化为1

将第2行除以-5,使得第2行的主元变为1:
R 2 → 1 − 5 R 2 R_2 \rightarrow \frac{1}{-5} R_2 R251R2
[ 1 2 − 3 ∣ 10 0 / ( − 5 ) − 5 / ( − 5 ) 10 / ( − 5 ) ∣ − 20 / ( − 5 ) 0 − 1 2 ∣ − 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ \textcolor{red}{0/(-5)} & \textcolor{red}{-5/(-5)} & \textcolor{red}{10/(-5)} & | & \textcolor{red}{-20/(-5)} \\ 0 & -1 & 2 & | & -4 \end{bmatrix} 10/(5)025/(5)1310/(5)21020/(5)4

得到:
[ 1 2 − 3 ∣ 10 0 1 − 2 ∣ 4 0 − 1 2 ∣ − 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & 1 & -2 & | & 4 \\ 0 & -1 & 2 & | & -4 \end{bmatrix} 1002113221044

第五步:消去第二列中的其他数值

  1. 第3行:用第2行加到第3行,使得第3行第二列变为0:
    R 3 → R 3 + R 2 R_3 \rightarrow R_3 + R_2 R3R3+R2
    [ 1 2 − 3 ∣ 10 0 1 − 2 ∣ 4 0 + 0 − 1 + 1 2 + ( − 2 ) ∣ − 4 + 4 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & 1 & -2 & | & 4 \\ \textcolor{red}{0+0} & \textcolor{red}{-1+1} & \textcolor{red}{2+(-2)} & | & \textcolor{red}{-4+4} \end{bmatrix} 100+0211+1322+(2)1044+4
    得到:
    [ 1 2 − 3 ∣ 10 0 1 − 2 ∣ 4 0 0 0 ∣ 0 ] \begin{bmatrix} 1 & 2 & -3 & | & 10 \\ 0 & 1 & -2 & | & 4 \\ 0 & 0 & 0 & | & 0 \end{bmatrix} 1002103201040

  2. 第1行:用第2行的2倍去减去第1行,使得第1行第二列变为0:
    R 1 → R 1 − 2 R 2 R_1 \rightarrow R_1 - 2R_2 R1R12R2
    [ 1 − 2 ∗ 0 2 − 2 ∗ 1 − 3 − 2 ∗ ( − 2 ) ∣ 10 − 2 ∗ 4 0 1 − 2 ∣ 4 0 0 0 ∣ 0 ] \begin{bmatrix} \textcolor{red}{1-2*0} & \textcolor{red}{2 - 2*1} & \textcolor{red}{-3-2*(-2)} & | & \textcolor{red}{10-2*4} \\ 0 & 1 & -2 & | & 4 \\ 0 & 0 & 0 & | & 0 \end{bmatrix} 120002211032(2)20102440
    得到:
    [ 1 0 1 ∣ 2 0 1 − 2 ∣ 4 0 0 0 ∣ 0 ] \begin{bmatrix} 1 & 0 & 1 & | & 2 \\ 0 & 1 & -2 & | & 4 \\ 0 & 0 & 0 & | & 0 \end{bmatrix} 100010120240

第六步:解释最终矩阵

矩阵现在已经是简化行最简形式。方程组变为:

x + z = 2 y − 2 z = 4 0 = 0 ( 无新信息 ) \begin{aligned} x + z &= 2 \\ y - 2z &= 4 \\ 0 &= 0 \quad (\text{无新信息}) \end{aligned} x+zy2z0=2=4=0(无新信息)

从第一个方程:
x = − z + 2 x = -z + 2 x=z+2

从第二个方程:
y = 2 z + 4 y = 2z + 4 y=2z+4

因此,解为:
x = − z + 2 , y = 2 z + 4 , z = z x = -z + 2, \quad y = 2z + 4, \quad z = z x=z+2,y=2z+4,z=z
其中, z z z 是自由变量(可以取任意值)。因此,解的形式是:

( x , y , z ) = ( − z + 2 , 2 z + 4 , z ) (x, y, z) = (-z + 2, 2z + 4, z) (x,y,z)=(z+2,2z+4,z)

这是该方程组的通解。

黑板:求解多个未知数的方程

当解决多个未知数的方程组时,首先要做的是消去项。通过消去项,可以将方程组简化为一个较为简单的形式,最终得出一个未知数的值。具体方法是,首先尽可能消除掉不需要的项,使得每个方程只包含一个未知数。接着,通过除以系数得到该未知数的解,然后可以将这个解代入其他方程中,逐步反向求解其他未知数,直到所有未知数的解都得到。

这种解决方法是通过规范化的过程实现的。其核心思想是将求解的步骤转化为一系列可以执行的规则,从而简化了实际的计算和推导过程。在数学中,这个过程是非常常见的,尤其是在处理线性方程组时,消元法和回代法是常用的技术。

总结来说,解决多元方程组的基本思路是消去多余项、简化方程,然后逐步求解每个未知数的值。

黑板:我们完全陷入了数学的深坑β

有时,可能会陷入数学的思维模式中,一旦进入这种状态,就会完全专注于数学问题,不再关注其他方面。这个过程有时会导致思维的偏离,可能会突然忘记自己原本要表达的内容。即使如此,通常还是会回到原本的话题,并且最终会再次提到自己之前的思考内容。

在数学过程中,尤其是在解决方程和矩阵问题时,重点是理解这些概念如何应用,并逐步把复杂的数学操作转化为规范的规则和步骤。最终,虽然有时会迷失在数学的深思中,但最终还是会回到解决问题的目标上,并继续推进思维的逻辑。

黑板:你可以自由地加或乘任何两条含有相同项的方程

如果要构建一个矩阵,只包含未知数的系数,可以从方程出发。假设有两个方程,分别是方程的左边和右边,表示的是未知数的关系。对于这两个方程,知道它们的左边和右边是相等的。

如果有两个方程,可以将它们加在一起,这是完全合法的操作。只要在方程的两边加上相同的量,这个等式依然成立。因为左边和右边是相等的,所以可以自由地对它们进行加法操作。这样,方程的两边仍然保持平衡。

此外,还可以将方程的两边都乘以相同的数值,这同样是合法的。比如,如果将方程的左边和右边都乘以2,依然不会改变方程的平衡,因为在两边做相同的操作,方程的本质没有变化。可以随意进行这些加法和乘法操作,只要遵循等式的规则,结果依然是有效的。

黑板:我们可以对矩阵的行列进行正则化操作

在处理矩阵时,可以通过对矩阵的行和列进行操作来规范化矩阵。通过对行进行操作,可以逐步消去矩阵中的某些项。例如,假设有一个矩阵的第一行表示系数,而我们希望通过操作第二行来消去某些元素。具体来说,如果想要消去某个元素(例如H),可以考虑如何将第一行的某个元素(例如a)调整成与H相等。为了达到这个目的,可以通过加上适当的倍数来实现消去。

这种操作通常是通过除以某个系数,计算出需要加的数值,从而使得矩阵中的特定元素变为零。这个过程的核心是通过行操作将矩阵简化,逐步消去不需要的项。

黑板:使用数字清晰演示高斯消元法

在进行矩阵操作时,通过消去特定的项,可以简化矩阵。假设有一个矩阵,如:

( 5 2 3 1 7 6 10 4 9 ) \begin{pmatrix} 5 & 2 & 3 \\ 1 & 7 & 6 \\ 10 & 4 & 9 \end{pmatrix} 5110274369

想要消去某些值,比如消去第二行和第三行的某个元素。为此,可以考虑如何通过行操作使得某个元素变为零。比如,要消去第一行的第二个元素(2),可以计算出需要多少倍的第一行元素来使得第二行中的某个值消失。具体来说,这个倍数就是第二行要减去的倍数,这个值为2。然后,可以将第一行乘以2,再与第二行进行相减,从而消去第二行中的元素。

这样处理后,原本的矩阵经过行操作后就变成了新的矩阵,其中第二行的第一个和第二个元素被消去,而第三行的最后一个元素变成了0。这个操作可能会消去多个元素,有时候可能会不小心消去不该消去的项,但这是行操作中常见的现象。

通过行操作,可以逐步消去矩阵中的元素,最终将矩阵简化到只剩下一个项。这一项对应着最后的未知数,这个过程的目的是通过消去其他项来逐步求解未知数,从而得到最终的解。如果按照这种方法进行操作,就能够逐步减少方程中的未知数,直到只剩下一个最终的解。

黑板:然后你可以将最后剩下的项除以目标数

一旦消去矩阵中的其他项,最后剩下的项可以通过目标值进行除法运算,得到最终的解。虽然有时可以进一步消去项,但并非每次都高效,因为有些操作可能需要对其他行进行调整。关键在于,当矩阵中的一些项被消去后,可以通过将最后剩下的项除以目标值来得到所需结果,最终可能得到一个单位矩阵。

整个过程中,重要的是理解如何通过行操作来简化矩阵。具体操作包括:可以将一个行的倍数加到另一个行上,或者通过乘以负数再加到另一行上,最终消去不需要的项。这些行操作可以帮助消除矩阵中的某些成员。

通过这样的行操作,问题变得更加计算机友好,因为这是一堆数字,操作相对简单,易于编程实现。这样的线性方程求解方法可以通过程序实现,比如高斯消元法(Gaussian elimination)。接下来,可以更明确地讨论如何在计算机中实现这一过程。

黑板:我们希望能够通过矩阵乘法得到单位矩阵

目标是通过高斯消元法来将一个矩阵转化为单位矩阵(1, 0, 0, 1)。要实现这一点,需要通过一系列行操作,使得矩阵的左侧部分转化为单位矩阵,同时右侧部分产生结果。在这个过程中,关键是通过高斯消元法操作对原始矩阵进行变换,使得当进行乘法运算时,能够得到最终的单位矩阵。

其中一个常见的策略是将高斯消元法应用到矩阵的同时,也操作一个初始单位矩阵。这样,当矩阵转化为单位矩阵时,右侧的矩阵就会变成原始矩阵的逆矩阵。虽然这种方法可能需要一定的技巧,但基本概念是通过一系列的行操作使得左边变成单位矩阵,右边的矩阵最终变为所需的逆矩阵。

黑板:高斯消元法的常规解法

高斯消元法(Gaussian Elimination)如何用于求解线性方程组,并逐步解释了如何通过矩阵操作来找出方程的解。主要的步骤包括:

  1. 矩阵与向量乘法:如果已知矩阵 A 和向量 X,可以通过矩阵与向量的乘法得到结果 AX。但当不知道向量 X 时,需要求解方程 AX = B

  2. 高斯消元法:高斯消元法是一种通过一系列行操作将矩阵转化为上三角矩阵的算法。这个过程可以将方程组中的未知数逐步消去,最终得到解。

  3. 消去步骤

    • 假设有一个方程组 AX = B,通过消去系数矩阵的某些元素(比如通过对行进行加减运算),可以逐步简化方程。
    • 首先,通过乘以某个系数并加到另一行,来消去某个元素。
    • 然后继续对矩阵进行行操作,直到得到一个上三角矩阵。
  4. 求解未知数:在得到上三角矩阵后,可以通过代回的方式逐步求解未知数。这个过程是从最后一行开始,逐步代入前面的行。

  5. 矩阵的逆:通过高斯消元法还可以求解矩阵的逆。实际操作中,除了求解线性方程组外,也可以在过程中同时计算矩阵的逆(通过将单位矩阵附加到原矩阵旁边进行行操作)。

  6. 注意事项:高斯消元法虽然对于小规模矩阵非常有效,但对于大规模或病态矩阵(即条件数大的矩阵),其数值稳定性较差。因此,在实际应用中,通常会采用其他更加稳定的数值方法,如迭代法。

黑板:不幸的是我们没有完全讲到逆转置

这段内容主要讲解了矩阵的逆与转置的概念,尤其是如何通过矩阵的逆来解决线性方程组的问题。

  1. 逆矩阵的定义与作用

    • 逆矩阵是指如果有一个矩阵 A,那么它的逆矩阵 A⁻¹ 满足 A * A⁻¹ = I,其中 I 是单位矩阵。逆矩阵的核心作用是,它可以帮助解决方程组,特别是通过逆矩阵来从已知的 AB 计算出未知的 X
    • 逆矩阵的应用不局限于理论,它可以用来解线性方程组。例如,对于方程 AX = B,如果已知矩阵 A 和向量 B,则可以通过乘以 A 的逆矩阵来求解 X。也就是说,X = A⁻¹ * B
  2. 方程组的解法

    • 之前的重点是如何给定 AX 来计算 B,也就是正向运算(如 AX = B)。然而,在这段内容中,转向了反向解法,即给定 AB,如何计算 X
    • 当我们知道了逆矩阵的存在后,可以通过逆矩阵将方程两边同时乘以 A⁻¹,从而求解 X。这个过程帮助解决了线性方程组中的未知数,特别是在变换坐标系时尤为重要。
  3. 坐标系的变换与逆矩阵的应用

    • 之前的例子讨论了坐标系之间的转换:给定一个坐标系中的点 P,如何通过变换矩阵 A 将其转换到另一个坐标系中。这个过程使用了类似 P' = A * P 的关系式。
    • 在这个讨论中,逆矩阵的作用是逆向操作,即给定变换后的点 P' 和变换矩阵 A,通过求解 P = A⁻¹ * P',可以将点 P' 从变换后的坐标系映射回原始坐标系。
  4. 矩阵的逆转置关系

    • 另一个重要话题是矩阵的逆转置。当矩阵的逆等于其转置时,这会有特别的意义。尽管具体的条件和应用还未深入探讨,但可以初步理解为在某些情况下,逆矩阵和转置矩阵可能具有相等的关系。
  5. 高斯消元法与逆矩阵的计算

    • 计算逆矩阵的过程会用到高斯消元法,但由于计算的复杂性,讨论没有完全展开。高斯消元法是通过行变换将矩阵简化为上三角矩阵的过程,从而帮助计算出逆矩阵。

对于反转2x2矩阵,使用简单的余子式方程非常高效

对于求解二阶矩阵的逆矩阵,一个简单的余子式(cofactor)方程是非常高效的。具体来说,二阶矩阵的逆矩阵可以通过一个简单的公式来求得,公式如下:

设矩阵 A 为:

A = [ a b c d ] A = \begin{bmatrix} a & b \\ c & d \end{bmatrix} A=[acbd]

它的逆矩阵 A⁻¹ 可以通过以下公式计算:

A − 1 = 1 a d − b c [ d − b − c a ] A^{-1} = \frac{1}{ad - bc} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} A1=adbc1[dcba]

其中,ad - bc 是矩阵 A 的行列式。如果行列式不等于零,则矩阵 A 是可逆的,逆矩阵就是上述公式中的结果。

这个方法通过使用余子式和行列式的概念来计算逆矩阵,适用于二阶矩阵。对于更高阶的矩阵,通常需要更复杂的计算方法,如高斯消元法或者行列式的展开。

消元法中的所有步骤都可以表示为一个矩阵。从M开始,乘以所有这些矩阵,得到单位矩阵。所以这些矩阵相乘就是逆矩阵。将它们全部与单位矩阵相乘就得到了逆矩阵。是这个技巧吗?

在讨论高斯消元法时,可以通过矩阵的乘法来表示每一个消元步骤,最终通过这些步骤矩阵的乘积可以得到单位矩阵。换句话说,通过这些矩阵的乘积得到的结果就是矩阵的逆。

首先,考虑高斯消元法中的一个操作。例如,假设我们有一个矩阵,目标是通过某种操作将矩阵中的元素变为零。这个操作可以通过构造一个矩阵来实现,这个矩阵在乘以原矩阵后,能产生想要的结果。具体来说,如果我们要对矩阵的某一行进行变换,例如将某行的一个元素乘以某个系数并加到另一行上,那么我们可以构造一个矩阵来实现这个变换。这个矩阵会与原矩阵相乘,产生预期的结果。

通过这种方法,可以将每一步消元操作转化为矩阵乘法,并最终得到单位矩阵。而这些操作矩阵的乘积就构成了逆矩阵。这是通过矩阵乘法实现矩阵求逆的一种方式。

然而,在实际操作中,这个过程并不容易直观理解。例如,想要通过矩阵表示某个特定的消元操作时,可能需要构造一个矩阵,它在某一行上产生特定的变换,但这个过程并不总是简单。特别是在实际构建矩阵时,可能会出现疑惑,例如如何确保在进行行变换时保持矩阵的其他部分不变,这需要深思熟虑和一些反复的推敲。

总结来说,矩阵的逆是通过逐步的行变换实现的,而每一个行变换都可以用一个矩阵来表示,最终这些矩阵的乘积给出的是逆矩阵。不过,这个过程涉及到复杂的矩阵运算,需要一定的线性代数基础来理解和实现。

为了找逆矩阵,我们难道不能通过负角度旋转并按最初缩放的倒数缩放来做吗?

在讨论矩阵的逆时,可以通过旋转负角度并按最初的缩放因子倒数进行缩放来构造逆矩阵。这种方法通常用于图形学中,因为有时直接反转矩阵比计算逆矩阵要简单。然而,这种方法只适用于已经知道矩阵的来源的情况,因为有时我们并不总是知道矩阵的构成。

如果矩阵是由缩放和旋转构成的,并且已经知道缩放因子和旋转角度,那么可以通过分别计算逆缩放矩阵和逆旋转矩阵来得到矩阵的逆。缩放矩阵是一个对角矩阵,其中对角线元素为缩放因子,其他位置为零。如果要得到逆矩阵,则缩放因子的倒数作为新矩阵的对角线元素。旋转矩阵的逆则是其转置矩阵,即旋转的逆操作。

对于旋转矩阵的逆,可以通过数学推导得出。当旋转矩阵表示的是坐标轴的旋转时,逆矩阵可以通过交换矩阵的列来得到。这是因为旋转矩阵的列向量是单位向量,并且它们是正交的。通过点积计算,可以验证转置矩阵确实是旋转矩阵的逆。

此外,逆矩阵的计算涉及到如何处理旋转和缩放的组合。对于旋转矩阵,点积可以验证旋转矩阵和其转置的关系。对于缩放矩阵,只需将对角线元素倒数,就可以得到缩放的逆。

总结来说,旋转矩阵的逆通常是其转置,而缩放矩阵的逆是通过将其对角线元素倒数来得到的。这种方法能够有效地简化矩阵求逆过程,尤其是在已知矩阵结构的情况下。

我记得我是把单位矩阵放在原始矩阵旁边,逐步对每个进行操作

讨论了矩阵求逆的过程。首先,通过理解矩阵乘以单位矩阵的性质,即矩阵与单位矩阵相乘得到原矩阵,建立了矩阵求逆的基础。接着,介绍了高斯消元法(Gaussian elimination)来将矩阵通过一系列步骤转化为单位矩阵,进而求得其逆矩阵。

具体来说,假设有一个矩阵 A A A,其乘以单位矩阵 I I I 等于自身,即 A × I = A A \times I = A A×I=A,这个过程是矩阵乘法的基本法则之一。然后,通过消去矩阵的每一项,逐步将原矩阵变为单位矩阵。在这个过程中,消元后的矩阵的另一部分就会变成矩阵 A A A 的逆矩阵。

然而,在执行这个过程时,存在一些困惑的地方。一个问题是,经过消元后,为什么最终得到的矩阵一定是正确的逆矩阵。此时需要再次仔细推导消元过程,确保每一步都符合数学原理。尽管有些部分令人感到困惑,但总体思路是通过高斯消元法将原矩阵转化为单位矩阵,从而找到其逆矩阵。

如果你有一个矩阵,比如 int[2][2],变量是abcd,难道你不能仅仅交换a和d并把c和b取负吗?

讨论了如何通过对一个 2x2 矩阵进行操作来求逆。假设矩阵是:

[ a b c d ] \begin{bmatrix} a & b \\ c & d \end{bmatrix} [acbd]

如果按照提议,交换 a a a d d d,并将 b b b c c c 取负,得到新的矩阵:

[ d − b − c a ] \begin{bmatrix} d & -b \\ -c & a \end{bmatrix} [dcba]

接下来,通过计算矩阵的行列式,即做点积,得到:

a d − ( − b ) ( − c ) = a d − b c ad - (-b)(-c) = ad - bc ad(b)(c)=adbc

然后观察到,结果 a d − b c ad - bc adbc 不等于 1,因此这并不是单位矩阵,也不能直接作为逆矩阵。为了矩阵的逆成立,行列式的值必须等于 1,否则无法得到正确的逆矩阵。

总结来说,直接交换矩阵的元素并取负并不能保证得到逆矩阵,必须通过正确的行列式计算和消元步骤来验证逆矩阵的正确性。

如果你将A和I写在一起,然后应用一堆操作,你在计算T3T2T1 A和T3T2T1 I。因为你最后得到单位矩阵,T3T2T1A = I。所以T3T2T1 = A^-1。因此T3T2T1 I = A^-1

有一种方法来计算矩阵的逆,即将矩阵 A A A 和单位矩阵 I I I 放在一起,应用一系列操作。这个方法的基本思路是,经过一系列操作(比如高斯消元),将矩阵 A A A 转换为单位矩阵 I I I。在这个过程中,对矩阵 I I I 同时应用相同的操作。最终,矩阵 A A A 变成了单位矩阵,而矩阵 I I I 变成了 A A A 的逆矩阵。

这些操作步骤可以称为 t 1 , t 2 , t 3 t_1, t_2, t_3 t1,t2,t3 等,它们代表了将矩阵 A A A 转换为单位矩阵的过程。根据这个过程,得出的结论是,操作 t 1 , t 2 , t 3 t_1, t_2, t_3 t1,t2,t3 作用于单位矩阵时,结果就是矩阵 A A A 的逆。换句话说,假设操作将 A A A 变成了单位矩阵,那么这些操作实际上也得到了矩阵 A A A 的逆,因为它们能够将单位矩阵转换为 A − 1 A^{-1} A1

这种思路通过高斯消元来说明如何得到矩阵的逆。当矩阵 A A A 被消元为单位矩阵时,相应的步骤会使单位矩阵变成 A A A 的逆。


http://www.mrgr.cn/news/90588.html

相关文章:

  • 【PyTorch项目实战】肿瘤检测:AI辅助诊断(低倍率分割淋巴结 + 高倍率分类肿瘤 + 热图计算T/MLN) + 专家审查
  • 安科瑞光伏发电防逆流解决方案——守护电网安全,提升能源效率
  • anolis os 8.9安装jenkins
  • Vue全流程--Vue3.0与Vue2.0响应式原理对比
  • Unity使用iTextSharp导出PDF-04图形
  • Vue2生命周期面试题
  • RabbitMQ使用guest登录提示:User can only log in via localhost
  • 编译和链接【四】链接详解
  • 逻辑分析仪的使用-以STM32C8T6控制SG90舵机为例
  • Linux系统调用
  • MySQL 入门大全:数据类型
  • DataBase【MySQL基础夯实使用说明(下)】
  • 浏览器网络请求全流程深度解析
  • Llama_Index核心组件介绍
  • 【设计模式】【行为型模式】状态模式(State)
  • Redis7.0八种数据结构底层原理
  • Spring Boot + ShardingSphere 踩坑记
  • 前缀树算法篇:前缀信息的巧妙获取
  • 动态规划LeetCode-416.分割等和子集
  • 动态规划LeetCode-1049.最后一块石头的重量Ⅱ
  • 计算机网络和操作系统常见面试题目(带脑图,做了延伸以防面试官深入提问)
  • 小白零基础如何搭建CNN
  • UGUI Canvas为Overlay模式下的UI元素的position和localPosition
  • 【Matlab算法】基于人工势场的多机器人协同运动与避障算法研究(附MATLAB完整代码)
  • C++病毒(^_^|)(2)
  • 变化检测相关论文可读list