I have 3 matrices(129x129) corresponding to x, y and z coordinates. I used the function mesh
mesh(x,y,z);
to plot the corresponding figure. It comes out to be a sphere. Now, I have another set of x, y, z(again 129) which gives a different sphere. What I want is to use interpolation in MATLAB to obtain the figures that come in between. I looked at the function interp3 in MATLAB but could not figure out what to do with it.
It seems like you are interested in the evolution of the surface z(x,y) from one surface z0 to another z1. I would suggest the following process
T = 5; % number of "time steps" from z0 to z1
t = linspace( 0, 1, T );
for ii = 1 : T
zt = t(ii).*z1 + (1-t(ii)).*z0;
mesh( x, y, zt ); title( sprintf( 'time %d', ii ) );
drawnow;
pause(1); wait a sec
end
Related
I have this Binary image bw:
edges of an object to carry out some measurements. But firstly I have to do curve fitting for both edges. The result should be two smooth curves representing edges.
I have the indices for each edge but I can not use them in making x-y data to be input data to a fitting function. I mean they are not x and f(x), actually, they all have the same value (1) with different positions. It is not right to say [x y]=find(BW) ; y here is not the value at x, but for sure there should be a way to use them to some kind of scale the binary image. I seem confused and I'm stuck here.
Any recommendations?
Why not use polyfit?
[y x] = find( bw ); %// get x y coordinates of all curve points
There are two small "tricks" you need to use here:
You have two curves, thus you need to split your data points to the left and right curves
right = x<300;
xr = x(right);
yr = y(right);
xl = x(~right);
yl = y(~right);
Since your curves are close to vertical, it would be better to fit x=f(y) rather than the "classic" y=f(x):
pr = polyfit( yr, xr, 3 ); %// fit 3rd deg poly
pl = polyfit( yl, xl, 3 );
Now you can plot them
yy = linspace( 1, size(bw,1), 50 );
figure; imshow(bw, 'border', 'tight' );
hold all
plot( polyval( pr, yy ), yy, '.-', 'LineWidth', 1 );
plot( polyval( pl, yy ), yy, '.-', 'LineWidth', 1 );
And you get:
If you want to create a new refined mask from the estimated curves, you can do the following:
yy = 1:size(bw,1); %// single value per row
xxr=polyval(pr,yy); %// corresponding column values
xxl=polyval(pl,yy);
Set a new mask of the same size
nbw = false(size(bw));
nbw( sub2ind(size(bw),yy,round(xxr)) )=true;
nbw( sub2ind(size(bw), yy, round(xxl) )) = true;
And the result
figure;imshow(nbw,'border','tight');
Probably it's scatter3 what I don't understand. I have a matrix of which all slices but the last are NaNed (M(:,:,1:10) = NaN;) and then it's permuted switching first and last dimension. So there are only values in M(11,:,:). I expect all plotted values to be in the Y-Z plane at x==11, but the plot looks differently (see code and picture below). Any explanations?
M = rand(22,55,11);
M(:,:,1:10) = NaN;
M = permute(M,[3 2 1]);
shape = size(M)
[x, y, z] = meshgrid(1:shape(1), 1:shape(2), 1:shape(3));
scatter3(x(:), y(:), z(:), 4, M(:), 'fill');
view([60 60]);
xlabel('X ', 'FontSize', 16);
ylabel('Y ', 'FontSize', 16);
zlabel('Z ', 'FontSize', 16);
The explanation is that meshgrid switches x and y:
From meshgrid documentation:
MESHGRID is like NDGRID except that the order of the first two input
and output arguments are switched (i.e., [X,Y,Z] = MESHGRID(x,y,z)
produces the same result as [Y,X,Z] = NDGRID(y,x,z)).
At first sight, this should result in a plot with values in the X-Z plane at y==11 (i.e. x and y interchanged with respect to what you initially expected). But note that your code treats x and y sizes incorrectly (because of meshgrid). This has the additional effect that the x and y coordinates get "shuffled" and you don't see a plane (even in X-Z), but rather a lattice.
So the solution is to use ndgrid, which doesn't do any switching. Just replace "meshgrid" by "ndgrid" in your code. The resulting figure is now as expected:
In matlab, I have a vector, say x and a function of x say y. I want to plot x and y in matlab.
The problem is I want smooth curve (not in a sense of smooth texture but differentiable, and without sharp bends). Matlab, with plot, simply joins the points and the plotted curve has sharp bends.
Is there a way I can resolve this?
Following Dan and wakjah, what you need is to interpolate x and y to more sample points
plot( x, y, '+r' ); % plot the original points
n = numel(x); % number of original points
xi = interp1( 1:n, x, linspace(1, n, 10*n) ); % new sample points
yi = interp1( x, y, xi );
hold all;
plot( xi, yi ); % should be smooth between the original points
Question: is it possible to illustrate an image on non-uniform axis?
Details:
I need to illustrate a multidimensional timeseries as an image. But the time grid of this timeseries is very non-uniform. Here is an example:
m = 10;
n = 3;
t = sort(rand(m, 1)); % non-uniform time
values = randn(m, n); % some random values
The figure, plot(t, values); handles it well.
But imagesc() converts t into uniform time between t(1) and t(end) according to documentation:
imagesc(x,y,C) displays C as an image and specifies the bounds of the
x- and y-axis with vectors x and y.
Therefore, the command:
figure, imagesc(t, 1 : n, values'); colorbar;
illustrates the image on uniform time grid.
Edit: It's possible to re-sample the timeseries with higher uniform resolution. But my timeseries is already very large.
There is pcolor function in MATLAB. This function does exactly what you're asking.
m = 10;
n = 3;
t = sort(rand(m, 1)); % non-uniform time
values = randn(m, n); % some random values
figure
plot(t, values);
figure
pcolor(t, 1 : n, values');
colorbar;
try uimagesc from the file exchange.
Solution
Try using surface for non-uniform spacing.
First, create a 3D xyz surface of the same size as your input data:
m = 10;
n = 3;
t = sort(rand(m, 1)); % non-uniform time
values = randn(m, n); % some random values
x = repmat(t,1,n);
y = repmat(1:n,m,1);
z = zeros(size(y));
Then, colormap your values. There is a nice tool posted to the mathworks file exchange, real2rgb, that can do this for you:
cdata = real2rgb(values); % Where size(cdata) = [m n 3]
Lastly, plot the surface. You can even get fancy and set the transparency.
surface(x,y,z,cdata,'EdgeColor','none','FaceColor','texturemap',...
'CDataMapping','direct');
alpha(0.3)
I would like to plot a 3D figure of a hyperbole that is cut down at the bottom of it in the following way (figure)
any ideas?
OK, here's my stab at your problem. This is the experimental script I've been using:
%%# first part
%#------------------
clf
%# use cylinder to get unit cone
[x,y,z] = cylinder( linspace(1, 0, 1e3), 1e3);
%# intersect the cone with this surface
inds = z < (cos(x).*sin(pi*y/2)+1)/4;
x(inds) = NaN; %# remove all corresponding
y(inds) = NaN; %# indices, in all arrays
z(inds) = NaN;
%# Now plot the cone. Note that edges are ugly when
%# using a large number of points
surf(x, y, z, 'edgecolor', 'none');
%%# second part
%#------------------
hold on
%# the surface to intersect the cone with
f = #(x,y) (cos(x).*sin(pi*y/2)+1)/4;
%# add the surfacfe to the cone plot
[x,y] = meshgrid( linspace(-1,1, 1e3) );
surf(x,y, f(x,y), 'edgecolor', 'none')
The first part shows a cone intersected with a curve. You might want to tinker a bit with the curve to get the overall shape right, which is what the second part is for.
If you want a paraboloid (or other), just use
[x,y] = meshgrid( linspace(-1,1, 1e3) );
z = 1-x.^2-y.^2; %# or whatever other equation
instead of the cylinder command.