有谁知道如何做“逆” 三线性插值?

发布于 2024-07-25 13:21:46 字数 113 浏览 4 评论 0原文

三线性插值使用立方体顶点处的值来近似立方体内点 (x, y, z) 的值。 我正在尝试进行“逆”三线性插值。 知道立方体顶点的值和附加到点的值如何找到 (x, y, z)? 任何帮助将不胜感激。 谢谢你!

Trilinear interpolation approximates the value of a point (x, y, z) inside a cube using the values at the cube vertices. I´m trying to do an "inverse" trilinear interpolation. Knowing the values at the cube vertices and the value attached to a point how can I find (x, y, z)? Any help would be highly appreciated. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

往日情怀 2024-08-01 13:21:46

您正在给定 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。

You are solving for 3 unknowns given 1 piece of data, and as you are using a linear interpolation your answer will typically be a plane (2 free variables). Depending on the cube there may be no solutions or a 3D solution space.

I would do the following. Let v be the initial value. For each "edge" of the 12 edges (pair of adjacent vertices) of the cube look to see if 1 vertex is >=v and the other <=v - call this an edge that crosses v.

If no edges cross v, then there are no possible solutions.

Otherwise, for each edge that crosses v, if both vertices for the edge equal v, then the whole edge is a solution. Otherwise, linearly interpolate on the edge to find the point that has a value of v. So suppose the edge is (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)

This will give you all edge points that are equal to v. This is a solution, but possibly you want an internal solution - be aware that if there is an internal solution there will always be an edge solution.

If you want an internal solution then just take any point linearly between the edge solutions - as you are linearly interpolating then the result will also be v.

枯叶蝶 2024-08-01 13:21:46

我不确定你可以适用于所有情况。 例如,对颜色使用三线性过滤,其中每个点的每种颜色 (C) 都相同,这意味着无论您在何处进行插值,仍然会返回颜色 C。 在这种情况下,任何 x、y、z 都可能有效。 因此,不可能确切地说出初始插值是什么。

我确信在某些情况下你可以反转数学,但是我想,在很多情况下,如果不了解更多的输入信息,这是不可能做到的。

祝你好运,我希望有人能证明我错了:)

I'm not sure you can for all cases. For example using tri-linear filtering for colours where each colour (C) at each point is identical means that wherever you interpolate to you will still get the colour C returned. In this situation ANY x,y,z could be valid. As such it would be impossible to say for definite what the initial interpolation values were.

I'm sure for some cases you can reverse the maths but, i imagine, there are far too many cases where this is impossible to do without knowing more of the input information.

Good luck, I hope someone will prove me wrong :)

青芜 2024-08-01 13:21:46

三线性插值的维基百科页面有链接到一个 NASA 页面,据称该页面描述了反转过程 - 您看过吗?

The wikipedia page for trilinear interpolation has link to a NASA page which allegedly describes the inversing process - have you had a look at that?

¢蛋碎的人ぎ生 2024-08-01 13:21:46

您所描述的问题有些不明确。
您所要求的基本上可以翻译为:我有一个 3D 函数,并且我知道它的 8 个已知点的值。 我想知道函数接收值 V 的点是什么。
问题在于,很可能有无数个这样的点,它们构成一组曲面、线或点,具体取决于数据。
找到该集合的一种方法是使用等曲面算法,例如行进立方体

The problem as you're describing it somewhat ill-defined.
What you're asking for basically translates to this: I have a 3D function and I know its values in 8 known points. I'd like to know what is the point in which the function received value V.
The trouble is that in most likelihood there is an infinite number of such points which make a set of surfaces, lines or points, depending on the data.
One way to find this set is to use an iso-surfacing algorithm like Marching cubes.

灵芸 2024-08-01 13:21:46

让我们从 2d 开始:想象一座占地一平方公里的双线性山,
4 个角的高度为 0 10 20 30
和在高度 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)

Let's start with 2d: think of a bilinear hill over a square km,
with heights say 0 10 20 30 at the 4 corners
and a horizontal plane cutting the hill at height z.
Draw a line from the 0 corner to the 30 corner (whether adjacent or diagonal).
The plane must cut this line, for any z,
so all points x,y,z fall on this one line, right ? Hmm.

OK, there are many solutions -- any z plane cuts the hill in a contour curve.
Say we want solutions to be spread out over the whole hill,
i.e. minimize two things at once:

  • vertical distance z - bilin(x,y),
  • distance from x,y to some point in the square.

Scipy.optimize.leastsq is one way of doing this, sample code below;
trilinear is similar.

(Optimizing any two things at once requires an arbitrary tradeoff or weighting:
food vs. money, work vs. play ...
Cf. Bounded rationality
)

""" 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文