快速三线性插值

article/2025/10/2 17:30:55

转载自https://lianera.github.io/post/2018/fast-trilinear-interpolation/
快速三线性插值
最近需要对一个体素进行插值,并且应用到一张大图像上。这个本来用三线性插值很容易就实现了,但是体素的尺寸很小,长宽高大概20x15x10的大小,图像的尺寸非常大,差不多是4000x3000,等我实现完普通的三线性插值后,发现算法速度实在太慢,单是这一项三线性插值耗费的时间就占了总程序的一半多。其实如果能够用GPU,利用OpenGL里面的3d texture是最方便,也最快的,但是图像从内存传送到GPU需要耗费一定时间,并且很多情况下没法用GPU。所以只能推导一下,在体素上事先就进行预计算,然后再用参数应用到大图像上。

原理
借用一张常用的三线性插值示意图
在这里插入图片描述
三线性插值实际上可以通过7次线性插值实现。首先假定使用左手坐标系,z轴朝上,在x方向上对四条棱边进行四次插值,得到每条边上的四个点的值c00,c01,c10,c11,然后在y方向上对四个点进行插值,得到两条线段以及中间的两个点的值c0,c1,然后在z方向上插值,得到最终的c点的值。

我们知道,对于线性插值来说,其公式为:
在这里插入图片描述
其中包括四次加减运算,三次乘除运算,因此总的来说,进行一次三线性插值,运算总数为28次加减运算,21次乘除运算,并且往体素中寻找位置并且取值还要花费大量的运算,对于大图像来说,总的运算耗费的时间非常大。

假定立方体原点为(x0,y0,z0),离原点最远的点为(x1,y1,z1),立方体的每个顶点的值在体素中是知道的。值得注意的是,虽然现在计算的坐标位置实际上是插值时的位置,但是实际上插值只与待求点(x,y,z)与(x0,y0,z0)和(x1,y1,z1)的相对位置比有关,不过为了后续插值的方便,建议首先将点映射到目标坐标上,这样在插值的时候就不需要再进行坐标映射。首先对x方向上插值,得到yz平面上四个点的值分别为f1,f2,f3,f4:
在这里插入图片描述
在这里插入图片描述
注意一下,这里面隐含了x1和x0不能相等,如果两者相等,则f1=f(x0,y0,z0)=f(x1,y0,z0)恒成立,所以直接设置成x1=1,x0=0,再用上述公式即可。注意到,这里面的矩阵是不包含未知数的,这是个常数矩阵。这样一来,我们可以事先在体素上计算好矩阵,最后再应用到图像上就好了。当然我们这还只是一次线性插值,现在继续插值。我们令上面式子f1,f2,f3,f4中右侧矩阵分别为M1,M2,M3,M4,因为是常数矩阵,我们将他们用常数a,b替换。同样利用线性插值方法,现在在y轴方向上插值,计算1,2插值的点5,以及3,4插值的点6
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实现
预计算参数的实现直接按照上面的常数参数计算即可,因为预计算是在小的体素上面实现的,所以不用太担心速度。

c++
/* precompute trilinear coefficients
* v: f(x0,y0,z0), f(x1,y0,z0), f(x0,y1,z0), f(x1,y1,z0)
*    f(x0,y0,z1), f(x1,y0,z1), f(x0,y1,z1), f(x1,y1,z1)
*/
template <typename T>
array<T,8> PreComp(float x0, float y0, float z0, float x1, float y1, float z1, const array<T,8>& v)
{const float epsilon = 10e-6f;if (x1 - x0 < epsilon) { x1 = 1.f; x0 = 0.f; }if (y1 - y0 < epsilon) { y1 = 1.f; y0 = 0.f; }if (z1 - z0 < epsilon) { z1 = 1.f; z0 = 0.f; }float deno = (x1 - x0)*(y1 - y0)*(z1 - z0);float nume = 1.f / deno;T a1 = x1 * v[0] - x0 * v[1];T a2 = x1 * v[2] - x0 * v[3];T a3 = x1 * v[4] - x0 * v[5];T a4 = x1 * v[6] - x0 * v[7];T b1 = v[1] - v[0];T b2 = v[3] - v[2];T b3 = v[5] - v[4];T b4 = v[7] - v[6];T c5 = y1 * a1 - y0 * a2;T c6 = y1 * a3 - y0 * a4;T d5 = a2 - a1;T d6 = a4 - a3;T e5 = y1 * b1 - y0 * b2;T e6 = y1 * b3 - y0 * b4;T f5 = b2 - b1;T f6 = b4 - b3;T h1 = z1 * c5 - z0 * c6;T h2 = z1 * d5 - z0 * d6;T h3 = z1 * e5 - z0 * e6;T h4 = z1 * f5 - z0 * f6;T h5 = c6 - c5;T h6 = d6 - d5;T h7 = e6 - e5;T h8 = f6 - f5;array<T, 8> h = {h1*nume, h2*nume, h3*nume, h4*nume, h5*nume, h6*nume, h7*nume, h8*nume};return h;
}

