如何在数据点之间进行插值?

8

我正在使用opencv和qt开发一款绘制数据点的软件。我需要能够从不完整的数据中填充图像。我想在已有的点之间进行插值。有没有人可以推荐一个库或函数来帮助我。我认为可能是opencv的reMap方法,但我似乎无法让它起作用。

这些数据是强度值的2-d矩阵。我想创建某种类型的图像。这是一个学校项目。


需要额外的信息:这是什么类型的数据?您能描述一下曲线的性质吗(例如,它们的形状如何)? - Rook
数据是一个强度值的二维矩阵。我想创建某种类型的图像。这是一个学校项目。 - Sam
基本上,以下没有任何答案回答了建议库或函数的问题...因为我和楼主遇到了完全相同的问题。 - Lightsout
4个回答

13
插值是一个复杂的主题。有无限种方法可以对一组点进行插值,这是假设您确实希望进行插值,而不是任何类型的平滑处理。(插值函数可以完全重现原始数据点)。当然,这个问题的二维性质使得事情更加困难。
在2D中,有几种常见的散点插值方案。实际上,对于那些可以访问它的人,有一篇非常好的论文可用(Richard Franke,“Scattered data interpolation: Tests of some methods”,Mathematics of Computation,1982年)。
也许最常用的方法是基于数据的三角剖分。只需从数据点构建域的三角剖分即可。然后,数据凸包内的任何点必须位于恰好一个三角形内,否则它将位于共享边缘上。这允许您在线性三角形内进行插值。如果您使用MATLAB,则可以使用griddata函数来完成此目的。
尝试从散点填充完整矩形图像时的问题是,很可能数据并不延伸到阵列的4个角落。在这种情况下,基于三角剖分的方案将失败,因为阵列的角落不在散点的凸包内。那么,另一种选择是使用“径向基函数”(通常缩写为RBF)。可以找到许多这样的方案,包括地球物理统计学中使用的Kriging。

http://en.wikipedia.org/wiki/Kriging

最后,修补是插值方案的名称,其中数组中给定了元素,但存在缺失元素。该名称显然指的是艺术保护人员需要修复有价值艺术品上的撕裂或破损。

http://en.wikipedia.org/wiki/Inpainting

inpainting的想法通常是制定一个边界值问题。也就是说,在存在孔洞的区域定义一个偏微分方程。使用已知的边界值,通过解决未知元素的PDE来填补孔洞。如果有大量未知元素,则这可能会消耗大量计算资源,因为它通常需要解决至少一个庞大的稀疏线性方程组。如果PDE是非线性的,则这将成为更加复杂的问题。对于PDE的简单而合理的选择是拉普拉斯算子,它可以得到良好外推的线性系统。同样,我可以为MATLAB用户提供解决方案。

http://www.mathworks.com/matlabcentral/fileexchange/4551

更好的PDE选择可能来自于非线性PDE。其中一种是Navier/Stokes方程。它非常适合建模通常看到的表面类型,但处理起来也更加困难。就像生活中的许多方面一样,你得到的就是你所付出的。

7

哎呀,这是一个大题目。

"正确"的答案很大程度上取决于您的问题领域和您正在做的各种细节。

在多个维度上进行插值需要做出一些选择。我将假设您正在绘制一个常规网格,但其中一些网格点没有数据。重要的问题是:缺失的点是稀疏的,还是形成了大块?

无法添加信息,因此您只是尝试建立一些看起来可以接受的东西。

概念上简单的建议(但实现可能需要一些工作):

对于每个缺少数据的区域,请确定所有边缘点。也就是说,在这个图中找到x。

oooxxooo
oox..xoo 
oox...xo
ox..xxoo
oox.xooo
oooxoooo

对于缺失数据的点,用周围四个最近邻点的平均值填充。为了使其更加平滑,可以根据两点之间的出租车距离(delta x + delta y)来加权每个点,权重为 1/d


在没有具体信息的情况下:

如果您的数据相当密集,您是否尝试过直接线性插值?这可能对您有所帮助,并且编码起来足够简单。

通常下一步是三次样条插值,但您可能需要使用现有的实现。


当我需要比快速线性插值更强大的工具时,我通常会使用ROOT(并选择其中一个 TSpline 类),但这可能比您需要的要复杂。

如评论中所述,ROOT 很庞大,虽然它很快,但它确实试图强制您按照 ROOT 的方式操作,因此它可能会对您的程序产生很大影响。


两个点(x1,y1)和(x2,y2)之间的线性插值(或外推)给出:

 y_i = (x_i-x1)*(y2-y1)/(x2-x1)

Root是一种非常庞大的开销,而且大部分都必须通过解释器运行,而不是实际编译。 - James Matta
很多额外的开销:是的。需要使用cint:不需要(我更喜欢针对它进行编译)。而且我是一名粒子物理学家,所以我已经安装了它并且对它非常熟悉... - dmckee --- ex-moderator kitten
你的答案基本上就是我想要的,但是我宁愿不自己实现,有没有一个我可以用来得到这种结果的C++库? - Sam

1
考虑到这只是一个简单的学校项目,可能最容易实现的插值技术是“最近邻居”。
对于每个缺失的数据点,您可以找到最近的“填充”数据点,并将其用作值。
如果您想进一步改善结果,您可以找到K个最近的数据点,并使用它们的加权平均值作为缺失数据点的值。
权重可以与该点与缺失数据点之间的距离成比例。
还有无数其他技术,但最近邻居可能是最容易实现的。

0

如果我理解你的需求是这样的。

我认为你有一个L乘W维度的x、y、强度子集,你想要填充所有X从0到L和Y从0到W。

如果这是你的问题,那么解决方案是使用滤波器获取其他强度。

我认为Bayer滤波器或高斯滤波器可以为您完成工作。

你可以谷歌这些滤波器,你会得到实现的答案。

祝你好运。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接