基于MATLAB的径向基函数插值(RBF插值)(一维、二维、三维)
基于MATLAB的径向基函数插值(RBF插值)(一维、二维、三维)
- 0 前言
- 1 RBF思路
- 2 1维RBF函数
- 2.1 参数说明
- 2.1.1 核函数选择
- 2.1.2 作用半径
- 2.1.3 多项式拟合
- 2.1.4 误差项(光滑项)
- 3 2维RBF函数
- 4 3维RBF函数
惯例声明:本人没有相关的工程应用经验,只是纯粹对相关算法感兴趣才写此博客。所以如果有错误,欢迎在评论区指正,不胜感激。本文主要关注于算法的实现,对于实际应用等问题本人没有任何经验,所以也不再涉及。
0 前言
插值是一个工程中非常常见的扩展数据方法。通常数据测量数量永远是已知的,数据的储存空间也是有限的,但工程中的数据需求却永远是无限的。
如何用较少位置处的数据点来推广到任意位置处的数据点,是工程中常见的问题。其中径向基函数RBF插值具有不依赖数据网格的特点,省去了传统插值的网格剖分,是一种基于拟合的插值。
本文主要注重于具有几何意义上的RBF插值,所以只列举了一维二维和三维插值,更高维插值数据可以稍加改写代码就可以实现,本文也不再涉及。
本文的参考文献如下:
[1]Meshfree Approximation Methods with MATLAB.Gregory E. Fasshauer.
1 RBF思路
径向基函数的大概原理是利用一系列函数叠加,对原函数进行拟合。也就是:
F ( x ) = ∑ w i ∗ f i ( x 0 , x ) F(x)=\sum w_i*f_i(x_0,x) F(x)=∑wi∗fi(x0,x)
其中f(x0,x)为基函数,是中心对称函数,函数中心点在x0上。w为每个函数的权重。
因此,只需要求出权重w,就可以利用基函数在各个点的值,计算出整个域的函数。而求解权重,也是一个简单的线性代数问题,直接用线性方程组求逆的方式就可以得到。
因此,RBF方法也具有原理简单,编程容易的特点。
下面用一个简单的例子来解释。
首先问题假设如下,我有下面6个点的数据(xi,yi),想插值出蓝色的曲线结果,该如何处理?
那么第一步,我们构造核函数。这里选用高斯函数作为核函数:
总共构造6个核函数f(x,xi),每个核函数中心点在xi上。
f i ( x ) = e x p ( − ( x − x i ) 2 / 2 / s 2 ) f_i(x)=exp(-(x-x_i)^2/2/s^2) fi(x)=exp(−(x−xi)2/2/s2)
每个函数乘以权重,可以得到当前基函数对应各个点的数值。以第一个基函数为例:
w 1 ∗ [ f 1 ( x 1 ) f 1 ( x 2 ) f 1 ( x 3 ) f 1 ( x 4 ) f 1 ( x 5 ) f 1 ( x 6 ) ] w_1* \begin{bmatrix} f_1(x_1)\\ f_1(x_2)\\ f_1(x_3)\\ f_1(x_4)\\ f_1(x_5)\\ f_1(x_6)\\ \end{bmatrix} w1∗ f1(x1)f1(x2)f1(x3)f1(x4)f1(x5)f1(x6)
则原函数F(x)可以计算为:
F ( x ) = ∑ w i ∗ f i ( x ) F(x)=\sum w_i*f_i(x) F(x)=∑wi∗fi(x) = ∑ w i ∗ [ f i ( x 1 ) f i ( x 2 ) f i ( x 3 ) f i ( x 4 ) f i ( x 5 ) f i ( x 6 ) ] =\sum w_i*\begin{bmatrix} f_i(x_1)\\ f_i(x_2)\\ f_i(x_3)\\ f_i(x_4)\\ f_i(x_5)\\ f_i(x_6)\\ \end{bmatrix} =∑wi∗ fi(x1)fi(x2)fi(x3)fi(x4)fi(x5)fi(x6) = [ f 1 ( x 1 ) f 2 ( x 1 ) f 3 ( x 1 ) f 4 ( x 1 ) f 5 ( x 1 ) f 6 ( x 1 ) f 1 ( x 2 ) f 2 ( x 2 ) f 3 ( x 2 ) f 4 ( x 2 ) f 5 ( x 2 ) f 6 ( x 2 ) f 1 ( x 3 ) f 2 ( x 3 ) f 3 ( x 3 ) f 4 ( x 3 ) f 5 ( x 3 ) f 6 ( x 3 ) f 1 ( x 4 ) f 2 ( x 4 ) f 3 ( x 4 ) f 4 ( x 4 ) f 5 ( x 4 ) f 6 ( x 4 ) f 1 ( x 5 ) f 2 ( x 5 ) f 3 ( x 5 ) f 4 ( x 5 ) f 5 ( x 5 ) f 6 ( x 5 ) f 1 ( x 6 ) f 2 ( x 6 ) f 3 ( x 6 ) f 4 ( x 6 ) f 5 ( x 6 ) f 6 ( x 6 ) ] ∗ [ w 1 w 2 w 3 w 4 w 5 w 6 ] = \begin{bmatrix} f_1(x_1)&f_2(x_1)&f_3(x_1)&f_4(x_1)&f_5(x_1)&f_6(x_1)\\ f_1(x_2)&f_2(x_2)&f_3(x_2)&f_4(x_2)&f_5(x_2)&f_6(x_2)\\ f_1(x_3)&f_2(x_3)&f_3(x_3)&f_4(x_3)&f_5(x_3)&f_6(x_3)\\ f_1(x_4)&f_2(x_4)&f_3(x_4)&f_4(x_4)&f_5(x_4)&f_6(x_4)\\ f_1(x_5)&f_2(x_5)&f_3(x_5)&f_4(x_5)&f_5(x_5)&f_6(x_5)\\ f_1(x_6)&f_2(x_6)&f_3(x_6)&f_4(x_6)&f_5(x_6)&f_6(x_6)\\ \end{bmatrix}* \begin{bmatrix} w_1\\ w_2\\ w_3\\ w_4\\ w_5\\ w_6\\ \end{bmatrix} = f1(x1)f1(x2)f1(x3)f1(x4)f1(x5)f1(x6)f2(x1)f2(x2)f2(x3)f2(x4)f2(x5)f2(x6)f3(x1)f3(x2)f3(x3)f3(x4)f3(x5)f3(x6)f4(x1)f4(x2)f4(x3)f4(x4)f4(x5)f4(x6)f5(x1)f5(x2)f5(x3)f5(x4)f5(x5)f5(x6)f6(x1)f6(x2)f6(x3)f6(x4)f6(x5)f6(x6) ∗ w1w2w3w4w5w6
然后利用线性代数方式,就可以得到系数w。
则原函数F可以利用这些个基函数叠加得到:
叠加后的函数和原函数对比见下图:
可以看到计算结果还可以,曲线过渡也比较光滑。
如果已知的插值点更多,还可以拟合的更好。下图为10个已知点进行插值的结果,和预想曲线几乎重合。
上面代码如下:
%RBF基本原理
clear
clc
close all%插值点
x0=0.2:0.5:3;
y0=sin(2*pi*0.5*x0)+cos(2*pi*0.8*x0)+2;
%原函数
x2=0:0.02:3;
y2=sin(2*pi*0.5*x2)+cos(2*pi*0.8*x2)+2;figure()
hold on
plot(x2,y2)
plot(x0,y0,'o','MarkerSize',8)
hold off%1构造函数
N_k=length(x0);%构造函数的数量
RBF_Kernel=cell(N_k,1);
for k=1:N_kx_k=x0(k);%中心位置,插值节点RBF_Kernel_k=@(x) exp(-(x-x_k).^2/2/0.3^2);%正态函数RBF_Kernel{k}=RBF_Kernel_k;%储存每个函数
end%2计算出插值矩阵
InterpMat=zeros(N_k,N_k);
for k=1:N_kRBF_phi_k=RBF_Kernel{k}(x0);%计算出当前正态函数InterpMat(:,k)=RBF_phi_k(:);%插值矩阵每一列储存的都是对应的正态函数
end%3利用插值矩阵求解出每个高斯函数的权重
%∑φ(k)*w(k)=InterpMat*w=y0,可以线性求逆直接得到系数w
w=InterpMat\y0';%绘制出每个正态函数
figure()
hold on
mcp=colormap('lines');
for k=1:N_kRBF_phi2_k=RBF_Kernel{k}(x2)*w(k);plot(x2,RBF_phi2_k,'Color',mcp(k,:))plot([x0(k),x0(k)],[0,RBF_Kernel{k}(x0(k))*w(k)],'Color',mcp(k,:),'LineStyle','--')
end
plot(x2,y2,'Color','k','LineWidth',2)
hold off%绘制出最终相加的结果
y_RBF=zeros(size(y2));
for k=1:N_ky_RBF=y_RBF+RBF_Kernel{k}(x2)*w(k);%叠加每一个正态函数
end
figure()
hold on
plot(x2,y2)
plot(x2,y_RBF,'--')
plot(x0,y0,'o','MarkerSize',8)
legend({'原函数','RBF插值结果'},'Location','best')
2 1维RBF函数
下面为1维RBF函数插值的代码,基本思路和上面第一章节的一样。但是对于计算速度和输入输出等方面简单做了一些优化。
计算结果如下:
代码如下:
clear
clc
close all%初始已知点
x0=0:0.1:3;
y0=sin(2*pi*0.5*x0)+cos(2*pi*0.8*x0)+2+0.02*rand(size(x0));x=(-1:0.01:4);
y=RBF1(x0,y0,x,'gaussian',0.3,0,0.001);figure()
hold on
plot(x0,y0,'o')
plot(x,y)
hold offfunction y=RBF1(x0,y0,x,Method,Rs,Npoly,Error)
%一维RBF插值,输入x0散点,y0值。x是输出插值得到的点。
%Method方法,默认'linear'。
%'linear',|R|
%'gaussian',exp(-(R/Rs)^2)
%'thin_plate',R^2*log(R)
%'linearEpsR',|R|。分段线性插值,要求s更大一些
%'cubic',|R^3|%Rs,插值核作用半径。Rs对于'linear','cubic','thin_plate'无影响。Rs大概和点和点之间的距离差不多就行。
%Npoly多项式拟合。默认是1,只拟合1次项。
%Error误差。在(-∞,∞)区间。默认是0,无误差。表示可以在部分误差范围内去插值。
%Error一般在0~1之内。如果只是为了收敛,可以比较小,在0.1以内就可以有很好效果;如果想实现平滑,可适当增大,大于1。%示例:x0=0:0.3:pi;y0=sin(2*x0)+0.2*x0;x=-1:0.01:4;y=RBF1(x0,y0,x,'linear',0.2,1,0.0);
%示例:x0=0:0.1:3;y0=0.25*x0.^2-0.5*x0+0.1*rand(size(x0));x=-1:0.01:4;y=RBF1(x0,y0,x,'gaussian',0.3,2,0.01);N=length(x0);%点的数量,也是RBF核的数量
%整理为列向量
x0=x0(:);
y0=y0(:);
x=x(:);%函数默认信息
if nargin<4 || isempty(Method)Method='linear';%默认线性核函数
elseif nargin<5 || isempty(Rs)Rs=1.1*(max(x0)-min(x0))/N;%假设空间均匀分布
elseif nargin<6 || isempty(Npoly)Npoly=1;%默认拟合1次项
elseif nargin<7 || isempty(Error)Error=0;%默认输入数据没有误差
end%选择核函数
K_method=0;
switch Methodcase 'linear'K_method=1;fun=@(RMat) Kernel_Linear(RMat,Rs);case 'gaussian'K_method=2;fun=@(RMat) Kernel_Gaussian(RMat,Rs);Error=-Error;%因为零点不是零,远点是0,所以这里误差为负case 'thin_plate'K_method=3;fun=@(RMat) Kernel_Thin_plate(RMat,Rs);case 'linearEpsR'K_method=4;fun=@(RMat) Kernel_LinearEpsR(RMat,Rs);Error=-Error;%因为零点不是零,远点是0,所以这里误差为负
end%将原始数据分离出多项式项Npoly
if Npoly==0C=ones(N,1);%常数项wC=mean(y0);
elseif Npoly==1C=[ones(N,1),x0];%常数项+一次项wC=C\y0;
elseif Npoly==2C=[ones(N,1),x0,x0.^2];%常数项+一次项+二次项wC=C\y0;
elseerror('只支持Npoly=0,1,2')
end
yC=C*wC;%多项式项
y1=y0-yC;%计算每个基函数在各个点的值
K2=zeros(N);%每一列对应一个函数
%计算距离矩阵
DisMat=squareform(pdist(x0));
K3=fun(DisMat);%每一个核函数的中心点在节点上
K3=K3-Error*eye(N);%把误差函数加入w=K3\y1;%计算权重%根据权重计算插值
y=zeros(size(x));
for k=1:N %计算每个核的贡献,然后叠加R_k=abs(x-x0(k));yt=w(k)*fun(R_k );%plot(t,yt);y=y+yt;
endNOut=length(y);
%再还原回多项式项
if Npoly==0C=ones(NOut,1);%常数项
elseif Npoly==1C=[ones(NOut,1),x];%常数项+一次项
elseif Npoly==2C=[ones(NOut,1),x,x.^2];%常数项+一次项+二次项
end
y=y+C*wC;%再加上多项式项%检查结果
if max(abs(w))/max(abs(y1))>1e3warning('结果未收敛,建议调整误差Error');
elseif (max(y)-min(y))>5*(max(y0)-min(y0))warning('结果未收敛,建议增大区间Eps,或者调整误差Error');
endendfunction z=Kernel_Linear(R,s)
%R距离
z=abs(R);%线性函数
endfunction z=Kernel_Gaussian(R,s)
%R距离
%s大概和采样点间距差不多就行,可以略大(更胖)
z=exp(-R.^2/2/s^2);%正态函数
endfunction z=Kernel_Thin_plate(R,s)
%R距离
z=R.^2.*log(R);%thin_plate
endfunction z=Kernel_LinearEpsR(R,s)
%R距离
%s大概和采样点间距差不多就行,可以略大(更胖)
s=2*s;%这里要更大
z=s-R;%线性函数
z(z<0)=0;
end
2.1 参数说明
下面说一下上面函数RBF1的后面各项参数结果:
y=RBF1(x0,y0,x,Method,Rs,Npoly,Error)
2.1.1 核函数选择
RBF函数的核函数有非常多种,比如高斯函数、线性函数、薄板函数等。
下面以分别选择高斯函数和线性函数作为核函数的RBF进行对比:
clear
clc
close all%初始已知点
x0=0:0.1:3;
y0=sin(2*pi*0.5*x0)+cos(2*pi*0.8*x0)+2+0.02*rand(size(x0));x=(-1:0.01:4);
y=RBF1(x0,y0,x,'gaussian',0.3,0,0.001);figure()
hold on
plot(x0,y0,'o')
plot(x,y)
hold off
可以看到线性核函数的效果相当于线性插值,而高斯核函数对峰值的拟合预测很好,各有侧重点。
事实上,核函数的选择对RBF插值有重要影响,不同核函数对应着不同的场景。
2.1.2 作用半径
对于某些核函数,还需要确定其作用半径。比如对于高斯函数,半径越大,核越宽。
对于高斯函数,作用半径通常要大于两个散点之间距离,但最好不要太大。如果太小,会导致每个点都是一个孤立的峰。如果太大,会导致求系数时方程求解困难。
下面代码展示了作用半径为0.05、0.3和0.8半径的插值效果。
%初始节点
x0=0:0.3:3;
y0=sin(2*pi*0.5*x0)+cos(2*pi*0.8*x0)+2+0.02*rand(size(x0));x=(-1:0.01:4);
y=RBF1(x0,y0,x,'gaussian',0.3,0,0.01);
y3=RBF1(x0,y0,x,'gaussian',0.05,0,0.0001);
y4=RBF1(x0,y0,x,'gaussian',0.8,0,0.0001);
figure()
hold on
plot(x,y3)
plot(x,y)
plot(x,y4)
plot(x0,y0,'o')
hold off
legend({'Rs=0.05','Rs=0.3','Rs=0.7'},'location','best')
ylim([-0.5,4.5])
可以看到上面每个点的间距为0.2。当Rs很小的时候,每个点只有一个孤立的高斯峰。当Rs大于间距时,比如Rs=0.3和0.7,都可以求解出结果。
但当Rs比较大,比如Rs=0.7时,会出现计算很奇怪的解,比如系数w特别大。这种如果适当的加一小点误差Error(有一点就行,1e-3量级的已经足够了),放宽求解精度,可以避免这种系数w很大不收敛的情况。
2.1.3 多项式拟合
本RBF插值函数默认带一个常数项。因为像高斯函数等函数无穷大处是0,对于本身数值在0附近的函数插值效果还可以,但是函数距离x轴很远时,再用这些基函数去拟合效果就会非常差。
因此在RBF插值之前,需要先求出常数项C,然后将所有散点的yi减去这个常数项C。之后计算完系数再插值后,再把这个常数项C加上。
一次项也是同样的原理,就是先拟合出y’=kx+b,然后把所有散点yi-y’,得到计算系数用的y值。之后再把这个一次项加上即可。
通常常数项一般就够,除非数据有很明显的线性度。
下面代码展示了常数项和一次项对比插值的效果:
x0=0:0.3:3;
x=(-1:0.01:4);
y0=sin(2*pi*0.5*x0)+cos(2*pi*0.8*x0)+1+2*x0+0.02*rand(size(x0));
y1=RBF1(x0,y0,x,'gaussian',0.3,0,0.0001);
y2=RBF1(x0,y0,x,'gaussian',0.3,1,0.0001);
figure()
hold on
plot(x,y1)
plot(x,y2)
plot(x0,y0,'o')
hold off
legend({'常数项','一次项'},'location','best')
2.1.4 误差项(光滑项)
当数据采集具有一定的误差,或者计算不需要完全贴合每一个点的数据,或者拟合出的曲线太曲折需要光滑,或者计算出的系数w过大甚至不收敛,都可以适当的添加误差项来解决。
其中系数w不收敛的问题,可能是由于核半径Rs过大,或者原始数据本身不太好导致的。适当添加一点误差,1e-3甚至更小,就可以解决这个问题。
而如果想要消除误差,光滑曲线,则需要较大的数,比如0.2,甚至超过1。这个根据具体效果来看。
这个的原理是直接在矩阵K的对角线上减去一个数。这样可以略微放宽求解的约束,使得节点处的数值不一定是控制点数值。
下面展示了添加了随机项后,大误差和小误差项的对比代码和结果:
x0=0:0.1:3;
y0=sin(2*pi*0.5*x0)+cos(2*pi*0.8*x0)+1+0.4*randn(size(x0));
x=(-0.0:0.01:3.0);
y1=RBF1(x0,y0,x,'gaussian',0.15,0,0.0001);
y2=RBF1(x0,y0,x,'gaussian',0.15,0,0.3);figure()
hold on
plot(x,y1)
plot(x,y2)
plot(x0,y0,'o')
hold off
legend({'小误差项','大误差项'},'location','best')
可以看到小误差项,曲线经过了每一个散点。大误差项,曲线只是大致经过了散点。
3 2维RBF函数
二维RBF函数的原理和一维相同。
z=RBF2(x0,y0,z0,x,y,Method,Rs,Npoly,ExtrapMethod,Error)
其中x0、y0是已知散点,z0是对应的值。然后要插值出x、y对应的值。
二维RBF函数额外考虑了外插的方法。通常并不建议数据外插,因为缺乏足够的信息。
本函数总共考虑了三种外插方法:
第一个是’rbf’,其实就是RBF方法算出来多少就是多少。
第二个是’nearest’,就是不外插,超出包线的点的数值直接等于相邻数据点数值。
第三个是’ploy’,是多项式外插,超出包线的点,按照多项式拟合的值计算得到,适用于波动不大的数据。
推荐’rbf’方法,因为不需要计算包线,如果不怎么考虑外插的话,非常节省时间。
下面展示了二维RBF插值计算的结果:
可以看到RBF插值可以较好的拟合出预期的效果。
展示的代码如下:
clear
clc
close all%初始节点
N=60;
x0=rand(N,1)*6-3;%-3~3
y0=rand(N,1)*6-3;%-3~3
z0=peaks(x0,y0)+0.05*x0;[x,y]=meshgrid(-5:0.02:5);
%二维RBF插值
z3=RBF2(x0,y0,z0,x,y,'gaussian',0.5,1,'rbf',0.001);z=zeros(size(x));z(:)=z3(:);figure()
hold on
surf(x,y,z,'EdgeColor','none');
scatter3(x0,y0,z0)
hold offfunction z=RBF2(x0,y0,z0,x,y,Method,Rs,Npoly,ExtrapMethod,Error)
%二维RBF插值,输入x0,y0散点,z0值。x,y是输出插值得到的点。
%Method方法,默认'linear'。
%'linear',|R|
%'gaussian',exp(-(R/Rs)^2)
%'thin_plate',R^2*log(R)
%'linearEpsR',|R|。分段线性插值,要求s更大一些
%'cubic',|R^3|%Rs,插值核作用半径。Rs对于'linear','cubic','thin_plate'无影响。Rs大概和点和点之间的距离差不多就行。
%Npoly多项式拟合。默认是1,只拟合1次项。
%ExtrapMethod,外插方法。某个数,全部赋值为这个数。'nearest',按照临近值外插。'ploy',多项式外插。'rbf',默认用RBF插值得到的值。
%Error误差。在(-∞,∞)区间。默认是0,无误差。表示可以在部分误差范围内去插值。
%Error一般在0~1之内。如果只是为了收敛,可以比较小,在0.1以内就可以有很好效果;如果想实现平滑,可适当增大,大于1。%示例:N=numel(x0);%点的数量,也是RBF核的数量
%整理为列向量
x0=x0(:);
y0=y0(:);
z0=z0(:);
x=x(:);
y=y(:);
%计算包线
[k_ch,V]=convhull(x0,y0);
if V<=0warning('输入散点过于集中');
end
%函数默认信息
narginchk(5,10)
if nargin<7 || isempty(Method)Method='linear';%默认线性核函数
elseif nargin<8 || isempty(Rs)Rs=1.1*(max(x0)-min(x0))/N;%假设空间均匀分布
elseif nargin<9 || isempty(Npoly)Npoly=1;%默认拟合1次项
elseif nargin<10 || isempty(Npoly)ExtrapMethod='rbf';%默认不外插
elseif nargin<11 || isempty(Error)Error=0;%默认输入数据没有误差
end%选择核函数
switch Methodcase 'linear'fun=@(RMat) Kernel_Linear(RMat,Rs);case 'gaussian'fun=@(RMat) Kernel_Gaussian(RMat,Rs);Error=-Error;%因为零点不是零,远点是0,所以这里误差为负case 'thin_plate'fun=@(RMat) Kernel_Thin_plate(RMat,Rs);case 'linearEpsR'fun=@(RMat) Kernel_LinearEpsR(RMat,Rs);Error=-Error;%因为零点不是零,远点是0,所以这里误差为负
end%将原始数据分离出多项式项Npoly
if Npoly==0C=ones(N,1);%常数项wC=mean(z0);
elseif Npoly==1if N<2;warning('点数太少,建议Npoly等于0');endC=[ones(N,1),x0,y0];%常数项+一次项wC=C\z0;
elseif Npoly==2if N<5;warning('点数太少,建议Npoly等于1');endC=[ones(N,1),x0,y0,x0.^2,y0.^2,x0.*y0];%常数项+一次项+二次项wC=C\z0;
elseerror('只支持Npoly=0,1,2')
end
zC=C*wC;%多项式项
z1=z0-zC;%计算距离矩阵
DisMat=squareform(pdist([x0,y0]));
K3=fun(DisMat);%每一个核函数的中心点在节点上
K3=K3-Error*eye(N);%把误差函数加入w=K3\z1;%计算权重%根据权重计算插值
z=zeros(size(x));
for k=1:N %计算每个核的贡献,然后叠加R_k=sqrt((x-x0(k)).^2+(y-y0(k)).^2);zt=w(k)*fun(R_k );z=z+zt;
endNOut=length(z);
%再还原回多项式项
if Npoly==0C=ones(NOut,1);%常数项
elseif Npoly==1C=[ones(NOut,1),x,y];%常数项+一次项
elseif Npoly==2C=[ones(NOut,1),x,y,x.^2,y.^2,x.*y];%常数项+一次项+二次项
end
zC2=C*wC;%再加上多项式项%判断外插方法
Inpoly=inpolygon(x,y,x0(k_ch),y0(k_ch));%多边形内
indxInpoly=find(Inpoly);
if isnumeric(ExtrapMethod)z(Inpoly)=z(Inpoly)+zC1(Inpoly);%内部的正常z(~Inpoly)=ExtrapMethod;%外部的固定值
elseif ischar(ExtrapMethod)switch ExtrapMethodcase 'rbf'z=z+zC2;%再加上多项式项case 'ploy'z(Inpoly)=z(Inpoly)+zC2(Inpoly);%内部的正常z(~Inpoly)=zC2(~Inpoly);%外部的直接用多项式值case 'nearest'z(Inpoly)=z(Inpoly)+zC2(Inpoly);%内部的正常%找到最近的点F = scatteredInterpolant(x(Inpoly),y(Inpoly),z(Inpoly),'nearest','nearest');%外部的直接插值z(~Inpoly)=F(x(~Inpoly),y(~Inpoly));end
elseerror('未识别ExtrapMethod')
end%检查结果
if max(abs(w))/max(abs(z1))>1e3warning('结果未收敛,建议调整误差Error');
elseif (max(z)-min(z))>5*(max(z0)-min(z0))warning('结果未收敛,建议增大区间Eps,或者调整误差Error');
endendfunction z=Kernel_Linear(R,s)
%R距离
z=abs(R);%线性函数
endfunction z=Kernel_Gaussian(R,s)
%R距离
%s大概和采样点间距差不多就行,可以略大(更胖)
z=exp(-R.^2/2/s^2);%正态函数
endfunction z=Kernel_Thin_plate(R,s)
%R距离
z=R.^2.*log(R);%thin_plate
endfunction z=Kernel_LinearEpsR(R,s)
%R距离
%s大概和采样点间距差不多就行,可以略大(更胖)
s=2*s;%这里要更大
z=s-R;%线性函数
z(z<0)=0;
end
4 3维RBF函数
计算方法和二维的方法一致。其实更高维的数据计算方法也相差不多。
对于实际工程的几何插值使用,最高维度也就是三维。对于其它应用可能还是需要高维的插值,本文暂不涉及,由于RBF代码较为简单,因此稍加改动即可更改为高维RBF插值结果。
三维RBF函数的原理和二维也相同。
P=RBF3(x0,y0,z0,P0,x,y,z,Method,Rs,Npoly,ExtrapMethod,Error)
其中x0、y0、z0是已知散点,P0是对应的值。然后要插值出x、y、z对应的值。
下面展示了三维RBF插值计算的结果和对应代码:
clear
clc
close all%初始节点
N=1000;
x0=rand(N,1)*6-3;%-3~3
y0=rand(N,1)*6-3;%-3~3
z0=rand(N,1)*6-3;%-3~3
P0=sin(1*pi*x0)+cos(1.5*pi*y0)+sin(1*pi*z0)+1;[x,y,z]=meshgrid(-5:0.2:5);P3=RBF3(x0,y0,z0,P0,x,y,z,'linear',0.5,1,'nearest',0.01);%RBF插值P=zeros(size(x));P(:)=P3(:);%实际插值结果
figure()
hold on
s=slice(x,y,z,P,[0],[0],[0]);
set(s,'LineStyle','none');
scatter3(x0,y0,z0)
hold off
xlabel('x');ylabel('y');zlabel('z');
view(3)%理论目标结果
figure()
P3=sin(1*pi*x)+cos(1.5*pi*y)+sin(1*pi*z)+1;
P3(x>3)=0;P3(y>3)=0;P3(z>3)=0;P3(x<-3)=0;P3(y<-3)=0;P3(z<-3)=0;
s=slice(x,y,z,P3,[0],[0],[0]);
xlabel('x');ylabel('y');zlabel('z');
view(3)function P=RBF3(x0,y0,z0,P0,x,y,z,Method,Rs,Npoly,ExtrapMethod,Error)
%二维RBF插值,输入x0,y0散点,z0值。x,y是输出插值得到的点。
%Method方法,默认'linear'。
%'linear',|R|
%'gaussian',exp(-(R/Rs)^2)
%'thin_plate',R^2*log(R)
%'linearEpsR',|R|。分段线性插值,要求s更大一些
%'cubic',|R^3|%Rs,插值核作用半径。Rs对于'linear','cubic','thin_plate'无影响。Rs大概和点和点之间的距离差不多就行。
%Npoly多项式拟合。默认是1,只拟合1次项。
%ExtrapMethod,外插方法。某个数,全部赋值为这个数。'nearest',按照临近值外插。'rbf',默认用RBF插值得到的值。三维外插判据复杂,不建议用。
%Error误差。在(-∞,∞)区间。默认是0,无误差。表示可以在部分误差范围内去插值。
%Error一般在0~1之内。如果只是为了收敛,可以比较小,在0.1以内就可以有很好效果;如果想实现平滑,可适当增大,大于1。
N=numel(x0);%点的数量,也是RBF核的数量
%整理为列向量
x0=x0(:);
y0=y0(:);
z0=z0(:);
P0=P0(:);
x=x(:);
y=y(:);
z=z(:);
%计算包线
[k_ch,V]=convhull(x0,y0,z0);
%函数默认信息
narginchk(7,12)
if nargin<7 || isempty(Method)Method='linear';%默认线性核函数
elseif nargin<8 || isempty(Rs)Rs=1.1*(max(x0)-min(x0))/N;%假设空间均匀分布
elseif nargin<9 || isempty(Npoly)Npoly=1;%默认拟合1次项
elseif nargin<10 || isempty(Npoly)ExtrapMethod='rbf';%默认不外插
elseif nargin<11 || isempty(Error)Error=0;%默认输入数据没有误差
end%选择外插包线
if strcmp(ExtrapMethod,'rbf')Inpoly=[];
elsek_ch=unique(k_ch);Inpoly=IsPointInShape3([x0(k_ch),y0(k_ch),z0(k_ch)],[x,y,z]);
end
if V<=0warning('输入散点过于集中');
end
%选择核函数
switch Methodcase 'linear'fun=@(RMat) Kernel_Linear(RMat,Rs);case 'gaussian'fun=@(RMat) Kernel_Gaussian(RMat,Rs);Error=-Error;%因为零点不是零,远点是0,所以这里误差为负case 'thin_plate'fun=@(RMat) Kernel_Thin_plate(RMat,Rs);case 'linearEpsR'fun=@(RMat) Kernel_LinearEpsR(RMat,Rs);Error=-Error;%因为零点不是零,远点是0,所以这里误差为负
end
%将原始数据分离出多项式项Npoly
if Npoly==0C=ones(N,1);%常数项wC=mean(P0);
elseif Npoly==1if N<3;warning('点数太少,建议Npoly等于0');endC=[ones(N,1),x0,y0,z0];%常数项+一次项wC=C\P0;
elseif Npoly==2if N<9;warning('点数太少,建议Npoly等于1');endC=[ones(N,1),x0,y0,z0,x0.^2,y0.^2,z0.^2,x0.*y0,x0.*z0,z0.*y0];%常数项+一次项+二次项wC=C\P0;
elseerror('只支持Npoly=0,1,2')
end
PC=C*wC;%多项式项
P1=P0-PC;
%计算距离矩阵
DisMat=squareform(pdist([x0,y0,z0]));
K3=fun(DisMat);%每一个核函数的中心点在节点上
K3=K3-Error*eye(N);%把误差函数加入w=K3\P1;%计算权重
%根据权重计算插值
P=zeros(size(x));
for k=1:N %计算每个核的贡献,然后叠加R_k=sqrt((x-x0(k)).^2+(y-y0(k)).^2+(z-z0(k)).^2);Pt=w(k)*fun(R_k );P=P+Pt;
end
NOut=length(P);
%再还原回多项式项
if Npoly==0C=ones(NOut,1);%常数项
elseif Npoly==1C=[ones(NOut,1),x,y,z];%常数项+一次项
elseif Npoly==2C=[ones(NOut,1),x,y,z,x.^2,y.^2,z.^2,x.*y,x.*z,z.*y];%常数项+一次项+二次项
end
PC2=C*wC;%再加上多项式项%判断外插方法
if isnumeric(ExtrapMethod)P(Inpoly)=P(Inpoly)+zC1(Inpoly);%内部的正常P(~Inpoly)=ExtrapMethod;%外部的固定值
elseif ischar(ExtrapMethod)switch ExtrapMethodcase 'rbf'P=P+PC2;%再加上多项式项case 'ploy'P(Inpoly)=P(Inpoly)+PC2(Inpoly);%内部的正常P(~Inpoly)=PC2(~Inpoly);%外部的直接用多项式值case 'nearest'P(Inpoly)=P(Inpoly)+PC2(Inpoly);%内部的正常%找到最近的点F = scatteredInterpolant(x(Inpoly),y(Inpoly),z(Inpoly),P(Inpoly),'nearest','nearest');%外部的直接插值P(~Inpoly)=F(x(~Inpoly),y(~Inpoly),z(~Inpoly));end
elseerror('未识别ExtrapMethod')
end
%检查结果
if max(abs(w))/max(abs(P1))>1e3warning('结果未收敛,建议调整误差Error');
elseif (max(P)-min(P))>5*(max(P0)-min(P0))warning('结果未收敛,建议增大区间Eps,或者调整误差Error');
end
endfunction z=Kernel_Linear(R,s)
%R距离
z=abs(R);%线性函数
endfunction z=Kernel_Gaussian(R,s)
%R距离
%s大概和采样点间距差不多就行,可以略大(更胖)
z=exp(-R.^2/2/s^2);%正态函数
endfunction z=Kernel_Thin_plate(R,s)
%R距离
z=R.^2.*log(R);%thin_plate
endfunction z=Kernel_LinearEpsR(R,s)
%R距离
%s大概和采样点间距差不多就行,可以略大(更胖)
s=2*s;%这里要更大
z=s-R;%线性函数
z(z<0)=0;
endfunction IsInShape=IsPointInShape3(A,points)
%判断点是否在某个三维凸多面体内
%A,凸多面体的顶点。points,N行3列。
%例子:A=[0,0,0;0,0,1;0,1,0;0,1,1;1,0,0;1,0,1;1,1,0;1,1,1];points=rand(1000,3)*3-1;
%IsInShape=IsPointInShape3(A,points)NPoints=size(points,1);%计算有多少个点
IsInShape=false(NPoints,1);
NConvhull=size(A,1);%计算凸包上有多少个点
BD_A=[min(A,[],1);max(A,[],1)];
for kp=1:NPointsP_k=points(kp,:);if any(P_k<BD_A(1,:)) || any(P_k>BD_A(2,:)) %如果超过A的矩形边界,说明肯定不在A内continueendNewA=[A;P_k];%把这个点加入新凸包计算NewP=max(unique(convhull(NewA,'Simplify',false)));%查看新凸包这个点会不会涉及到新点IsInShape(kp)=(NewP==NConvhull);
end
end
相关文章:
基于MATLAB的径向基函数插值(RBF插值)(一维、二维、三维)
基于MATLAB的径向基函数插值(RBF插值)(一维、二维、三维) 0 前言1 RBF思路2 1维RBF函数2.1 参数说明2.1.1 核函数选择2.1.2 作用半径2.1.3 多项式拟合2.1.4 误差项(光滑项) 3 2维RBF函数4 3维RBF函数 惯例声…...
flume拦截器
flume拦截器代码 1.依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apach…...
vue、elementui控制前一级选择后,后一级才会有数据
<el-form-item label"废物类型:"><el-select clearable v-model"queryForm.hswCateType" placeholder"请选择" change"industryCategoryChange" focus"industryCategoryFocus"><el-option v-for&…...
亲测influxdb安装为window后台服务
InfluxDB 安装 64bit:https://dl.influxdata.com/influxdb/releases/influxdb-1.7.4_windows_amd64.zip 解压安装包 修改配置文件 [meta]# Where the metadata/raft database is storeddir "D:/influxdb/meta"...[data]# The directory where the TSM…...
【LeetCode - 每日一题】823. 带因子的二叉树 (2023.08.29)
823. 带因子的二叉树 题意 元素都大于1,元素不重复。计数满足要求的二叉树(每个非叶结点的值应等于它的两个子结点的值的乘积)的数量。元素可以重复使用。 代码 自上而下动态规划。 所有元素大于1,所以不会有 自己自己自己 的…...
flutter 上传图片并裁剪
1.首先在pubspec.yaml文件中新增依赖pub.dev image_picker: ^0.8.75 image_cropper: ^4.0.1 2.在Android的AndroidManifest.xml文件里面添加权限 <activityandroid:name"com.yalantis.ucrop.UCropActivity"android:screenOrientation"portrait"andro…...
一台服务器上部署 Redis 伪集群
哈喽大家好,我是咸鱼 今天这篇文章介绍如何在一台服务器(以 CentOS 7.9 为例)上通过 redis-trib.rb 工具搭建 Redis cluster (三主三从) redis-trib.rb 是一个基于 Ruby 编写的脚本,其功能涵盖了创建、管…...
ealtek高清晰音频管理器(realtek高清晰音频管理器怎么设置win10)
本文为大家介绍realtek高清晰音频管理器(realtek高清晰音频管理器怎么设置win10),下面和小编一起看看详细内容吧。 我们都使用电脑来听音乐、看电影或者进行其他操作,但是如果我们觉得电脑产生的音效不够立体,我们就会想要去Realtek来设置音…...
微信小程序 scroll-view 组件的 bindscroll 不触发不生效
使用微信小程序基础组件中的scroll-view,但是滑动的时候 bindscroll 一直不生效。 <view class"container log-list"><scroll-view scroll-y style"height:100%;white-space:nowrap;" scroll-into-view"{{toView}}" enable…...
datax 删除分区数据,再写入MySQL脚本
#! /bin/bashDATAX_HOME/opt/module/datax#1、判断参数是否传入 if [ $# -lt 1 ] thenecho "必须传入all/表名..."exit fi #2、判断日期是否传入 [ "$2" ] && datestr$2 || datestr$(date -d -1 day %F)#DataX导出路径不允许存在空文件,…...
hyperf 十四 国际化
一 安装 composer require hyperf/translation:v2.2.33 二 配置 1、设置语言文件 文件结构: /storage/languages/en/messages.php /storage/languages/zh_CH/messages.php // storage/languages/en/messages.php return [welcome > Welcome to our applicat…...
C语言_初识C语言指针
文章目录 前言一、指针 ... 一个内存单元多大比较合适?二、地址或者编号如何产生?三、指针变量的大小 前言 内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。 所以为了有效的使用内存,就把内存划分成一个个…...
EMQX启用双向SSL/TLS安全连接以及java连接
作为基于现代密码学公钥算法的安全协议,TLS/SSL 能在计算机通讯网络上保证传输安全,EMQX 内置对 TLS/SSL 的支持,包括支持单/双向认证、X.509 证书、负载均衡 SSL 等多种安全认证。你可以为 EMQX 支持的所有协议启用 SSL/TLS,也可…...
4399面试总结C/C++游戏开发
主要流程 首先询问了C/C知识点 然后询问操作系统,计算机组成,数据结构,计算机网络哪两门熟悉 涉及的相关问题 多态的概念 tcp,udp? tcp,udp区别 tcp可靠,udp不可靠 tcp这个链接的过程? 一个TCP连接必须要经过三次“…...
hashlib 模块学习
hashlib 是 Python 标准库中用于散列和摘要算法的模块。散列算法将输入数据转换为固定长度的散列值(也称为摘要),并且对于相同的输入始终生成相同的散列值。这对于存储密码、数字签名、数据完整性验证等领域非常有用。以下是对 hashlib 模块的…...
大模型开发05:PDF 翻译工具开发实战
大模型开发实战05:PDF 翻译工具开发实战 PDF-Translator 机器翻译是最广泛和基础的 NLP 任务 PDF-Translator PDF 翻译器是一个使用 AI 大模型技术将英文 PDF 书籍翻译成中文的工具。这个工具使用了大型语言模型 (LLMs),如 ChatGLM 和 OpenAI 的 GPT-3 以及 GPT-3.5 Turbo 来…...
LeetCode 43题:字符串相乘
题目 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 "2", num2 "3&…...
基于java Swing 和 mysql实现的飞机订票系统(源码+数据库+ppt+ER图+流程图+架构说明+论文+运行视频指导)
一、项目简介 本项目是一套基于java Swing 和 mysql实现的飞机订票系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、项目文档、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过…...
Jmeter性能综合实战 —— 签到及批量签到
提取性能测试的三个方面:核心、高频、基础功能 签 到 请 求 步 骤 1、准备工作: 签到线程组n HTTP请求默认值n HTTP cookie 管理器n 首页访问请求n 登录请求n 查看结果树n 调试取样器l HTTP代理服务器 (1)创建线程组 …...
燃气管网监测系统,提升城市燃气安全防控能力
燃气是我们日常生活中不可或缺的能源,但其具有易燃易爆特性,燃气安全使用、泄漏监测尤为重要。当前全国燃气安全事故仍呈现多发频发态势,从公共安全的视角来看,燃气已成为城市安全的重大隐忧!因此,建立一个…...
【SQL】1731. 每位经理的下属员工数量 ( 新思想:确定左表,依次添加后续字段)
leetcode题目链接 注意点 确定左表(即,确定result表中的主键),依次添加后续字段。注意:主键可能是一个字段,也可能是多个字段COUNT(DISTINCT()),一般为了防止重复,使用COUNT计数时,…...
AMD Radeon RX 7000/6000系列显卡安装ROCm 调用CUDA
A卡用户画图炼丹、跑大模型甚至是跑机器学习、深度学习的有福了~ 注意:ROCm目前仅限在Linux系统下可用,Windows暂不支持 1. 安装ROCm RX6000系列及以下显卡使用ROCm 5.4.2稳定版本命令 【支持包括桌面级AMD Radeon RX6950XT、RX6900XT、RX6800XT、RX6…...
钉钉小程序引用阿里巴巴图标
2.打开的界面如图,先建一个iconfont.acss文件,全选浏览器打开的样式代码,复制粘贴进新建的iconfont.acss文件中 3.使用...
深入了解Nginx:高性能的开源Web服务器与反向代理
一、Nginx是什么 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,也可以作为负载均衡器和HTTP缓存服务器使用。它采用事件驱动、异步非阻塞的处理方式,能够处理大量并发连接和高流量负载ÿ…...
vue3 自定义显示内容
vue3 自定义显示内容 vue3 自定义显示内容示例uni-app封装自定义内容组件 vue3 自定义显示内容 在 Vue 3 中,你可以通过插槽(Slot)来自定义组件的显示内容。 插槽允许你将额外的内容插入到组件的特定位置,从而实现更灵活的组件…...
视频行为分析——视频图像转换与ffmpeg相关操作
工具类说明 1. 图像视频转换 1.1 视频输出gif from moviepy.editor import VideoFileClip # 设置输入视频文件路径和输出GIF文件路径 input_video video.avi output_gif output.gif # 读取视频文件 video VideoFileClip(input_video) # 将视频保存为GIF文件 video.write_…...
Bean 生命周期
Bean 生命周期 一、Bean 实例化的基本流程 Spring容器在进行初始化时,会将xml配置的的信息封装成一个BeanDefifinition对象,所有的BeanDefifinition存储到一个名为beanDefifinitionMap的Map集合中去,Spring框架在对该Map进行遍历࿰…...
JavaScript原型链污染
前言 在浏览某个论坛的时候,第一次看到了JavaScript原型链污染漏洞。当时非常的好奇,当时我一直以为js作为一种前端语言,就算存在漏洞也是针对前端,不会危害到后端,因此我以为这种漏洞危害应该不大。可当我看到他的漏…...
【Java】设计模式之单例模式与工厂模式
1、设计模式概念及分类 简单来说设计模式是被广大程序员们总结并认可的编码套路,其中最常用的莫过于单例模式与工厂模式,而单例模式也有更加细的分类,一起来学习一下这些模式的用法和特点吧。 2、单例模式 一个类只能被实例化出来一个对象…...
web自动化框架:selenium学习使用操作大全(Python版)
目录 一、浏览器驱动下载二、selenium-python安装(打开网站、操作元素)三、网页解析(HTML、xpath)四、selenium基本操作1、元素定位八种方法2、元素动态定位3、iframe切换4、填充表单_填充文本框5、填充表单_单选按钮6、填充表单_…...
boringssl EVP_aes_128_ecb实现
最近学习boringssl,发现没找到EVP_aes_128_ecb在哪里实现的 饶了一大圈,发现它的定义很无语 #define EVP_CIPHER_FUNCTION(keybits, mode) \const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \return aes_##keybits##_##mode##_gene…...
vxe-table中树形结构
如图,同事让帮忙实现一个需求 从二级树节点开始,同时选中的只能有一个二级树节点,选中的二级树节点之下的子节点都可以被选中。否则不能被选中 直接上代码 需要注意的是,文中树状图传递的数据是打平的数据,设置代码是…...
Linux命令查看CPU、内存、IO使用情况简单介绍
文章目录 1. CPU相关介绍1.1 物理CPU1.2 物理CPU内核1.3 逻辑CPU1.4 几核几线程1.5 CPU设计图 2. top 查看系统负载、CPU使用情况2.1 系统整体的统计信息2.2 进程信息2.3 top命令使用 3. lscpu 显示有关 CPU 架构的信息4. free 查看内存信息5. iostat 查看io信息 1. CPU相关介绍…...
RPC框架的核心是什么
文章目录 什么是 RPC封装的艺术(如何隐藏底层逻辑)协议的实现序列化和反序列化(编解码)总结 什么是 RPC 首先思考这样一个问题,假设你不知道任何框架,现在有两台机器,每台机器上有一个服务&…...
直播、AI赋能,美团披着荆棘前行
随着互联网流量红利逐渐消退,阿里、抖音、腾讯、拼多多、快手、小红书等各赛道玩家,为了寻求新的增量,纷纷“卷”向本地生活,开始入侵美团的腹地。然而,哪怕巨头环伺,美团仍然展现出了其独特的竞争力&#…...
提升代码逻辑的感觉——python循环语句
提升代码逻辑的感觉——python循环语句 简介 循环是编程中的一个非常重要的概念,它用于处理重复性任何和迭代草错,通过循环我们能优化并简化代码,提高代码的可维护性,在Python中循环是一种控制结构,允许我们重复执行…...
【ARM Coresight 系列文章 20 -- linux perf 与 ARM coresight】
文章目录 1.1 Perf Introduction1.1.1 Perf 架构图1.1.2 Perf Tools 介绍1.1.3 Perf 命令介绍1.2 Events1.2.1 Perf 与 PMU 的关系1.2.2 Hardware events1.2.1.1 linux perf 事件分类1.2.2 Software Events1.2.3 Tracepoint Events1.3 Perf 工具使用1.4 用户态开发1.4.1 用户态…...
微服务之Nacos
1 版本说明 官网地址: https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 1.1 2021.x 分支 适配 SpringBoot 2.4, Spring Cloud 2021.x 版本及以上的Spring Cloud Alibaba 版本如下表(最新版本用*标记&am…...
jvm 新生代的区域划分
虚拟机将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次分配内存只使用 Eden 和其中一块 Survivor。发生垃圾收集时,将 Eden 和 Survivor 中仍然存活的对象一次性复制到另外一块 Survivor 空间上,然后直接清理掉 Eden 和已用过…...
【C++】对于string的补充(成员函数c_str()、大小写转换、字符串和实数之间的相互转换)
前言 本篇文章记录的是一些关于string的补充说明 string与const char*之间的相互转换 const char* 转换成string 在C中存在着从const char到string的隐式类型转换,换句话说,如果一个函数的参数类型是string类,直接传入const char类型的参…...
华为OD机试真题【羊狼农夫过河】
1、题目描述 【羊、狼、农夫过河】 羊、狼、农夫都在岸边,当羊的数量小于狼的数量时,狼会攻击羊,农夫则会损失羊。农夫有一艘容量固定的船,能够承载固定数量的动物。要求求出不损失羊情况下将全部羊和狼运到对岸需要的最小次数。…...
【线性代数-3Blue1Brown】- 5 三维空间的线性变换
飞书原文档:Docs...
Maven入门教程(二):idea/Eclipse使用Maven
Maven入门教程(一):安装Maven环境 4.开发工具配置 4.1 idea配置 idea有多个版本,配置是一样的,只是配置页面的入口不一样 旧版idea 新版idea 4.2 Eclipse配置 打开Eclipse,菜单中选择:Window -> Preference ->…...
【MySQL】MySQL里的用户账户和角色是什么?如何管理?
用户(user)验证和授权创建用户账户连接服务器查看用户账户设置 角色(role)创建角色 操作用户帐户和角色重命名删除 感谢 💖 用户(user) 在MySQL中,用户是数据库访问的主要实体。每个…...
vbs病毒
vbs脚本:VBS脚本病毒原理分析和防范 疯狂代码 http://CrazyCoder.cn/ Sh t t p : / C r a z y C o d e r . c n / S e c u r i t y / Ar t i c l e 7 2 0 0 8 . h t m l 网络流行让我们世界变得更加美好但它也有让人不愉快时候当您收到封主题为1LoveYou” 邮件用兴奋 得几乎快发…...
用Java实现Huffman编码
文章目录 前言一、实现思路二、准备Huffman结点三、主要实现 前言 在使用http1.1协议传输数据的时候,会有一些固定的字段,比如cookie、编码方式、接收的数据类型,另外会有一些大量重复的字段造成请求报文过于冗长,为了解决这个问…...
day-04 基于UDP的服务器端/客户端
一.理解UDP (一)UDP套接字的特点 UDP套接字具有以下特点: 无连接性:UDP是一种无连接的协议,这意味着在发送数据之前,不需要在发送方和接收方之间建立连接。每个UDP数据包都是独立的,它们可以独…...
FFmpeg rtp rtp_mpegts的区别
rtp 在FFmpeg中,rtpenc是一个用于将音视频数据封装成RTP(Real-time Transport Protocol)数据包并发送到网络上的编码器。RTP是一种用于实时传输音视频数据的协议,常用于视频会议、流媒体等场景。 rtpenc可以将音视频数据封装成R…...
【链表OJ】相交链表 环形链表1
前言: 💥🎈个人主页:Dream_Chaser~ 🎈💥 ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 一.leetcode 160. 相交链表 1.问题描述: 2.解题思路: 二.leetcode 141.环形链表 …...
DevOps之自动化测试
什么是自动化测试? 明确一下自动化测试不是什么。自动化测试不是指自动化生成测试代码,而是自动化地执行由开发人员或测试人员编写的测试代码。正如下面这句谚语:“绝不要手工去做任何可以被自动化处理的事情。——Curt Hibbs” 之前是由人…...