更新: 我下面的术语是错误的。我在“ Lerp2D”中描述的“正向”算法(我需要逆运算)需要四个任意角。它沿着每个边都是线性的,但是 所有 4个 边_都可以独立拉伸。它 _不是双线性的 。
我已经在标题中保留了双线性-如果您来这里是寻找“双线性的逆”,例如in x和中的独立拉伸y。
x
y
如果需要更一般的情况(由任意四边形定义拉伸),请参见接受的答案。
在此问题的评论中,另请参阅人们给出的链接。
原始问题:
双线性插值的计算很简单。但是我需要一种执行逆运算的算法。(算法对我来说可以是伪代码或任何广泛使用的计算机语言)
例如,这是双线性插值的Visual Basic实现。
' xyWgt ranges (0..1) in x and y. (0,0) will return X0Y0, (0,1) will return X0Y1, etc. ' For example, if xyWgt is relative location within an image, ' and the XnYn values are GPS coords at the 4 corners of the image, ' The result is GPS coord corresponding to xyWgt. ' E.g. given (0.5, 0.5), the result will be the GPS coord at center of image. Public Function Lerp2D(xyWgt As Point2D, X0Y0 As Point2D, X1Y0 As Point2D, X0Y1 As Point2D, X1Y1 As Point2D) As Point2D Dim xY0 As Point2D = Lerp(X0Y0, X1Y0, xyWgt.X) Dim xY1 As Point2D = Lerp(X0Y1, X1Y1, xyWgt.X) Dim xy As Point2D = Lerp(xY0, xY1, xyWgt.Y) Return xy End Function
哪里
' Weighted Average of two points. Public Function Lerp(ByVal a As Point2D, ByVal b As Point2D, ByVal wgtB As Double) As Point2D Return New Point2D(Lerp(a.X, b.X, wgtB), Lerp(a.Y, b.Y, wgtB)) End Function
和
' Weighted Average of two numbers. ' When wgtB==0, returns a, when wgtB==1, returns b. ' Implicitly, wgtA = 1 - wgtB. That is, the weights are normalized. Public Function Lerp(ByVal a As Double, ByVal b As Double, ByVal wgtB As Double) As Double Return a + (wgtB * (b - a)) End Function
在1-D中,我确定了Lerp的反函数:
' Calculate wgtB that would return result, if did Lerp(a, b, wgtB). ' That is, where result is, w.r.t. a and b. ' < 0 is before a, > 1 is after b. Public Function WgtFromResult(ByVal a As Double, ByVal b As Double, ByVal result As Double) As Double Dim denominator As Double = b - a If Math.Abs(denominator) < 0.00000001 Then ' Avoid divide-by-zero (a & b are nearly equal). If Math.Abs(result - a) < 0.00000001 Then ' Result is close to a (but also to b): Give simplest answer: average them. Return 0.5 End If ' Cannot compute. Return Double.NaN End If ' result = a + (wgt * (b - a)) => ' wgt * (b - a) = (result - a) => Dim wgt As Double = (result - a) / denominator 'Dim verify As Double = Lerp(a, b, wgt) 'If Not NearlyEqual(result, verify) Then ' Dim test = 0 ' test 'End If Return wgt End Function
现在,我需要在二维中执行相同的操作:
' Returns xyWgt, which if given to Lerp2D, would return this "xy". ' So if xy = X0Y0, will return (0, 0). if xy = X1Y0, will return (1, 0), etc. ' For example, if 4 corners are GPS coordinates in corners of an image, ' and pass in a GPS coordinate, ' returns relative location within the image. Public Function InverseLerp2D(xy As Point2D, X0Y0 As Point2D, X1Y0 As Point2D, X0Y1 As Point2D, X1Y1 As Point2D) As Point2D ' TODO ???? End Function
为了简化,让我们从仅考虑单个内插值 z开始 。 假设四个值 z 00, z 01, z 10, z 10和两个权重 w 0和 w 1应用于第一和第二索引,得出
z 0 = z 00 + w 0 ×( z 10 - z 00) z 1 = z 01 + w 0 ×( z 11 - z 01)
最后
z = z 0 + w 1 ×( z 1 - z 0) = z 00 + w 0 ×( z 10 - z 00)+ w 1 ×( z 01 - z 00)+ w 1 × w 0 ×( z 11 - ž 10 - ž 01 + ž 00)
因此,对于您的问题,您将必须逆转二维二次方程
x = x 00 + w 0 ×( x 10 - x 00)+ w 1 ×( x 01 - x 00)+ w 1 × w 0 ×( x 11 - x 10 - x 01 + x 00) y = y 00 + w 0 ×( y 10 - y 00)+ w 1×( y 01 - y 00)+ w 1 × w 0 ×( y 11 - y 10 - y 01 + y 00)
不幸的是,没有一个简单的公式可以从 x 和 y 恢复 w 0和 w 1。但是,您可以将其视为非线性最小二乘问题并最小化
( x w( w 0, w 1) -x )2 +( y w( w 0, w 1) -y )2
您可以使用Levenberg- Marquardt算法高效地执行此操作。
编辑 :进一步的想法
在我看来,您可能会对从( x , y )到( w 0, w 1)的插值感到满意,而不是实际的逆。从rev(fwd( w 0, w 1))可能比( w 0, w 1)更远的地方开始,这会比实际的倒数更不准确。
您在不规则网格而不是规则网格上进行插值的事实将使这一点变得更加棘手。理想情况下,您应该将( x , y )点与不重叠的三角形连接起来,并使用重心坐标进行线性插值。 为了保持数值稳定性,应避免使用浅而尖的三角形。幸运的是,Delaunay三角剖分满足了这一要求,并且在二维中构造也不是 太 困难。
如果您希望反向插值采用与正向插值类似的形式,则可以使用基函数
1 x y x × y
并计算系数 a i , b i , c i 和 d i ( i 等于0或1),使得
w 0 = a 0 + b 0 × x + c 0 × y + d 0 × x × y w 1 = a 1 + b 1 × x + c 1 × y + d 1 × x × y
通过代入相关的已知值 x , y , w 0和 w 1,您将为每个 w 获得四个联立的 线性 方程,您可以求解这些 线性 方程,以获取其系数。 理想情况下,您应该使用数值稳定的矩阵求逆算法,该算法可以处理接近奇异的矩阵(例如SVD),但是如果小心一点,您 也许 可以摆脱高斯消除。
抱歉,我无法给您提供任何更简单的选择,但恐怕这确实是一个相当棘手的问题!