如何在数据点之间进行插值?
Posted
技术标签:
【中文标题】如何在数据点之间进行插值?【英文标题】:How to interpolate between data points? 【发布时间】:2010-10-11 04:37:03 【问题描述】:我目前正在开发一款使用 opencv 和 qt 绘制数据点的软件。我需要能够从不完整的数据中填充图像。我想在我拥有的点之间进行插值。任何人都可以推荐一个可以帮助我的库或函数。我想也许是 opencv reMap 方法,但我似乎无法让它工作。
数据是强度值的二维矩阵。我想创建某种图像。这是一个学校项目。
【问题讨论】:
需要的其他信息:它是什么样的数据?你能谈谈曲线的性质(即它们的外观吗?) 数据是强度值的二维矩阵。我想创建某种图像。这是一个学校项目。 所以基本上下面的答案都没有回答关于建议库或函数的问题......因为我遇到了与 op 完全相同的问题。 【参考方案1】:插值是一门复杂的学科。有无数种方法可以对一组点进行插值,并且假设您确实希望进行插值,而不是任何类型的平滑。 (插值法精确地再现了原始数据点。)当然,这个问题的二维性质使事情变得更加困难。
有几种常见的二维散点数据插值方案。实际上,对于那些可以访问它的人来说,可以获得一篇非常好的论文(Richard Franke,“Scattered data interpolation: Tests of some methods”,Mathematics of Computation,1982。)
也许最常用的方法是基于数据的三角测量。仅从您的数据点构建域的三角剖分。那么数据凸包内的任何点都必须恰好位于其中一个三角形内,否则它将位于共享边上。这允许您在三角形内进行线性插值。如果您使用的是 MATLAB,那么函数 griddata 可用于此目的。)
尝试从分散的点填充完整的矩形图像时的问题是数据很可能不会扩展到数组的 4 个角。在这种情况下,基于三角剖分的方案将失败,因为阵列的角不位于散点的凸包内。那么另一种选择是使用“径向基函数”(通常缩写为 RBF)。当地统计学界使用时,可以找到许多这样的方案,包括克里金法。
http://en.wikipedia.org/wiki/Kriging
最后,修复是一种插值方案的名称,其中元素在数组中给出,但缺少元素。这个名字显然是指需要修复珍贵艺术品上的撕裂或撕裂的艺术保护者所做的事情。
http://en.wikipedia.org/wiki/Inpainting
修复背后的想法通常是制定一个边界值问题。即在有洞的区域定义一个偏微分方程。使用已知边界值,通过求解未知元素的 PDE 来填充孔。如果存在大量未知元素,这可能是计算密集型的,因为它通常需要解决至少一个大规模稀疏线性方程组。如果 PDE 是非线性的,那么它就变成了一个更密集的问题。 PDE 的一个简单、相当好的选择是拉普拉斯算子,它产生一个可以很好地外推的线性系统。同样,我可以为 MATLAB 用户提供解决方案。
http://www.mathworks.com/matlabcentral/fileexchange/4551
偏微分方程的更好选择可能来自非线性偏微分方程。 Navier/Stokes 方程就是这样。它非常适合对常见的表面类型进行建模,但也更难处理。就像在生活的许多方面一样,你得到你所支付的。
【讨论】:
【参考方案2】:呸!大主题。
“正确”答案在很大程度上取决于您的问题领域和您正在做的各种细节。
在一维以上的插值需要做出一些选择。我假设您在常规网格上绘图,但是您的某些网格点没有数据。大问题:缺失的点是稀疏的,还是会形成大斑点?
你不能添加信息,所以你只是想建立一些看起来OK的东西。
概念上简单的建议(但实施可能有些工作):
对于缺失数据的每个区域,识别所有边缘点。也就是在这个图中找到x
oooxxooo
oox..xoo
oox...xo
ox..xxoo
oox.xooo
oooxoooo
其中 . 是缺失数据的点,x 和 o 有数据(对于单个缺失点,这将是四个最近的邻居)。用该 blob 周围边缘点的平均值填充每个缺失的数据点。为了使其平滑,每个点的权重为1/d
,其中 d 是两点之间的出租车司机距离(delta x + delta y)..
在我们有任何细节之前:
在没有此类信息的情况下,您是否尝试过直接线性插值?如果您的数据相当密集,这可能会为您完成,并且在您需要时可以简单地进行内联编码。
下一步通常是三次样条,但为此您可能需要获取现有实现。
当我需要比快速线性插值更强大的东西时,我通常使用ROOT(并选择一个 TSpline 类),但这可能比您需要的开销更大。
正如 cmets 中所述,ROOT 很大,虽然它很快,但它确实会试图强迫你以 ROOT 方式做事,因此它会对你的程序产生很大影响。
两点 (x1, y1) 和 (x2, y2) 之间的线性插值(或实际上是外推)给你
y_i = (x_i-x1)*(y2-y1)/(x2-x1)
【讨论】:
Root 是一个非常大的开销。而且大部分不是必须通过解释器运行而不是实际编译吗? 很多开销:是的。需要使用 cint: no (我更喜欢针对它编译东西)。而且我是粒子物理学家,所以我已经安装了它并且非常了解它...... 您的答案几乎正是我想要的,但我宁愿自己不实现它,有没有可以用来获得这种结果的 c++ 库?【参考方案3】:考虑到这是一个简单的学校项目,可能最容易实现的插值技术是“最近邻”
对于每个缺失的数据点,您可以找到最近的“填充”数据点并将其用作值。
如果您想进一步提高结果,那么您可以说,找到 K 个最近的数据点,并使用它们的加权平均值作为您缺失数据点的值。
权重可能与该点与缺失数据点的距离成正比。
还有无数其他技术,但最近邻法可能是最容易实现的。
【讨论】:
【参考方案4】:如果我了解您的需求如下。
我认为您有一个 x,y,Intensity 的子集,用于 L 乘 W 的维度,并且您想要填充从 0 到 L 的所有 X 和从 0 到 W 的 Y。
如果这是您的问题,那么解决方案是使用过滤器获得其他强度。
我认为拜耳过滤器或高斯过滤器会为您完成这项工作。
你可以谷歌这些过滤器,你会得到实施的答案。
祝你好运。
【讨论】:
以上是关于如何在数据点之间进行插值?的主要内容,如果未能解决你的问题,请参考以下文章