三线性插值使用立方体顶点处的值来近似立方体内点 (x, y, z) 的值。我正在尝试做一个“逆”三线性插值。知道立方体顶点的值和附加到点的值如何找到(x,y,z)?任何帮助将不胜感激。谢谢!
5 回答
给定 1 个数据,您正在求解 3 个未知数,并且当您使用线性插值时,您的答案通常是一个平面(2 个自由变量)。根据立方体的不同,可能没有解或 3D 解空间。
我会做以下事情。设 v 为初始值。对于立方体的 12 条边(相邻顶点对)中的每条“边”,查看是否有 1 个顶点 >=v 且另一个 <=v - 称其为穿过 v 的边。
如果没有边与 v 相交,则没有可能的解决方案。
否则,对于穿过 v 的每条边,如果边的两个顶点都等于 v,则整条边都是一个解。否则,在边缘上线性插值以找到值为 v 的点。因此假设边缘是 (x1, y1, z1)->v1 <= v <= (x2, y2, z2)->v2。
s = (v-v1)/(v2-v1)
(x,y,z) = (s*(x2-x1)+x1, (s*(y2-y1)+y1, s*(z2-z1)+z1)
这将为您提供等于 v 的所有边缘点。这是一个解决方案,但您可能需要一个内部解决方案 - 请注意,如果有内部解决方案,总会有一个边缘解决方案。
如果您想要一个内部解决方案,那么只需在边缘解决方案之间线性取任意点 - 因为您是线性插值,那么结果也将是 v。
我不确定您是否可以适用于所有情况。例如,对每个点的每种颜色 (C) 相同的颜色使用三线性过滤意味着无论您在哪里插值,您仍然会得到返回的颜色 C。在这种情况下,任何 x,y,z 都可能是有效的。因此,不可能确切地说出初始插值值是多少。
我敢肯定,在某些情况下,您可以反转数学运算,但我想,在很多情况下,如果不了解更多输入信息,这是不可能做到的。
祝你好运,我希望有人会证明我错了:)
您描述的问题有些不明确。
你所要求的基本上可以转化为:我有一个 3D 函数,我知道它在 8 个已知点中的值。我想知道函数接收值 V 的点是什么。
问题在于,很可能有无数这样的点构成一组曲面、线或点,具体取决于数据。
找到该集合的一种方法是使用等曲面算法,例如Marching cubes。
三线性插值的维基百科页面有一个 NASA 页面的链接,据称该页面描述了反演过程 - 你看过吗?
让我们从 2d 开始:想象一平方公里的双线性山丘,高度为 0 10 20 30 在 4 个角处,水平面在高度 z 处切割山丘。从 0 角到 30 角画一条线(无论是相邻还是对角线)。对于任何 z,平面必须切割这条线,所以所有点 x,y,z 都落在这条线上,对吗?唔。
好的,有很多解决方案——任何 z 平面都以等高线曲线切割山丘。假设我们希望解决方案遍布整个山丘,即一次最小化两件事:
- 垂直距离 z - bilin(x,y),
- 从 x,y 到正方形中某个点的距离。
Scipy.optimize.leastsq 是这样做的一种方式,示例代码如下;三线类似。
(同时优化任何两件事需要任意权衡或加权:食物与金钱,工作与娱乐......参见有限理性 )
""" find x,y so bilin(x,y) ~ z and x,y near the middle """
from __future__ import division
import numpy as np
from scipy.optimize import leastsq
zmax = 30
corners = [ 0, 10, 20, zmax ]
midweight = 10
def bilin( x, y ):
""" bilinear interpolate
in: corners at 0 0 0 1 1 0 1 1 in that order (binary)
see wikipedia Bilinear_interpolation ff.
"""
z00,z01,z10,z11 = corners # 0 .. 1
return (z00 * (1-x) * (1-y)
+ z01 * (1-x) * y
+ z10 * x * (1-y)
+ z11 * x * y)
vecs = np.array([ (x, y) for x in (.25, .5, .75) for y in (.25, .5, .75) ])
def nearvec( x, vecs ):
""" -> (min, nearest vec) """
t = (np.inf,)
for v in vecs:
n = np.linalg.norm( x - v )
if n < t[0]: t = (n, v)
return t
def lsqmin( xy ): # z, corners
x,y = xy
near = nearvec( np.array(xy), vecs )[0] * midweight
return (z - bilin( x, y ), near )
# i.e. find x,y so both bilin(x,y) ~ z and x,y near a point in vecs
#...............................................................................
if __name__ == "__main__":
import sys
ftol = .1
maxfev = 10
exec "\n".join( sys.argv[1:] ) # ftol= ...
x0 = np.array(( .5, .5 ))
sumdiff = 0
for z in range(zmax+1):
xetc = leastsq( lsqmin, x0, ftol=ftol, maxfev=maxfev, full_output=1 )
# (x, {cov_x, infodict, mesg}, ier)
x,y = xetc[0] # may be < 0 or > 1
diff = bilin( x, y ) - z
sumdiff += abs(diff)
print "%.2g %8.2g %5.2g %5.2g" % (z, diff, x, y)
print "ftol %.2g maxfev %d midweight %.2g => av diff %.2g" % (
ftol, maxfev, midweight, sumdiff/zmax)