I am trying to plot a 3d view of a very large CT dataset. My data is in a 3d matrix of 2000x2000x1000 dimension. The object is surrounded by air, which is set to NaN in my matrix.
I would like to be able to see the greyscale value of the surface of the object (no isosurface) but I cannot quite work out how to do that in Matlab. Can anyone help me please?
Given that I a dealing with a huge matrix and I am only interested in the surface of the object, does anyone know a good trick how to reduce the size of my dataset?
The function surf(X,Y,Z) allows you to plot 3d data, where (X,Y) gives the coordinates in the x-y-plane while Z gives the z-coordinate and the surface color.
By default the function does not plot anything for the NaN entries, so you should be good to go with the surf function.
To set the surf-function to use a grayscale plotting use:
surf(matrix3d);
colormap(gray);
This plots the matrix in a surface plot and sets the colormap to grayscale.
In addition, as I understand your data, you might be able to eliminate entire plane-segments in your matrix. If for instance the plane A(1,1:2000,1:1000) is NaN in all entries you could eliminate all those entries (thus the entire Y,Z-plane in entry X=1). This will however require some heavy for loops, which might be over the top. This depends on how many data matrices you have compared to how many different plot you want for each matrix.
I will try to give you some ideas. I assume lack of a direct 3D "surface detector".
Since you have a 3D matrix where XY-planes are CT scan slices and each slice is an image, I would try to find edges of each slice say with edge. This would require some preprocessing like first thresholding each slice image. Then I can either use scatter3 to display the edge data as a 3D point cloud or delaunay3 to display the edge data as a surface.
I hope this will help you achieve what you are asking for.
I managed to get it working:
function [X,Y,Z,C] = extract_surface(file_name,slice_number,voxel_size)
LT = imread(file_name);%..READ THE 2D MAP
BW = im2bw(LT,1);%..THRESHOLD TO BINARY
B = bwboundaries(BW,8,'noholes');%..FIND THE OUTLINE OF THE IMAGE
X = B{1}(:,1);%..EXTRACT X AND Y COORDINATES
Y = B{1}(:,2);
indices = sub2ind(size(LT),X,Y);%..FIND THE CORRESPONDING LINEAR INDICES
C = LT(indices);%..NOW READ THE VALUES AT THE OUTLINE POSITION
Z = ones(size(X))*slice_number;
I can then plot this with
figure
scatter3(X,Y,Z,2,C)
Now the only thing I could improve is to have all these points in the scatter plot connected with a surface. #upperBound you suggested delaunay3 for this purpose - I cannot quite figure out how to do this. Do you have a tip?
Related
I have a set of data vectors z that has this 2d plot
How would I go about embed this set of data into a 3d plot like this in matlab? I'm asking for advice and suggestions. The theory I'm trying to employ is "for each data vector~zj, “copies” the data vector intothe first two entries of a 3D data vector~yjand then computes the squared length of~zj as the third entry of~yj. " or kernel trick.
Your 2d data will somehow be in the form, that you have x-coordinates and y-coordinates. Let's say you have a vector x and a vector y for simplification.
As you found out the plot3-function proivdes functionality to plot arbitrary points in 3d without the need of generating a mesh. What you need additionally is a third vector z with data for the 3rd dimension.
So what else can you do? The thing I am thinking about is rotating the plane you are plotting you "2d" data:
Rotational matrices can be seen here:
https://en.wikipedia.org/wiki/Rotation_matrix
Here is a sample dataset.
x = linspace(10,20,50);
y = linspace(10,20,50);
z = cos(linspace(0,2*pi,50));
time = linspace(1,60,50);
sci_temp = randi(100,50,1);
x,y,z is position, and sci_temp is temperature data.
I wonder how to draw trajectory over xyz position with sci_temp data.
I try interpolate data, so I get 2D interpolate time vs z with sci_temp plot.
S = TriScatteredInterp(time',z',sci_temp);
[t_mesh z_mesh] = meshgrid(time,z);
tz_mesh = S(t_mesh, z_mesh);
pcolor(t_mesh,z_mesh,tz_mesh)
What I want to get is a 2D (time vs sci_temp) section map on a xyz 3D plot. Like this image.
how to show trajectory over sci_temp in 3D plot?
Is there anyone can help me?
Thanks
First, you are doing your interpolation slightly wrong, you don't want to interpolate over the mesh created by
meshgrid(time,z);
Because it will duplicate values. You want to interpolate over the mesh created by
meshgrid(time,linspace(min(z),max(z),50));
Once you get the interpolated values like:
You can plot them in 3D space with the surface function, you just need to make sure to give x and y coordinates appropriately
surface(repmat(x,50,1),repmat(y,50,1),zmesh,tzmesh)
You can even have more complex paths, for example, same data but y=z
Edit: Also I forgot to mention, I'd suggest you to use scatteredInterpolant instead of TriScatteredInterp. It gives you more control over the interpolation
I have a 3D matrix of a MRI image and used matlab edge function and it gave me a 3D matrix as follow which some of the points are 1 (means edges).
I want to show this surface in matlab but I don't know that how I should do this. I know that I should use surf.
As #bdecaf said, you can use find to determine the height of the points, or in other words, in which of the 100 layers does the point lie. You can do that as follows:
z1=zeros(30,100);
temp=find(b);
[row,col,layer]=ind2sub(size(b),temp);
for i=1:size(x,1)
z1(row(i),col(i))=layer(i);
end
You can get an image as follows:
I need to plot a 3D figure with each data point colored with the value of a 4th variable using a colormap. Lets say I have 4 variables X,Y,Z and W where W = f(X,Y,Z). I want a 3D plot with X, Y, and Z as the three axis. The statement scatter3(X,Y,Z,'filled','b') gives me a scatter plot in 3D but I want to incorporate the value of Z in the graph by representing the points as an extra parameter (either with different areas :bigger circles for data points with high value of Z and small circles for data points with low value of Z or by plotting the data points with different colors using a colormap). However, I am a novice in MATLAB and dont really know how to proceed. Any help will be highly appreciated.
Thanks in advance!
So just use z for the size vector (4th input) as well as the color vector (5th input):
z = 10*(1:pi/50:10*pi);
y = z.*sin(z/10);
x = z.*cos(z/10);
figure(1)
scatter3(x,y,z,z,z)
view(45,10)
colorbar
The size vector needs to be greater 0, so you may need to adjust your z accordingly.
You are already nearly there... simply use
scatter3(X,Y,Z,s,W);
where s is the point size (scalar, e.g. 3) and W is a vector with your W values.
You might also want to issue an
set(gcf, 'Renderer','OpenGL');
where gcf gets your current figure you are plotting in to significantly increase responsiveness when scattering a lot of data.
I have a 3D data set of a surface that is not a function graph. The data is just a bunch of points in 3D, and the only thing I could think of was to try scatter3 in Matlab. Surf will not work since the surface is not a function graph.
Using scatter3 gave a not so ideal result since there is no perspective/shading of any sort.
Any thoughts? It does not have to be Matlab, but that is my go-to source for plotting.
To get an idea of the type of surface I have, consider the four images:
The first is a 3D contour plot, the second is a slice in a plane {z = 1.8} of the contour. My goal is to pick up all the red areas. I have a method to do this for each slice {z = k}. This is the 3rd plot, and I like what I see here a lot.
Iterating this over z give will give a surface, which is the 4th plot, which is a bit noisy (though I have ideas to reduce the noise...). If I plot just the black surface using scatter3 without the contour all I get is a black indistinguishable blob, but for every slice I get a smooth curve, and I have noticed that the curves vary pretty smoothly when I adjust z.
Some fine-tuning will give a much better 4th plot, but still, even if I get the 4th plot to have no noise at all, the result using scatter3 will be a black incomprehensible blob when plotted alone and not on top of the 3D contour. I would like to get a nice picture of the full surface that is not plotted on top of the 3D contour plot
In fact, just to compare and show how bad scatter3 is for surfaces, even if you had exact points on a sphere and used scatter3 the result would be a black blob, and wouldn't even look like a sphere
Can POV-Ray handle this? I've never used it...
If you have a triangulation of your points, you could consider using the trisurf function. I have used that before to generate closed surfaces that have no boundary (such as polyhedra and spheres). The downside is that you have to generate a triangulation of your points. This may not be ideal to your needs but it definitely an option.
EDIT: As #High Performance Mark suggests, you could try using delaunay to generate a triangulation in Matlab
just wanted to follow up on this question. A quick nice way to do this in Matlab is the following:
Consider the function d(x, y, z) defined as the minimum distance from (x, y, z) to your data set. Make sure d(x, y, z) is defined on some grid that contains the data set you're trying to plot.
Then use isosurface to plot a (some) countour(s) of d(x, y, z). For me plotting the contour 0.1 of d(x, y ,z) was enough: Matlab will plot a nice looking surface of all points within a distance 0.1 of the data set with good lighting and all.
In povray, a blob object could be used to display a very dense collection of points, if you make them centers of spheres.
http://www.povray.org/documentation/view/3.6.1/71/
If you want to be able to make slices of "space" and have them colored as per your data, then maybe the object pattern (based on a #declared blob object) might do the trick.
Povray also has a way to work with df3 files, which I've never worked with, but this user appears to have done something similar to your visualization.
http://paulbourke.net/miscellaneous/df3/