0

我问了一个关于 Bi 线性变换的问题并得到了这个答案:

在您发布的那个页面上,有一个指向源代码的链接。我将解释双线性变换

http://www.antigrain.com/__code/include/agg_trans_bilinear.h.html

这里的想法是找到形式的转换:

output_x = a * input_x + b * input_x * input_y + c * input_y + d
output_y = e * input_x + f * input_x * input_y + g * input_y + h

术语“双线性”来自这些方程中的每一个,它们本身在任一输入坐标中都是线性的。我们要求解 a、b、c 和 d 的正确值。假设您有要映射到 (0,0)、(1,0)、(0,1)、(1,1) (或某些图像坐标系)的参考矩形 r1、r2、r3、r4。

对于 a、b、c、d:

0 = a * r1_x + b * r1_x * r1_y + c * r1_y + d
1 = a * r2_x + b * r2_x * r2_y + c * r2_y + d
0 = a * r3_x + b * r3_x * r3_y + c * r3_y + d
1 = a * r4_x + b * r4_x * r4_y + c * r4_y + d

对于 e,f,g,h:

0 = e * r1_x + f * r1_x * r1_y + g * r1_y + h
0 = e * r2_x + f * r2_x * r2_y + g * r2_y + h
1 = e * r3_x + f * r3_x * r3_y + g * r3_y + h
1 = e * r4_x + f * r4_x * r4_y + g * r4_y + h

你可以用你最喜欢的方式解决这个问题。(如果你熟悉矩阵符号,这是两个矩阵相同的矩阵方程,然后你只需要找到一次LU分解,并求解两个未知向量)。然后应用系数将矩形的内部映射到矩形中的位置。


问题是,我有 input_x 和 input_y 以及 r1、r2、r3、r4,但我不确定如何实现 output_x 和 output_y。我该如何求解这样的方程?我只熟悉用 2 个变量求解方程。

谢谢

4

2 回答 2

5

这是你找到的一个可怕的解释。希望我能帮助您了解引擎盖下发生的事情。

您要做的是将矩形区域(一个四边形)映射到另一个(任意形状)四边形。让我们从一个更简单的情况开始:线性插值(查找沿线的

如果您有一条从 a 到 b 的线,那么您可以使用以下等式找到该线上的任何点“c”:

c = ((1 - p) * a) + (p * b);

这“混合”(内插)两个位置沿它们之间的直线(线性)的值。如果你使用 p=0 那么等式变成

c = (1 * a) + (0 * b)   = a

所以在 p=0 时,方程给出了点“a”。

当 p=1 时,方程变为:

c = (0 * a) + (1 * b)   = b

所以在 p=1 时,等式给出了点“b”。

在 p 的中间值处,您会在 a 和 b 之间的线上得到点。(所以在 p=0.5 时,你得到的点正好在 a 和 b 的中间)

因此,要将像素从屏幕上的一行复制到屏幕上的另一行,我们可以使用线性插值来找到要读取和写入的行上的位置。

for (float p = 0.0; p <= 1.0; p += 0.1)    // copy 10 pixels from line 1 to line 2
    DrawPixelOnLine2(p, GetPixelFromLine1(p));

这两种方法只使用线性插值来计算读取和绘制像素的正确位置,如下所示:

int ax = 0, ay = 100, bx = 50, by = 170;   // line a-b goes from (0,100) to (50,170)

int px = ((1-p) * ax) + (p * bx);          // calc the x and y values separately
int py = ((1-p) * ay) + (p * by);

(请注意,我必须使用两次计算来执行 2D 位置。我可以通过简单地为 z/bz/pz 坐标再次添加相同的计算来在 3D 中插值)

因此,现在您可以将任意一条直线上的点复制到另一条直线上。

双线性插值是完全一样的,只是我们想在一个矩形内而不是在一条直线内找到一个点,所以我们需要两个维度来描述该点在矩形中的位置(沿矩形底部的px,和py在矩形的一侧)。现在您可以使用 (px,py) 坐标对定位矩形中的任何点。

要进行上述映射,我们只需在二维中进行线性插值计算:首先我们沿底部和顶部进行插值,以找到垂直通过矩形中间的直线的两个端点。然后我们沿着这条垂直线进行插值以找到矩形中间的最终点。

“矩形”不需要是矩形的。这两个维度可用于任何 4 边形状(即,您可以将矩形的角移动到任何您喜欢的位置,方程仍会找到角之间的位置以填充形状所包围的区域)

在您找到的示例中,作者使用四个点来描述源形状 (a,b,c,d) 和另外四个点来描述目标形状 (e,f,g,h)

此外,他们通过求解方程来填充变换矩阵,使计算更加高效,该变换矩阵可以与点相乘以进行映射过程。但是,效果与我上面描述的相同。希望我的解释能让你更容易“看到”方程式在做什么。

于 2010-07-18T06:31:06.110 回答
0

如果要将矩形映射到另一个矩形,则需要简单的线性变换。要将点 r 映射到点 q,您有:

qx = a rx + b ry + c
qy = d rx + e ry + f

有 6 个变量,你需要 6 个方程(3 分)。要将矩形 r 映射到矩形 q:

q1x = a*r1x + b*r1y + c
q1y = d*r1x + e*r1y + f
q2x = a*r2x + b*r2y + c
q2y = d*r2x + e*r2y + f
q3x = a*r3x + b*r3y + c
q3y = d*r3x + e*r3y + f

从上面你必须解决 3 个线性方程组的 2 个系统,每个方程组有 3 个变量。只要点不同且不共线,它们将恰好有 1 个解决方案(在矩形角的情况下,这已实现)。

于 2010-07-18T07:32:46.910 回答