帮助理解这些方程?

jma*_*erx 0 c c++ algorithm vector-graphics

我问了一个关于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
Run Code Online (Sandbox Code Playgroud)

术语"双线性"来自这些方程中的每一个,它们在任一输入坐标中都是线性的.我们想要求出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
Run Code Online (Sandbox Code Playgroud)

对于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
Run Code Online (Sandbox Code Playgroud)

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


问题是,我有input_x和input_y以及r1,r2,r3,r4,但我不知道如何实现output_x和output_y.我如何解决这样的等式?我只熟悉用2个变量求解方程.

谢谢

Jas*_*ams 5

这是你发现的一个可怕的解释.希望我能帮助您了解发动机罩下发生的事情.

你想要做的是将一个矩形区域(一个四边形)映射到另一个(任意形状)四边形.让我们从一个更简单的案例开始:线性插值(找到沿着一条线的值)

如果你有一条从a到b的线,那么你可以使用这个等式在该线上找到任何一个'c'点:

c = ((1 - p) * a) + (p * b);
Run Code Online (Sandbox Code Playgroud)

这将两个位置的值"混合"(插值)在它们之间的直线上(线性地).如果你使用p = 0那么等式就变成了

c = (1 * a) + (0 * b)   = a
Run Code Online (Sandbox Code Playgroud)

所以在p = 0时,等式给出了'a'点.

当p = 1时,等式变为:

c = (0 * a) + (1 * b)   = b
Run Code Online (Sandbox Code Playgroud)

所以在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));
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

为了进行上述映射,我们简单地在两个维度上进行线性插值计算:首先我们沿着底部和顶部进行插值,以找到垂直穿过矩形中间的直线的两个端点.然后我们沿着这条垂直线进行插值,找到矩形中间的最终点.

"矩形"不需要是矩形.这两个尺寸可用于任何4面形状(即您可以将矩形的角移动到任何您喜欢的位置,方程式仍然可以找到角之间的位置以填充形状所包围的区域)

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

此外,他们通过求解方程以填充变换矩阵使得计算更有效,该变换矩阵可以与点相乘以进行映射过程.但是,效果与我上面描述的相同.希望我的解释能让你更容易"看到"方程式的作用.