更新: 我下面使用的术语是错误的。我在“Lerp2D”中描述的“forward”算法(我需要它的反向操作)需要4个任意角落。它沿着每条边线性,但所有4条边缘都可以独立拉伸; 它不是双线性的。
我将双线性保留在标题中 - 如果您在寻找“双线性的反向操作”,例如在x
和y
中进行独立拉伸,请参见Spektre的答案。
如果您需要更一般的情况(由任意四边形定义的拉伸),请参见被接受的答案。
还请查看人们在此问题评论中提供的链接。
原始问题:
双线性插值很容易计算。但我需要一个执行反向操作的算法。 (算法对我来说在伪代码或任何广泛使用的计算机语言中都很有用)
例如,这里是双线性插值的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
where
' 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
在一维情况下,我已经确定了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