常用线性插值的介绍和应用(双线性插值,三线性插值,平滑曲线插值)

article/2025/10/2 17:45:16

常用线性插值的介绍和应用

 

线性插值

插值是计算机图形学中非常常用的技术。通常,数据是在常规网格上指定的(值写在2D或3D网格的顶点位置)或在线上(在一维的情况下),但是程序需要在该网格上的随机位置求值。如果样本位于网格顶点上,那么我们可以简单地使用存储在网格顶点上的值。但是,如果样本位于网格上其他任何位置(单元中的某个位置),则考虑到那里没有数据,我们需要通过平均存储在单元顶点处的值来计算一个。这项技术称为插值,因为关键思想是在固定的网格位置“插值”现有值以计算网格上其他任何位置的值。

在2D中,该技术称为双线性插值。它的3D对应物称为三线性插值。线性插值的方程式:

目标点(下图符号?处)的属性值由上述公式给出。其中a和b分别为两个端点处的属性值,t的值为目标点到a的距离与a到b的距离比值(t在0到1的范围内),我们示例图如下:

与重心坐标类似,未知点的属性都是由端点属性和对立权重的加权和。即始终是左方端点a乘对立权重(1-t),加上右方端点b乘对立权重t。下面的双线性插值和三线性插值更为直观。

 

双线性插值

当我们需要知道规则2D网格上随机位置的值时,可以使用双线性插值。注意,该网格也可以是图像或纹理贴图。如下示例:

我们希望在绿点(具有坐标cx,cy的c)标记的位置插值出一个值。为了计算c的值,我们将首先在一个方向(x方向)上执行两次线性插值,获得a和b。我们将使用tx对c00-c10和c01-c11进行线性插值以获得a和b。然后,我们将沿第二方向(y轴)线性插值a-b,以使用ty获得c。无论是开始沿x轴还是沿y轴对前两个值进行插值,都没有任何区别。在我们的示例中,我们首先对c00-c10和c01-c11进行插值以获得a和b。我们也可以先使用ty从c00-c01和c10-c11插值,然后使用tx插值结果。值得注意的是,双线性插值不再是线性的了,因为它是两个线性函数的乘积。如果采样点位于单元格的边缘之一(线c00-c10或c00-c01或c01-c11或c10-c11)上,则该函数为线性。在其他任何地方都是二次方。双线性插值代码如下:

float bilinear( const float &tx, const float  &ty, const Vec3f &c00, const Vec3f &c10, const Vec3f &c01, const Vec3f &c11) 
{ 
#if 1 //两步计算float  a = c00 * (1 - tx) + c10 * tx; float  b = c01 * (1 - tx) + c11 * tx; return a * (1) - ty) + b * ty; 
#else //面积计算return (1 - tx) * (1 - ty) * c00 + tx * (1 - ty) * c10 + (1 - tx) * ty * c01 + tx * ty * c11; 
#endif 
} 

我们上面讲解的是分成两步计算,我们还可以用上面提到的重心坐标的理解方法,使用面积计算。未知点属性由:端点属性乘对立面积乘积,再对四个端点都进行此操作并求和。c00端点操作如下:

如上图,c00点的属性乘上右上角矩形的面积。同理c10点的属性要乘上左上角的矩形,c01乘上右下角的矩形,c11乘上左下角的矩形。我们根据面积的代码就根据此得出。

 

三线性插值

三线性插值又是双线性插值的拓展。我们若想计算随机三维空间的点,如下图:

使用分步法来实现:为了计算e和f,我们使用两个双线性插值。为了计算g,我们沿z轴线性插值e和f。实现代码如下:

