如何使用 scipy 获得非平滑 2D 样条插值

2024-01-08

我想要一个二维三次样条拟合一些不规则的间隔数据 - 即一个完全拟合给定点处的数据的函数 - 但也可以返回之间的值。

我所能找到的(对于不规则间隔的数据)是scipy.interpolate.SmoothBivariateSpline。我不知道如何关闭“平滑”(无论我在s范围。

然而,我确实发现我可以得到我想要的大部分东西scipy.interpolate.griddata- 虽然这必须每次都重新计算(即不只是生成一个函数)。从根本上来说,这两者之间有什么区别吗?griddata做一些与“样条线”不同的事情?是否有办法关闭平滑SmoothBivariateSpline或者一个不平滑的等效函数?

以下是我用来测试样条曲线与多项式拟合的脚本

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import scipy.optimize
import scipy.interpolate
import matplotlib.pyplot as plt
import numpy.polynomial.polynomial as poly


# Grid and test function
N = 9;
x,y = np.linspace(-1,1, N), np.linspace(-1,1, N)
X,Y = np.meshgrid(x,y)
F = lambda X,Y : X+Y-1*X*Y-(X*Y)**2 -2*X*Y**2 + X**2*Y + 3*np.exp(-((X+1)**2+(Y+1)**2)*5)
Z = F(X,Y)
noise = 0.4
Z *= 1+(np.random.random(Z.shape)*2-1)*noise # noise

# Finer Grid and test function
N2 = 19;
x2,y2 = np.linspace(-1,1, N2), np.linspace(-1,1, N2)
X2,Y2 = np.meshgrid(x2,y2)
Z2 = F(X2,Y2)

# Make data into lists
Xl = X.reshape(X.size)
Yl = Y.reshape(Y.size)
Zl = Z.reshape(Z.size)

# Polynomial fit
# polyval(x,y,p) = p[0,0]+p[0,1]y+p[1,0]x+p[1,1]xy+p[1,2]xy^2 ..., etc
# I use a flat (1D) array for p, so it needs to be reshaped into a 2D array before
# passing to polyval
order = 3
p0 = np.zeros(order**2) # guess parameters (all 0 for now)
f_poly = lambda x,y,p : poly.polyval2d(x,y,p.reshape((order,order))) # Wrapper for our polynomial
errf = lambda p : np.mean((f_poly(Xl,Yl,p.reshape((order,order)))-Zl)**2) # error function to find least square error
sol = scipy.optimize.minimize(errf, p0)
psol = sol['x']

# Spline interpolation
# Bivariate (2D), Smoothed (doesn't fit points *exactly*)  cubic (3rd order - i.e. kx=ky=3) spline
spl = scipy.interpolate.SmoothBivariateSpline(Xl, Yl, Zl, kx=3,ky=3)
f_spline = spl.ev

# regular Interpolate
f_interp = lambda x,y : scipy.interpolate.griddata((Xl, Yl), Zl, (x,y), method='cubic')

# Plot
fig = plt.figure(1, figsize=(7,8))
plt.clf()

# poly fit
ax = fig.add_subplot(311, projection='3d')
ax.scatter3D(X2,Y2,Z2,s=3, color='red', label='actual data')
fit = f_poly(X2,Y2, psol)
l = 'order {} poly fit'.format(order)
ax.plot_wireframe(X2,Y2, fit, color='black', label=l)
ax.scatter3D(X,Y,Z, color='blue', label='noisy data')
plt.legend()
print("Average {} error: {}".format(l, np.sqrt(np.mean((fit-Z2)**2))))

# spline fit
ax = fig.add_subplot(312, projection='3d')
ax.scatter3D(X2,Y2,Z2,s=3, color='red', label='actual data')
l = 'smoothed spline'
fit = f_spline(X2,Y2)
ax.plot_wireframe(X2,Y2, fit, color='black', label=l)
ax.scatter3D(X,Y,Z, color='blue', label='noisy data')
plt.legend()
print("Average {} error: {}".format(l, np.sqrt(np.mean((fit-Z2)**2))))

# interp fit
ax = fig.add_subplot(313, projection='3d')
ax.scatter3D(X2,Y2,Z2,s=3, color='red', label='actual data')
l='3rd order interp '
fit=f_interp(X2,Y2)
ax.plot_wireframe(X2,Y2, fit, color='black', label=l)
ax.scatter3D(X,Y,Z, color='blue', label='noisy data')
plt.legend()
print("Average {} error: {}".format(l, np.sqrt(np.mean((fit-Z2)**2))))

plt.show(False)
plt.pause(1)

raw_input('press key to continue') # Change to input() if using python3

对于非结构化网格,griddata是正确的插值工具。然而,每次都会执行三角测量(Delaunay)和插值。一种解决方法是使用CloughTocher2DInterpolator https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CloughTocher2DInterpolator.html#scipy.interpolate.CloughTocher2DInterpolator对于 C1 平滑插值或LinearNDInterpolator https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.LinearNDInterpolator.html#scipy.interpolate.LinearNDInterpolator用于线性插值。这些是实际使用的函数griddata。区别在于可以使用 a 作为输入Delaunay object https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.spatial.Delaunay.html#scipy.spatial.Delaunay它返回一个插值函数。

这是一个基于您的代码的示例:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

import numpy as np
from scipy.interpolate import CloughTocher2DInterpolator
from scipy.spatial import Delaunay

# Example unstructured mesh:
nodes = np.array([[-1.        , -1.        ],
       [ 1.        , -1.        ],
       [ 1.        ,  1.        ],
       [-1.        ,  1.        ],
       [ 0.        ,  0.        ],
       [-1.        ,  0.        ],
       [ 0.        , -1.        ],
       [-0.5       ,  0.        ],
       [ 0.        ,  1.        ],
       [-0.75      ,  0.4       ],
       [-0.5       ,  1.        ],
       [-1.        , -0.6       ],
       [-0.25      , -0.5       ],
       [-0.5       , -1.        ],
       [-0.20833333,  0.5       ],
       [ 1.        ,  0.        ],
       [ 0.5       ,  1.        ],
       [ 0.36174242,  0.44412879],
       [ 0.5       , -0.03786566],
       [ 0.2927264 , -0.5411368 ],
       [ 0.5       , -1.        ],
       [ 1.        ,  0.5       ],
       [ 1.        , -0.5       ]])

# Theoretical function:
def F(x, y):
    return x + y -  x*y - (x*y)**2 - 2*x*y**2 + x**2*y + 3*np.exp( -((x+1)**2 + (y+1)**2)*5 )

z = F(nodes[:, 0], nodes[:, 1])

# Finer regular grid:
N2 = 19
x2, y2 = np.linspace(-1, 1, N2), np.linspace(-1, 1, N2)
X2, Y2 = np.meshgrid(x2, y2)

# Interpolation:
tri = Delaunay(nodes)
CT_interpolator = CloughTocher2DInterpolator(tri, z)
z_interpolated = CT_interpolator(X2, Y2)

# Plot
fig = plt.figure(1, figsize=(8,14))

ax = fig.add_subplot(311, projection='3d')
ax.scatter3D(nodes[:, 0], nodes[:, 1], z, s=15, color='red', label='points')

ax.plot_wireframe(X2, Y2, z_interpolated, color='black', label='interpolated')
plt.legend();

得到的图为:

样条法和 Clough-Tocher 插值法都是基于在网格元素上构造分段多项式函数。不同之处在于,对于样条线,网格是规则的并且由算法给出(参见.get_knots() https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.SmoothBivariateSpline.get_knots.html#scipy.interpolate.SmoothBivariateSpline.get_knots)。并且对系数进行拟合,使函数尽可能接近点并且平滑(拟合)。对于 Clough-Tocher 插值,网格元素是作为输入给出的元素。因此,所得函数保证通过这些点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 scipy 获得非平滑 2D 样条插值 的相关文章

  • 无法在 PIL 中对 16 位 TIF 应用图像滤镜

    我尝试使用 python 应用图像过滤器PIL http www pythonware com products pil 代码很简单 im Image open fnImage im im filter ImageFilter BLUR 此
  • Python 将列表中的字符串转换为数字

    我遇到了以下错误消息 以 10 为基数的 int 的文字无效 2 2 外部用单引号括起来 内部用双引号括起来 该数据位于primes列出使用print primes 0 样本数据在primes list 2 3 5 7 The primes
  • 如何在 Linux 中显示进程状态(阻塞、非阻塞)

    有没有办法查询 Linux 进程表中进程的状态 以便能够演示执行查询时进程是正在运行还是被阻止 我的目标是从进程或程序的 外部 执行此操作 因为我希望从操作系统进程的角度来理解这一点 但欢迎任何想法 这是Python代码阻塞的过程 impo
  • cv2.face.mindistancepredictcollector() 错误

    我已经安装了带有额外模块的 opencv 3 1 0 但是当我尝试使用 gt gt gt s cv2 face MinDistancePredictCollector 它返回一个错误 Traceback most recent call l
  • 地图与星图的性能?

    我试图对两个序列进行纯Python 没有外部依赖 逐元素比较 我的第一个解决方案是 list map operator eq seq1 seq2 然后我发现starmap函数来自itertools 这看起来和我很相似 但事实证明 在最坏的情
  • 如何更改条形图上的 y 轴限制?

    我有一个df 我从中索引了europe n我绘制了一个条形图 europe n r 5 c 45 looks like this df Country string df Population numeric 变量 plt bar df C
  • WTForms 中的小数字段舍入

    我有一个包含价格小数字段的表单 如下所示 from flask ext wtf import Form import wtforms from wtforms validators import DataRequired from deci
  • 肥皂服务的良好框架是什么?

    我正在寻找一个用于肥皂的好框架service 我更喜欢使用Pythonic框架 但是在查看了soaplib rpclib 太不稳定 SOAPy 不适用于2 7 和ZSI 太 令人困惑 之后 我不确定这是否可能 我对使用另一种语言感到满意 尽
  • 将列表传递给 PyCrypto 中的 AES 密钥生成器

    我尝试使用 Pycrypto 生成 AES 密钥 但收到以下错误 类型错误 列表 不支持缓冲区接口 对于以下声明 aescipher AES new mykey AES MODE ECB mykey 属于类型list并包含 18854347
  • 在 Windows 上将 NumPy 与 BLAS 链接

    我正在尝试在 Windows 系统上安装 Theano 并且需要安装 BLAS 和 LAPACK 我的 System32 文件夹中有这些的 dll 文件 当我运行 numpy config来自 Anaconda 的 show 库的路径正确显
  • 按字段名称对命名元组列表进行排序的 Pythonic 方法

    我想对命名元组列表进行排序 而不必记住字段名的索引 我的解决方案看起来相当尴尬 希望有人能有一个更优雅的解决方案 from operator import itemgetter from collections import namedtu
  • PyPI 项目页面中的“Py 版本”是什么意思?这有关系吗?

    我注意到 大多数在 PyPI 上发布的项目在其项目页面中都包含 Py 版本 元数据 但它们的值各不相同 如果包不是通用包或不是纯 python 包 那么它们的值是不同的 这是可以理解的 以便表示它们的目标平台 例如鼻页 https pypi
  • 图像堆栈的最大强度投影

    我正在尝试重新创建该功能 max array 3 来自 MatLab 它可以获取 N 个图像的 300x300px 图像堆栈 我在这里说 图像 因为我正在处理图像 实际上这只是一个大的双数组 300x300xN 并创建一个 300x300
  • 为什么全新安装后会有pip和conda包?

    All Windows 10 64 位 d l Anaconda 2 5 0 与 Python3 64 位并安装 全新安装后我输入conda list 并且 在软件包中 我看到 重复像 jupyter 1 0 0 py35 1 jupyte
  • 尝试修复我的功能

    我正在开发一个函数 我必须返回一个元组 其中第一个参数是最大数字的 str 第二个参数是 int 列表 这是示例以及我为该函数编写的内容 投票 G G N G C G 1 3 0 1 您必须将最大值的位置映射到正确的一方 parties N
  • 多线程写入文件

    前几天刚开始使用 python 对多线程的整个概念还很陌生 我在多线程时写入文件时遇到问题 如果我按照常规方式执行此操作 它会不断覆盖正在写入的内容 使用 5 个线程写入文件的正确方法是什么 不降低性能的最佳方法是在所有线程之间使用队列 每
  • 具有条件的重复行 pandas dataframe python

    我的数据框有问题 我的 df 是 product power brand product 1 3 x 1500W brand A product 2 2x1000W 1x100W product 3 1x1500W 1x500W brand
  • sklearn 中带有词袋和附加情感特征的文本分类器

    我正在尝试构建一个分类器 除了词袋之外 还使用情绪或主题 LDA 结果 等特征 我有一个包含文本和标签的 pandas DataFrame 并且想添加情感值 5 到 5 之间的数字 和 LDA 分析结果 带有句子主题的字符串 我有一个工作词
  • 安排 Asyncio 任务每 X 秒执行一次?

    我正在尝试创建一个 python 不和谐机器人 它将每隔 X 秒检查一次活跃会员 并根据会员的在线时间奖励积分 我正在使用 asyncio 来处理聊天命令 这一切都正常 我的问题是找到一种方法来安排每隔 X 秒异步检查一次活动成员 我已经阅
  • 在字典理解中为 locals() 添加下标失败并出现 KeyError [重复]

    这个问题在这里已经有答案了 我对 Python 的奇怪行为感到困惑locals 基本上我想从字典中获取一个项目locals 在字典理解中 但它失败了 这是一个非常基本的事情 所以 gt gt gt foo 123 gt gt gt bar

随机推荐