编程仿射参数
Programming Affine Parameters
我在一个制作图像解释软件的团队中。
我已经制作了一个真实世界的距离测量系统,对于给定的平面来说相当准确(与现实生活有 ~0.3% 的差异),但是当我问我的高级同事我如何才能使它在现实世界中准确时,他告诉我需要计算仿射参数。
我问了更多细节,但我不确定他是否完全知道,不管怎样,他没有和我谈更多细节。在和几个不同的人谈过之后,我确信这就是我需要做的。
我已经尝试阅读很多关于仿射变换如何工作的文章,但矩阵数学对我来说一直是一个很大的弱点,而且自从我的微积分 3 类 以来已经太久了。有人能帮我理解你是如何用面向对象的逻辑计算仿射变换的吗?因为当我发现所有这些文章开始在他们的方程式中包含 nabla 和矩阵等时(对我来说是希腊语),我发现这些文章都让我头疼。我可以学习如何使用这些东西(我假设我需要),但这一切对我来说似乎非常复杂。帮助理解这个主题将不胜感激。
我不知道它是否有帮助,但我正在用 C# 编程,并从用户在图像上输入的四边形的边和对角线的 6 个测量值开始。
我将只提供一些一般信息,因为需要有关您的特定问题的更多信息才能提供更具体的建议。此外,我不会详细介绍矩阵乘法或如何构造表示旋转的矩阵等,因为我确信无论您使用何种语言(即 C#)都会有一个库来处理这些.
3x3 矩阵和 space
中的旋转
在这种情况下,在选择原点和坐标系后,我们将用 3 维向量表示 space 中的点;例如,(0, 0, 0) 表示原点,(1, 0, 0) 表示在正 x 方向上距离原点 1 个单位的点。
现在想象一下绕 y 轴旋转 90 度。 (1, 0, 0) 会移动到 (0, 0, -1),而 (0, 1, 0) 不会移动。原来有一个矩阵代表这个旋转,即
0 0 1
0 1 0
-1 0 0
这意味着如果你将这个矩阵乘以一个向量,你将得到旋转向量的结果(例如乘以 (1, 0, 0) 得到 (0, 0, -1),然后乘以通过 (0, 1, 0) 给出 (0, 1, 0)).
您的矩阵库将有一个函数 MultiplyMatrixVector(或类似名称)来执行此操作,以及一个函数 RotationY(或类似名称)来构造表示绕 y 轴旋转给定角度的矩阵。它可能会通过从矩阵的行 [0, 0, 1, 0, 1, 0, -1, 0, 0] 中读取的 9 个数字的数组来表示矩阵(或者可能从列中读取,[0 , 0, -1, 0, 1, 0, 1, 0, 0]; 你会从文档或反复试验中找出哪个)。
用矩阵表示旋转的一个好处是,如果你想依次做几个旋转,只需要将相应的矩阵相乘即可。同样,您的库将具有类似 MultiplyMatrices 的函数来执行此操作。请注意,通常结果取决于旋转的顺序。再次检查库文档以了解当您使用 MultiplyMatrices(A, B) 时先发生哪个旋转。
在实践中,要回答像 "If I rotate 30 degrees around the y-axis, then 60 degrees around the z-axis, what happens to the point (2, 3, 4)?" 这样的问题,您可以这样做:
Ry = RotationY(30);
Rz = RotationZ(60);
R = MultiplyMatrices(Rz, Ry);
result = MultiplyMatrixVector(R, Vector3D(2, 3, 4));
4x4 矩阵和仿射变换
下一部分看起来很奇怪,但我们稍后会看到它的用处:我们将用 4 维向量表示 space 中的点。给定 3D 中的一个点,例如 (2, 3, 4),我们可以通过在末尾添加一个 1 来获得一个 4D 向量,即 (2, 3, 4, 1)。相反,4D 向量 (x, y, z, w) 表示 3D 中的点 (x/w、y/w、z/w)。请注意,(2, 3, 4, 1) 和 (4, 6, 8, 2) 在 3D 中都表示相同的点 (2, 3, 4)。
现在我们将使用 4x4 矩阵来表示转换。我们可以使用之前讨论的所有 3x3 旋转矩阵,方法是按照以下模式将它们拟合到 4x4 矩阵中:
* * * 0
* * * 0
* * * 0
0 0 0 1
比如上面的y轴旋转现在表示为
0 0 1 0
0 1 0 0
-1 0 0 0
0 0 0 1
和以前一样,我们使用 MultiplyMatrixVector 对一个点应用变换,并使用 MultiplyMatrices 按顺序进行变换。为什么 4D 向量有用?我们可以代表一些新的转变。例如,在 x 轴方向平移 1 个单位(平移)表示为
1 0 0 1
0 1 0 0
0 0 1 0
0 0 0 1
更重要的是我们可以表示一个投影。想象一下,您的眼睛位于原点,并且您正在 z=1 的平面中通过视口观看。 3D 中的每个点都投影到视口平面中的某个点。它可以通过应用矩阵
来计算
1 0 0 0
0 1 0 0
0 0 0 1
0 0 1 0
然后删除 z 坐标。例如,考虑点 p = (2, 3, 4),由 4D 向量 (2, 3, 4, 1) 表示。应用矩阵得到 (2, 3, 1, 4),表示 3D 点 (2/4, 3/4, 1/4)。放下 z 坐标,p 投影到平面中的 (2/4, 3/4)。这模拟了相机如何将 3D space 中的点映射到 2D 图像中的点。
投影可以更简单地描述为没有矩阵 - 它只是将 (x, y, z) 发送到 (x/z, y/z)。使用矩阵的优点是它可以很容易地与其他变换相结合。例如,如果相机不位于原点或指向 z 方向,您可以通过乘以一些旋转和平移矩阵来解决这个问题(再次注意以正确的顺序排列它们)。
我在一个制作图像解释软件的团队中。
我已经制作了一个真实世界的距离测量系统,对于给定的平面来说相当准确(与现实生活有 ~0.3% 的差异),但是当我问我的高级同事我如何才能使它在现实世界中准确时,他告诉我需要计算仿射参数。 我问了更多细节,但我不确定他是否完全知道,不管怎样,他没有和我谈更多细节。在和几个不同的人谈过之后,我确信这就是我需要做的。
我已经尝试阅读很多关于仿射变换如何工作的文章,但矩阵数学对我来说一直是一个很大的弱点,而且自从我的微积分 3 类 以来已经太久了。有人能帮我理解你是如何用面向对象的逻辑计算仿射变换的吗?因为当我发现所有这些文章开始在他们的方程式中包含 nabla 和矩阵等时(对我来说是希腊语),我发现这些文章都让我头疼。我可以学习如何使用这些东西(我假设我需要),但这一切对我来说似乎非常复杂。帮助理解这个主题将不胜感激。
我不知道它是否有帮助,但我正在用 C# 编程,并从用户在图像上输入的四边形的边和对角线的 6 个测量值开始。
我将只提供一些一般信息,因为需要有关您的特定问题的更多信息才能提供更具体的建议。此外,我不会详细介绍矩阵乘法或如何构造表示旋转的矩阵等,因为我确信无论您使用何种语言(即 C#)都会有一个库来处理这些.
3x3 矩阵和 space
中的旋转在这种情况下,在选择原点和坐标系后,我们将用 3 维向量表示 space 中的点;例如,(0, 0, 0) 表示原点,(1, 0, 0) 表示在正 x 方向上距离原点 1 个单位的点。
现在想象一下绕 y 轴旋转 90 度。 (1, 0, 0) 会移动到 (0, 0, -1),而 (0, 1, 0) 不会移动。原来有一个矩阵代表这个旋转,即
0 0 1
0 1 0
-1 0 0
这意味着如果你将这个矩阵乘以一个向量,你将得到旋转向量的结果(例如乘以 (1, 0, 0) 得到 (0, 0, -1),然后乘以通过 (0, 1, 0) 给出 (0, 1, 0)).
您的矩阵库将有一个函数 MultiplyMatrixVector(或类似名称)来执行此操作,以及一个函数 RotationY(或类似名称)来构造表示绕 y 轴旋转给定角度的矩阵。它可能会通过从矩阵的行 [0, 0, 1, 0, 1, 0, -1, 0, 0] 中读取的 9 个数字的数组来表示矩阵(或者可能从列中读取,[0 , 0, -1, 0, 1, 0, 1, 0, 0]; 你会从文档或反复试验中找出哪个)。
用矩阵表示旋转的一个好处是,如果你想依次做几个旋转,只需要将相应的矩阵相乘即可。同样,您的库将具有类似 MultiplyMatrices 的函数来执行此操作。请注意,通常结果取决于旋转的顺序。再次检查库文档以了解当您使用 MultiplyMatrices(A, B) 时先发生哪个旋转。
在实践中,要回答像 "If I rotate 30 degrees around the y-axis, then 60 degrees around the z-axis, what happens to the point (2, 3, 4)?" 这样的问题,您可以这样做:
Ry = RotationY(30);
Rz = RotationZ(60);
R = MultiplyMatrices(Rz, Ry);
result = MultiplyMatrixVector(R, Vector3D(2, 3, 4));
4x4 矩阵和仿射变换
下一部分看起来很奇怪,但我们稍后会看到它的用处:我们将用 4 维向量表示 space 中的点。给定 3D 中的一个点,例如 (2, 3, 4),我们可以通过在末尾添加一个 1 来获得一个 4D 向量,即 (2, 3, 4, 1)。相反,4D 向量 (x, y, z, w) 表示 3D 中的点 (x/w、y/w、z/w)。请注意,(2, 3, 4, 1) 和 (4, 6, 8, 2) 在 3D 中都表示相同的点 (2, 3, 4)。
现在我们将使用 4x4 矩阵来表示转换。我们可以使用之前讨论的所有 3x3 旋转矩阵,方法是按照以下模式将它们拟合到 4x4 矩阵中:
* * * 0
* * * 0
* * * 0
0 0 0 1
比如上面的y轴旋转现在表示为
0 0 1 0
0 1 0 0
-1 0 0 0
0 0 0 1
和以前一样,我们使用 MultiplyMatrixVector 对一个点应用变换,并使用 MultiplyMatrices 按顺序进行变换。为什么 4D 向量有用?我们可以代表一些新的转变。例如,在 x 轴方向平移 1 个单位(平移)表示为
1 0 0 1
0 1 0 0
0 0 1 0
0 0 0 1
更重要的是我们可以表示一个投影。想象一下,您的眼睛位于原点,并且您正在 z=1 的平面中通过视口观看。 3D 中的每个点都投影到视口平面中的某个点。它可以通过应用矩阵
来计算1 0 0 0
0 1 0 0
0 0 0 1
0 0 1 0
然后删除 z 坐标。例如,考虑点 p = (2, 3, 4),由 4D 向量 (2, 3, 4, 1) 表示。应用矩阵得到 (2, 3, 1, 4),表示 3D 点 (2/4, 3/4, 1/4)。放下 z 坐标,p 投影到平面中的 (2/4, 3/4)。这模拟了相机如何将 3D space 中的点映射到 2D 图像中的点。
投影可以更简单地描述为没有矩阵 - 它只是将 (x, y, z) 发送到 (x/z, y/z)。使用矩阵的优点是它可以很容易地与其他变换相结合。例如,如果相机不位于原点或指向 z 方向,您可以通过乘以一些旋转和平移矩阵来解决这个问题(再次注意以正确的顺序排列它们)。