草庐IT

基于MATLAB的二维与三维插值拟合运算(附完整代码)

唠嗑! 2023-10-09 原文

·

一. 一维插值

interp1函数在上个博客中(如下链接)已经更新了,此处再补充两个相关例题。

基于MATLAB的数据插值运算:Lagrange与Hermite算法(附完整代码)_唠嗑!的博客-CSDN博客

例题1

自行选择来自函数f(x)的数据点:

根据选择的数据进行插值处理,得出曲线。

解:

MATLAB代码如下:

clc;clear;

x=0:0.12:1;
y=(x.^2-3*x+5).*exp(-5*x).*sin(x);

%调用interp1()函数
x1=0:.02:1;
y0=(x1.^2-3*x1+5).*exp(-5*x1).*sin(x1);
y1=interp1(x,y,x1);
y2=interp1(x,y,x1,'pchip'); %分段三次Hermite插值
y3=interp1(x,y,x1,'spline'); %三次样条函数插值
y4=interp1(x,y,x1,'nearest'); %最近邻点插值

plot(x1,[y1',y2',y3',y4'],':',x,y,'o',x1,y0) %五条曲线,一个描点

%误差分析
[max(abs(y0(1:49)-y2(1:49))),max(abs(y0-y3)),max(abs(y0-y4))]

运行结果:

ans =

   0.017651383860966   0.008613955066235   0.159826013541615

 例题2

对f(x)进行Lagrange插值,并画图与标准图像对比。

解:

MATLAB代码如下:

clc;clear;

x0=-1+2*[0:10]/10;
y0=1./(1+25*x0.^2); %x0与y0生成数据点

x=-1:.01:1;
y=lagrange(x0,y0,x); %Lagrange插值

ya=1./(1+25*x.^2); %标准值

plot(x,ya,x,y,':') %虚线代表Lagrange插值运算后的图像

function y=lagrange(x0,y0,x)
ii=1:length(x0);
y=zeros(size(x));
for i=ii
    ij=find(ii~=i);
    y1=1;
    for j=1:length(ij),y1=y1.*(x-x0(ij(j)));
    end
    y=y+y1*y0(i)/prod(x0(i)-x0(ij));
end
end

运行结果:

二.二维插值

interp2命令作为二维数据内的插值运算,一共有三种常用的调用格式

格式1

ZI=interp2(X,Y,Z,XI,YI)

返回矩阵ZI,参量X和Y必须是单调的,且具有相同的划分格式,类似由命令meshgrid生成的一样。如果XI和YI中有在X与Y范围之外的点,那么就会返回NaN。

 格式2

ZI=interp2(Z,XI,YI)

缺省的表示形式,X=1:n,Y=1:m,且[m,n]=size(Z)。具体计算类似格式1

格式3

ZI=interp2(X,Y,Z,XI,YI,method)

method表明用指定的算法计算二维插值。常用的算法有以下四种:

  • 'linear':双线性插值算法,一种缺省算法
  • 'nearest':最临近插值
  • 'spline':三次样条插值
  • 'cubic':双三次插值

例题3

由z=f(x,y)可计算出一些较稀疏的网格数据,尝试对整个函数曲面进行插值拟合,并比较拟合结果。

解:

MATLAB代码如下:

clc;clear;

%绘制已知数据的网格图
[x,y]=meshgrid(-3:.6:3,-2:.4:2);
z=(x.^2-2*x).*exp(-x.^2-y.^2-x.*y);
surf(x,y,z), axis([-3,3,-2,2,-0.7,1.5])
title('初始网格图');

%选择较密的插值点,用默认的线性插值算法进行插值
[x1,y1]=meshgrid(-3:.2:3,-2:.2:2);
z1=interp2(x,y,z,x1,y1);
figure;
surf(x1,y1,z1),axis([-3,3,-2,2,-0.7,1.5])
title('默认线性插值算法画图');

%立方和样条插值
z2=interp2(x,y,z,x1,y1,'cubic');
z3=interp2(x,y,z,x1,y1,'spline');
figure;
surf(x1,y1,z2),axis([-3,3,-2,2,-0.7,1.5])
title('立方插值图');
figure;
surf(x1,y1,z3),axis([-3,3,-2,2,-0.7,1.5])
title('样条插值图');

%比较立方和样条插值算法误差
z_normal=(x1.^2-2*x1).*exp(-x1.^2-y1.^2-x1.*y1);
figure;
surf(x1,y1,abs(z_normal-z2)),axis([-3,3,-2,2,0,0.08]);
title('立方算法误差');
figure;
surf(x1,y1,abs(z_normal-z3)),axis([-3,3,-2,2,0,0.025])
title('样条算法误差');

运行结果:

三. 二维一般分布数据的插值