而插值的时候,速度就是比较重要的了,因为大体素与小体素对应的时候,block是共享参数的,并且即使是变量x,y,z也可以预先计算一部分,不用每个cell都计算。具体来说,插值的时候直接应用f7的计算公式即可:

T val = zf * (yf*(h[7] * xf + h[5]) + h[6] * xf + h[4])+ yf * (h[3] * xf + h[1]) + h[2] * xf + h[0];

结果
对一个20x20x20的小体素进行预计算,然后用上述的三线性插值放大5倍,形成一个100x100x100大小的体素。

原体素
在这里插入图片描述
在这里插入图片描述
完整代码:https://lianera.github.io/post/2018/fast-trilinear-interpolation/main.cpp


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

相关文章

线性插值、双线性插值、双三次插值学习笔记-图像处理

缺失值之线性插值 interpolate用法 在series中有两个空值 用图的方式表示出四个点 使用线性插值后的结果如下 使用代码演示 线性插值后的结果 再加入一条数据 结果如下 使用pandas中的DataFrame 运行结果&#xff0c;默认在垂直方向上使用线性插值 设置水平方向上的线性插值 …

插值(Interpolation)

前言 插值计算普遍存在于图像处理中,最近在做畸变优化时,看了一些资料中提到了插值&双线性插值,开始没明白,觉得一定很难,直接跳过,到最终写代码时,又不得不使用.于是就这里对这个功能进行学习,记录,并使用vs2017进行实际验证,验证后发现这个原理其实并不复杂. 插值 插值…

三点线性插值

问题&#xff1a; 在三角形的三个顶点具有3个不同颜色&#xff0c;如何通过插值计算出三角形中每个点的颜色&#xff1f; 应用实例&#xff1a;高洛德着色使用3个顶点的颜色进行线性插值&#xff0c;结果如下图&#xff1a; 解决方案&#xff1a; 显然&#xff0c;无论是线性…

线性插值和双线性插值

最近在学数字图像处理中旋转变换的问题,发现旋转以后图片有一些不连续点,于是试着用双线性插值法进行解决。下面就介绍下插值的原理: 线性插值 如果你只处理分离的数据、想知道分离点之间的某些值,需要用到某种类型的插值。这种情况如图5-17坐标所示。对某些分离的(整数)…

没想到会用到:线性插值(Linear Interpolation)原理及使用

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

线性插值 多项式插值 样条插值 牛顿插值总结

项目github地址&#xff1a;bitcarmanlee easy-algorithm-interview-and-practice 欢迎大家star&#xff0c;留言&#xff0c;一起学习进步 1.什么是插值 在数值分析中&#xff0c;插值(interpolation)是一种通过已知的、离散的数据点&#xff0c;在范围内推求新数据点的过程…

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

常用线性插值的介绍和应用 线性插值 插值是计算机图形学中非常常用的技术。通常&#xff0c;数据是在常规网格上指定的&#xff08;值写在2D或3D网格的顶点位置&#xff09;或在线上&#xff08;在一维的情况下&#xff09;&#xff0c;但是程序需要在该网格上的随机位置求值。…

线性插值 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…