转载于:二圈妹的知乎
线性插值
线性插值 linear interpolation
无需多言,公式:
P(t) = A + (B -A)t
P(t) = A(1-t) + Bt
这个函数一般我们叫做lerp.
template<typename T>
inline T lerp(const T &lo, const T &hi, float t)
{ return lo * (1 - t) + hi * t; }
如果门把t变成某个函数g(t),那么线性可以变得平滑,可以变成多项式等等...
双线性插值 bilinear interpolation
思路是类似的,我们首先用插值算出 nx0 和 nx1,然后再用插值算出P处的值:
nx0 = lerp(c00,c10,tx)
nx1 = lerp(c01,c11,tx)
p = lerp(nx0,nx1,ty)
如果我们展开的话长这样:
三线性插值 Trilinear interpolation
同样的思路,只是我们推到3d空间:
a = lerp(c000,c100,tx)
b = lerp(c010,c110,tx)
c = lerp(c001,c101,tx)
d = lerp(c011,c111,tx)
得到了这四个点,再把它代入回双线性插值既可:
e = lerp(a, b, ty)
f = lerp(c, d, ty)
最终e, f之间构成了线性插值:
p = lerp(e,f,tz)
展开看各项的系数:
- c000: (1-tx)(1-ty)(1-tz)
- c100: tx(1-ty)(1-tz)
- c010: (1-tx)ty(1-tz)
- c110: txty(1-tz)
- c001: (1-tx)(1-ty)tz
- c101: tx(1-ty)tz
- c011: (1-tx)tytz
- c111: txtytz
如果写代码的话可以简单一点:
float accum = 0;
for (size_t i = 0; i < 2; i++)
for (size_t j = 0; j < 2; j++)
for (size_t k = 0; k < 2; k++)
accum += (i*tx+(1-i)*(1-tx))*
(j*ty+(1-j)*(1-ty))*
(k*tz+(1-k)*(1-tz))*c[i][j][k];
例子
双线性插值的一个直观例子见题图:
参考: