How to smooth surf?
145 views (last 30 days)
Show older comments
I'm having a surface plot with many spikes. I was wondering what I can do to smooth it. interp2 might be a solution, I guess, but I'm having problems with the dimensions. Here is a part of the program:
a=0;
b=2;
c=0;
d=4;
M=40;
N=60;
hx=(b-a)/(M+1);
hy=(d-c)/(N+1);
alpha=inv(A)*L;
sol=zeros((M+2),(N+2));
for k=1:N*M
i=rem(k,M);
if i==0
i=M;
end
j=(k-i)/M+1;
newsol(i,j)=alpha(k);
end
sol(2:M+1,2:N+1)=newsol;
[X,Y]=meshgrid(a:hx:b,c:hy:d);
C = 1 + (X <= 0.25 | X >= 1.75);
surf(X,Y,sol',C);
colormap([1 0 0; 0 0 1]);
hold on
plot(0,0,'ko','MarkerSize',10,'MarkerFaceColor','black')
text(0,0,'(0,0)','Fontsize',20,'Color','k', 'Horiz','left','Vert','top')
plot(2,0,'k>','MarkerSize',10,'MarkerFaceColor','black')
text(2,0,'x_1','Fontsize',20,'Color','k', 'Horiz','left','Vert','top')
plot(0,4,'k<','MarkerSize',10,'MarkerFaceColor','black')
text(0,4,'x_2','Fontsize',20,'Color','k', 'Horiz','left','Vert','top')
xlabel('cm')
ylabel('cm')
zlabel('longitudinal fluid velocity (cm/s)')
2 Comments
Answers (1)
John D'Errico
on 30 Oct 2022
Edited: John D'Errico
on 30 Oct 2022
interp2 does NO smoothing. It is NOT designed to smooth anything, and would NOT be appropriate, because interpolation does not change any of your data.
And all you post is code that nobody can execute. So helping you is difficult. If you really want help, then make it easy to get help. All we see is a picture, with no data provided.
The simplest way to perform a 2-dimensional smoothing operation in MATLAB is to use conv2. But you need to be careful around the edges, so there is a fix. Since you provide no data at all, I'll make something up.
[X,Y] = meshgrid(1:100);
Z = sin((2*X-3*Y)/75) + randn(size(X))/10;
surf(Z)
As I said, the simple idea is to use a convolution in 2-d, with a Gaussian smoothing kernel. That will blur out the noise, and if the noise is random, then a blur will be good, as long as the signal in your surface is slowly varying. But you need to consider what happens at the edges. conv2 will effectively insert zeros outside of the array. And that will cause a bias in the results around the borders.
[xk,yk] = meshgrid(-5:5);
K = exp(-(xk.^2 + yk.^2)/10); K = K/sum(K(:));
surf(K)
The smoothing kernel I'll use is a simple truncated 2-d Gaussian shape, then rescaled to sum to 1. The size of that smoothing kernel is a factor, since a larger (wider) kernel would do more smoothing.
Now we can use this to perform a blurring smooth in the array Z. But if I just use conv2 directly with that kernel, maintining the same size array. we have a problem.
Zhat1 = conv2(Z,K,'same');
surf(Zhat1)
As you can see, there is a band around the edges that is clearly biased towards zero. We can fix that as I show below.
Zhat2 = conv2(Z,K,'same')./conv2(ones(size(Z)),K,'same');
surf(Zhat2)
As you can see, the result is much smoother now. Not perfect because the original array was pretty well contaminated with noise, but it is still smooth out to the edges of the array, with no biased band around the edge.
You can use other schemes of course, perhaps based on median filters. I could think of many ways. In fact, you could even download my own gridft from the file exchange, which can smooth very nicely.
1 Comment
Lorenzo Melito
on 3 Jan 2024
@John D'Errico, fantastic answer! Thanks a lot for the very informative process description!
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!