Algorithm 算法:如何计算双线性插值的逆?映射到任意四边形的逆?

Algorithm 算法:如何计算双线性插值的逆?映射到任意四边形的逆?,algorithm,interpolation,Algorithm,Interpolation,更新:我下面的术语是错误的。我在“Lerp2D”中描述的“正向”算法(我需要它的逆)具有4个任意角点。它沿每条边呈线性,但所有4条边都可以独立拉伸;它不是双线性的 我在标题中留下了双线性-如果您来这里寻找“双线性的逆”,例如x和y中的独立拉伸,请参阅 如果您需要更一般的情况(由任意四边形定义的拉伸),请参阅公认的答案 也可以在对这个问题的评论中看到人们给出的链接 原始问题: 双线性插值计算起来很简单。 但我需要一个做逆运算的算法。 (算法在伪代码或任何广泛使用的计算机语言中对我很有用) 例如,

更新:我下面的术语是错误的。我在“Lerp2D”中描述的“正向”算法(我需要它的逆)具有4个任意角点。它沿每条边呈线性,但所有4条边都可以独立拉伸;它不是双线性的

我在标题中留下了双线性-如果您来这里寻找“双线性的逆”,例如
x
y
中的独立拉伸,请参阅

如果您需要更一般的情况(由任意四边形定义的拉伸),请参阅公认的答案

也可以在对这个问题的评论中看到人们给出的链接


原始问题:

双线性插值计算起来很简单。 但我需要一个做逆运算的算法。 (算法在伪代码或任何广泛使用的计算机语言中对我很有用)

例如,这里是双线性插值的VisualBasic实现

' 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
在哪里


在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

定义双线性插值的逆。

你的代码对我来说不是很可读(不是一个VB程序员),可能是一些关于主要思想的附加文本会更好,但是从你的代码中,你返回了一些权重。在我看来,它是这样的:

双线性插值是二维图像/矩阵大小调整

  • 输入为二维图像/xs0、ys0分辨率矩阵和新分辨率矩阵xs1、ys1
  • 输出为分辨率为xs1、ys1的二维图像矩阵

反向双线性插值从调整大小的图像中获取原始2D图像/矩阵。只有当
(xs0要简化,让我们先考虑一个内插值z.
假设四个值z00、z01、z10、z10和两个权重w0和w1应用于第一个和第二个索引,给出

z0=z00+w0×(z10-z00)
z1=z01+w0×(z11-z01)

最后

z=z0+w1×(z1-z0)
=z00+w0×(z10-z00)+w1×(z01-z00)+w1×w0×(z11-z10-z01+z00)

所以,对于你的问题,你必须把一个二维二次方程倒过来

x=x00+w0×(x10-x00)+w1×(x01-x00)+w1×w0×(x11-x10-x01+x00)
y=y00+w0×(y10-y00)+w1×(y01-y00)+w1×w0×(y11-y10-y01+y00)

不幸的是,没有一个简单的公式可以从x和y中恢复w0和w1。但是,您可以将其视为非线性最小二乘问题并最小化

(xw(w0,w1)-x)2+(yw(w0,w1)-y)2

你们可以有效地利用这个

编辑:进一步思考

我突然想到,你可能会对从(x,y)到(w0,w1)的插值而不是实际的倒数感到满意。从这个意义上说,rev(fwd(w0,w1))可能比实际的倒数离(w0,w1)更远,这就不太准确了

在不规则网格上而不是在规则网格上插值的事实将使这成为一个更棘手的命题。理想情况下,您应该将(x,y)点与非重叠三角形连接起来,并使用它们进行线性插值。
对于数值稳定性,您应该避免使用浅的尖三角形。幸运的是,可以满足这一要求,并且在二维中构造也不太困难

如果希望反向插值采用与正向插值类似的形式,可以使用

1
x
y
x×y

并计算系数ai、bi、ci和di(i等于0或1),以便

w0=a0+b0×x+c0×y+d0×x×y
w1=a1+b1×x+c1×y+d1×x×y

通过替换x、y、w0和w1的相关已知值,您将得到每个w的四个联立线性方程组,您可以求解它们的系数。
理想情况下,您应该使用数值稳定的矩阵求逆算法,该算法可以处理近似奇异的矩阵(例如),但如果您小心,您可能会侥幸逃脱


对不起,我不能给你任何更简单的选择,但我担心这真的是一个相当棘手的问题!

Hmm,我认为解决方案是解决两个未知量的两个线性方程组。调查。最近没有这样做,所以我对细节很生疏。我没有数学包可调用,因此需要为t编写代码细节他的具体案例。另请参见和@Phrogz:Thank-这些正是我所需要的链接,但我在搜索中不知何故未能找到(当我开始研究这个问题时,我可能没有正确的术语;我看到“反向双线性插值”确实产生了这两个链接)查看程序图形大师Iñigo Quilez的文章。如何获得6个未知数(z00、z01、z10、z11、w0、w1)从2方程组?你还需要使用相邻点…顺便说一句,如果原始分辨率和偏移量已知,可以计算w0和w1,但这仍然比可计算的多出2个uknowns…@Spektre:z项纯粹用于推导双线性插值的一般公式。用x替换它们以获得fo得到y的公式。谢谢,这是我需要知道的。首先,我知道我没有忽略一些明显的东西,这实际上比插值要复杂得多,因为它是一个逆插值。仅供参考,在我的情况下,失真离线性不太远:而不是做一个最小化,或co在构造三角形网格时,我能够使用我更熟悉的猜测/迭代技术进行求解。我非常感谢您的数学知识和相关主题的指导,以防我将来需要更稳健的方法。以及
' 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
' 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