MATLAB中含有可对非网格数据进行插值的函数,调用的函数如下:

z=griddata(x0,y0,z0,x,y,'method')

上述中的method算法主要有五种,如下:

  • 'v4':MATLAB内含的插值算法,公认效果比较好
  • 'linear':双线性插值算法,属于缺省算法
  • 'nearest':最临近插值
  • 'spline':三次样条插值
  • 'cubic':双三次插值 

例题4

在x为[-3,3],y为[-2,2]的矩形区域内随机选择一组坐标,用'v4'和'cubic'插值法进行处理,并对误差进行比较。

解:

MATLAB代码如下:

clc;clear;

x=-3+6*rand(200,1);
y=-2+4*rand(200,1); %产生随机数
z=(x.^2-2*x).*exp(-x.^2-y.^2-x.*y);
[x1,y1]=meshgrid(-3:.2:3,-2:.2:2);

%cubic方法
z1=griddata(x,y,z,x1,y1,'cubic');
surf(x1,y1,z1),axis([-3,3,-2,2,-0.7,1.5])
title('cubic方法');

%v4方法
z2=griddata(x,y,z,x1,y1,'v4');
figure;
surf(x1,y1,z2),axis([-3,3,-2,2,-0.7,1.5])
title('v4方法');

%误差分析
z0=(x1.^2-2*x1).*exp(-x1.^2-y1.^2-x1.*y1);
figure;
surf(x1,y1,abs(z0-z1)),axis([-3,3,-2,2,0,0.25])
title('cubic方法的误差');
figure;
surf(x1,y1,abs(z0-z2)),axis([-3,3,-2,2,0,0.15])
title('v4方法的误差');

运行结果:

例题5

在x为[-3,3],y为[-2,2]的矩形区域随机选择一组坐标中,对分布不均匀的数据,进行插值分析。

解:

本题我将MATLAB代码分成两部分。

(1)样本点数据处理的MATLAB代码如下:

clc;clear;

x=-3+6*rand(200,1);
y=-2+4*rand(200,1);
z=(x.^2-2*x).*exp(-x.^2-y.^2-x.*y); %生成已知数据
plot(x,y,'x') %样本点的二维分布
title('样本点的二维分布');
figure;
plot3(x,y,z,'x'),axis([-3,3,-2,2,-0.7,1.5]),grid %三维图
title('三维样本图');

%去除在(-1,-1/2)点为圆心,以0.5为半径的圆内的点
ii=find((x+1).^2+(y+0.5).^2>0.5^2); %找出满足条件的点坐标
x=x(ii);y=y(ii);z=z(ii);
figure;
plot(x,y,'x')
t=[0:.1:2*pi,2*pi];
x0=-1+0.5*cos(t);
y0=-0.5+0.5*sin(t);
line(x0,y0) %在图形上叠加该圆,观察圆内样本点是否被去除
title('去除圆内点');

运行结果:

 

 

(2)插值与误差分析

MATLAB代码如下:

clc;clear;

x=-3+6*rand(200,1);
y=-2+4*rand(200,1);
z=(x.^2-2*x).*exp(-x.^2-y.^2-x.*y); %生成已知数据
t=[0:.1:2*pi,2*pi];
x0=-1+0.5*cos(t);
y0=-0.5+0.5*sin(t);

%用新样本拟合出曲面
[x1,y1]=meshgrid(-3:.2:3,-2:.2:2);
z1=griddata(x,y,z,x1,y1,'v4');
surf(x1,y1,z1),axis([-3,3,-2,2,-0.7,1.5])
title('拟合插值图');

%误差分析
z0=(x1.^2-2*x1).*exp(-x1.^2-y1.^2-x1.*y1);
figure;
surf(x1,y1,abs(z0-z1)),axis([-3,3,-2,2,0,0.15])
title('误差图');

figure;
contour(x1,y1,abs(z0-z1),30);
hold on,plot(x,y,'x');
line(x0,y0) %误差的二维等高线图
title('误差的二维等高线图');

 运行结果:

 

 

 

有关基于MATLAB的二维与三维插值拟合运算(附完整代码)的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  8. ruby-on-rails - Ruby on Rails I18n 插值 - 2

    大家好!我对我的:username字段进行了一个小的验证,它应该是4到30个字符。我写了一个验证::length=>{:within=>4..30,:message=>I18n.t('activerecord.errors.range')-我想显示一个错误各种错误的消息(不像,太长或太短),但这里有一个问题-我可以将最小值和最大值都传递给翻译,以便有类似的东西:用户名应该在4到30个字符之间。目前我有:range:"shouldbebetween%{count}and%{count}characters",这显然不起作用(只是为了检查)。是否可以从范围中获取这些值?谢谢大家的指教!

  9. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

  10. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

随机推荐