Vec3<T> interpolate(const Vec3<T>& location) { T gx, gy, gz, tx, ty, tz; unsigned gxi, gyi, gzi; // 获取网格点坐标(我们定义的网格为单位网格。长,宽,高为1)gx = location.x * nvoxels; gxi = int(gx); tx = gx - gxi; gy = location.y * nvoxels; gyi = int(gy); ty = gy - gyi; gz = location.z * nvoxels; gzi = int(gz); tz = gz - gzi; const Vec3<T> & c000 = data[IX(gei, gyi, gzi)]; const Vec3<T> & c100 = data[IX(gxi + 1, gyi, gzi)]; const Vec3<T> & c010 = data[IX(gxi, gyi + 1, gzi)]; const Vec3<T> & c110 = data[IX(gxi + 1, gyi + 1, gzi)]; const Vec3<T> & c001 = data[IX(gxi, gyi, gzi + 1)]; const Vec3<T> & c101 = data[IX(gxi + 1, gyi, gzi + 1)]; const Vec3<T> & c011 = data[IX(gxi, gyi + 1, gzi + 1)]; const Vec3<T> & c111 = data[IX(gxi + 1, gyi + 1, gzi + 1)]; 
#if 1 //分步处理,先进行2次双线性插值,再在z方向做线性插值Vec3<T> e = bilinear<Vec3<T> >(tx, ty, c000, c100, c010, c110); Vec3<T> f = bilinear<Vec3<T> >(tx, ty, c001, c101, c011, c111); return e * ( 1 - tz) + f * tz; 
#else //利用体积计算return (T(1) - tx) * (T(1) - ty) * (T(1) - tz) * c000 + tx * (T(1) - ty) * (T(1) - tz) * c100 + (T(1) - tx) * ty * (T(1) - tz) * c010 + tx * ty * (T(1) - tz) * c110 + (T(1) - tx) * (T(1) - ty) * tz * c001 + tx * (T(1) - ty) * tz * c101 + (T(1) - tx) * ty * tz * c011 + tx * ty * tz * c111; 
#endif } 

同样,我们还给出了利用体积求解三线性插值的方法。该方法依旧是重心坐标处理的拓展。c00和对立体积想乘,示例图如下:

同理另外7个点也根据此过程计算端点和对立体积的乘积,最后对8个端点求和便能得出最终插值属性。

三线性插值典型应用的例子是在mipmap中,我们用(u,v,d)三元组访问mipmap。值d为访问的mipmap的层级,可以为小数。采样高于d位置的纹理级别(整数)和低于d位置的级别(整数)(若d=3.5,则访问层级3和4的贴图)。(u,v)位置用于从这两个纹理级别的每一个中检索双线性插值样本。然后根据从每个纹理级别到d的距离对生成的样本进行线性插值。整个过程称就为三线性插值,且每个像素执行一次。

 

双线性插值和平滑曲线插值对比

在我们处理纹理贴图时,可选参数为NEAREST(最近),和LINEAR(双线性)。Qu ́ılez在文章“improved texture interpolation” 中提出了一种简单的技术,使用平滑曲线在一组2×2纹素之间进行插值。平滑曲线常用的为平滑步幅曲线和五次曲线:

左侧为平滑步幅曲线,右侧为五次曲线。平滑步幅曲线在0和1处有一阶导数为0的特点,即s'(0)=0,s'(1)=0。而5次曲线不仅0和1处的一阶导数为0,其二阶导数也为0,即s''(0)=0,s''(1)=0。两条曲线如下图所示:

我们观察放大一维纹理这些方法的对比图。 橙色圆圈表示纹理像素的中心以及纹理像素值(高度)。 从左到右:最近的,线性的,5次曲线插值,三次插值。

后面两种能给出平滑的改观。

Qu ́ılez方法过程如下:

  1. 将纹理坐标乘上纹理尺寸,然后加上0.5,用p保存结果。
  2. 将p取整,并保存在i中。
  3. 用p减去i获取小数部分,并保存在f中。
  4. 用平滑曲线函数处理f,即f=func(f);
  5. 将f和整数部分i相加,保存在p中。
  6. 将p减去0.5,再去除以纹理尺寸。

我们过程代码如下:

vec2 smoothst(vec2 tex){float u=tex.x*tex.x*(3.0-2.0*tex.x);float v=tex.y*tex.y*(3.0-2.0*tex.y);return vec2(u,v);
}vec2 quintic(vec2 tex){float u=tex.x*tex.x*tex.x*(6.0*tex.x*tex.x-15.0*tex.x+10);float v=tex.y*tex.y*tex.y*(6.0*tex.y*tex.y-15.0*tex.y+10);return vec2(u,v);
}vec4 getTexel( vec2 p )
{p = p*myTexResolution + 0.5;vec2 i = floor(p);vec2 f = p - i;f = quintic(f);p = i + f;p = (p - 0.5)/myTexResolution;return texture2D( myTex, p );
}

双线性插值效果和利用五次曲线平滑效果对比如下:

我们用低分辨率低的图片做实际对比:

其中,左1为原图,左2为双线性插值图,左三为平滑步幅曲线插值,左四为5次曲线插值。

由于线性插值仅仅是一阶多项式插值,因此重新采样纹理的斜率/导数是分段恒定的。这意味着当使用线性插值的高度图纹理生成某些法线/凹凸贴图或浮雕滤镜时,会出现不连续性(因为法线/凹凸贴图或浮雕滤镜是微分算子)。类似情况如下:

左一表示应用了5次曲线插值,左三表示双线性插值。他们右边的图是经过凹凸贴图滤波处理后的图,双线性插值明显不具有连续性。


http://chatgpt.dhexx.cn/article/KZwLWF1Q.shtml

相关文章

线性插值 np.interp()

线性插值是指插值函数为一次多项式的插值方式&#xff0c;其在插值节点上的插值误差为零。线性插值相比其他插值方式&#xff0c;如抛物线插值&#xff0c;具有简单、方便的特点。线性插值的几何意义即为概述图中利用过A点和B点的直线来近似表示原函数。 线性插值法是认为现象…

我与插值萍水相逢:线性插值(Linear Interpolation)原理及使用

各位博友们大家好&#xff0c;小弟遇到一些问题经常会去看大家的博客&#xff0c;所以也想加入大伙的阵营&#xff0c;每每看到一些好的东西&#xff0c;有些心得体会什么的也想与大伙分享。 1.关于插值 插值&#xff0c;它根据已知的数据序列&#xff08;也可以理解为坐标中一…

对线性插值的理解

【插值】 插值是用已知点求未知点的一种方法&#xff0c;而且通常是用两个已知点求一个未知点。&#xff08;如果是用很多已知点求未知点一般用曲线拟合&#xff09; 既然是用两个已知点求一个未知点&#xff0c;那么两个已知点之间的距离要尽可能的小&#xff0c;这样求出来…

python判断是否为数字类型_python判断字符串是否为数字

以下实例通过创建自定义函数 is_number() 方法来判断字符串是否为数字:# -*- coding: UTF-8 -*- # Filename : test.py # author by : www.runoob.com def is_number(s): try: float(s) return True except ValueError: pass try: import unicodedata unicodedata.…

使用正则表达式判断字符串是否为数字类型

java 判断字符串是否是数字 1.用JAVA自带的函数 publicstaticbooleanisNumeric(Stringstr){ for(inti0;i System.out.println(str.charAt(i)); if(!Character.isDigit(str.charAt(i))){ returnfalse; returntrue; 2.用正则表达式 首先要importjava.util.regex.Pattern和java.ut…

java判断字符串是否为数字

一&#xff1a;判断java中的字符串是否为数字&#xff0c;可以通过正则表达式来判断&#xff1b;其判断逻辑如下&#xff1a; 1、根据阿里巴巴代码规范&#xff0c;将Pattern设置为全局常量&#xff0c;通过 -?[0-9](\\\\.[0-9])? 进行匹配是否为数字 private static final P…

二次型化为标准型

将二次型化为标准形有利于我们了解二次型的简单形式、二次型的各种参数如正负惯性指数、得到二次型的规范形、对称矩阵合同的简单形等等。另外&#xff0c;化标准形也是解析几何化简二次曲线和二次曲面的需要。 下面&#xff0c;我们以两道题目为例说明计算二次型的标准形的2种…

二次型的标准型、规范型

若二次型只有平方项&#xff0c;则称二次型为标准型 如果标准型中&#xff0c;系数只有1&#xff0c;-1和0&#xff0c;那么称为二次型的规范型&#xff0c;因为标准型中&#xff0c;1&#xff0c;-1&#xff0c;0的个数是由正负惯性指数决定的&#xff0c;而合同的矩阵正负惯…

二次型,正定二次型

二次型&#xff1a;含有n个变量 x 1 , x 2 , . . . x n x_1,x_2,...x_n x1​,x2​,...xn​的二次齐次函数: f ( x 1 , x 2 , . . . x n ) a 11 x 1 2 a 12 x 1 x 2 a 13 x 1 x 3 a 14 x 1 x 4 . . . a 1 n x 1 x n f(x_1,x_2,...x_n)a_{11}x_1^2a_{12}x_1x_2a_{13}x_1x_3…

二次型的正定

实数二次型的类型 设为一个实二次型&#xff0c;若 自变量不全为0 若恒成立&#xff0c;则称f为一个正定二次型&#xff0c;称A为正定矩阵 若恒成立&#xff0c;则称f为一个半正定二次型&#xff0c;称A为半正定矩阵 若恒成立&#xff0c;则称f为一个负定二次型&#xff0…

线性代数-二次型及其正定性

二次型及其矩阵表示形式 二次型:含有n个变量的二次齐次多项式 二次型矩阵:xTAx,其中A为实对称矩阵 任给一个实二次型,就唯一确定一个实对称矩阵;反之,任给一个实对称矩阵,也可以唯一确认一个实二次型,因此,实二次型与实对称矩阵之间存在一一对应关系,称实对称矩阵A为二次型f的…

【考研线代】六. 二次型

文章目录 第六章 二次型6.1 二次型及其标准形6.1.1 概念6.1.2 合同基本性质6.1.3 题型 6.2 正定二次型6.2.1 概念6.2.2 定理 6.3 补充&#xff1a;解题技巧6.3.1 惯性定理的理解6.3.2 矩阵合同的充要条件6.3.3 配方法的坐标变换必须可逆6.3.4 正交变化化标准型 &#xff08;&am…

线性代数(10):二次型

一、二次型 &#xff08;1&#xff09;定义 含有 n 个变量 x1&#xff0c;x2&#xff0c;…… &#xff0c;xn 的二次齐次函数称为二次型&#xff1b; 对称矩阵 A 的秩也叫做二次型 f 的秩&#xff1b; &#xff08;2&#xff09; 例&#xff1a; 排列二次型 所对应的矩阵 …

二次型化标准形的三种方法

二次型化标准形的三种方法 将二次型化为标准形有利于我们了解二次型的简单形式、二次型的各种参数如正负惯性指数、得到二次型的规范形、对称矩阵合同的简单形等等。另外&#xff0c;化标准形也是解析几何化简二次曲线和二次曲面的需要。 下面&#xff0c;我们以两道题目为例…

二次型化标准形的五种方法

文章目录 1. 配方法2. 初等变换法3. 正交变换法4. 偏导数法5. 顺序主子式法 1. 配方法 用配方法化二次型为标准形的关键是消去交叉项&#xff0c;分如下两种情况&#xff1a; 情形1&#xff1a;如果二次型 f ( x 1 , x 2 , x 3 , ⋯ , x n ) {f \left( x\mathop{{}}\nolimits…

区别:二次型、标准形、规范形

文章目录&#xff1a; 一&#xff1a;二次型 二次型衔接 合同和相似 二&#xff1a;标准形 二次型化为标准形 1.配方法 2.正交变换法 三&#xff1a;规范形 标准形&#xff1a;不唯一规范形&#xff1a;唯一 一&#xff1a;二次型 二次型&#xff1a;对称矩阵 A&#…

速通二次型、二次型标准型、二次型规范型

浅过二次型 理解二次型可以从二次型的多项式入手&#xff1a; 显然&#xff0c;在系数都为实数的情况下&#xff0c;二次型矩阵即为一个实对称矩阵。 取一个代入值的例子就是&#xff1a; 二次型的标准型 OK&#xff0c;再从二次型的标准型的多项式入手&#xff0c;如下&…

二次型的来龙去脉

在学习二次型的时候没有好好理解概念&#xff0c;导致记住了可以用的结论&#xff0c;但往往遇到题目反应不过来&#xff0c;故这次对二次型进行一个详细剖析。 首先二次型是什么&#xff1f;是一个n元变量的二次齐次多项式&#xff0c;根据二次齐次多项式的定义&#xff08;所…

二次型二次型矩阵

二次型 二次型&#xff08;Quadratic form&#xff09;是关于一些变量的二次齐次多项式 二次型矩阵 表达形式跟矩阵的相似雷同&#xff0c;只是换成了转置 规范二次型 二次型化标准型 配方 将含有x1的项集中起来进行配方 非退化线性替换 合同变换 故标准型为 非退化线性…

线性代数——二次型

一&#xff1a;通过矩阵研究二次方程 二次型的定义&#xff1a; 把含有n个变量的二次齐次函数或方程称为二次型&#xff0c;例如&#xff1a; 二次型可以用矩阵来表示&#xff1a; 可以表示为 更一般的情况&#xff1a; 可以表示为 令&#xff1a;&#xff0c;&#xff0…