Is it possible to separate the different level contours given by imcontour in Matlab? - matlab

I am using the image processing toolbox and the
imcontour
function. I have 2 questions.
1) what are the levels exactly ?
2) How can I separate the different level contours given in c when using
[c,h]=imcontour(Img,3)
When displaying the contour, Matlab presents different colors for the different levels. I would like to retrieve the coordinates of the inner contour only, how can I do this ? On this image, I presented the output of the imcontour function with level 1, level 2, level 3 and level 4. I am only interested in the yellow part of the level 3 image.

Yes, this is possible, but not really trivial. The C matrix returned by [C,h]=imcontour(Img,3) is the ContourMatrix. This is a 2xN array containing all vertices for the lines drawn.
Say you have 3 contours (as per your second input argument to imcountour), and want to find the vertices to the 3rd contour (which is what I presume is the yellow line). You need to skip ahead two contours first:
index = 1;
for ii=1:2 % skip 2 contours
index = index + 1 + C(2,index);
end
N = C(2,index); % number of vertices for 3rd contour
level = C(1,index); % grey-level of 3rd contour
vertices = C(:,index+(1:N));

Related

Heights of automatic contour lines in Matlab

I do not know if this is the exact site for my question, but as far as I understand the FAQ correctly one can ask questions regarding one specific software algorithm from one specific language.
I have several 2D matrices (containing NaN's) for which I want to draw one iso-/contour line in Matlab. For this I use the implemented contour() function in the following way, where Matlab automatically chooses the level of the contour lines and I only specify the number of levels I want to display:
Contourline=contour(MyData,1);
The results are looking fine, but I was wondering now how the exact height of my contour line is chosen and if the heights are comparable between different matrices, meaning are they always drawn at e.g. 50 % of the maximum value?
The contour() function also allows to manually set a height for the contour line. Doing this (by setting the heights to x % of the maximum value in my matrix), the results appear not as fitting as the ones from the automated approach (regardless of the value of 'x' I choose).
Thanks!
Edit:
My question aims at the underlying algorithm implemented in the contour() function when the number of levels is set to 1. This produces very good results for my data, meaning the function draws one line (or more if the heights are the same) which kinda catches the distribution in my data (Image). If I try to set the heights manually contour(myData,[X X])this works,but not for all of my matrices in contrast to the automated mode when I only specify the number of levels contour(myData,1). So I am quite happy with those results, but if anybody asked me how I analyzed my data I want to give them a more mathematically sound answer than just: "I chose this function in this program".
In general:
I want to know how this height is chosen for the automated mode and if there might be a part in the code which makes it undesirable to compare the contour lines for different matrices. The documentation only states that the heights are set automatically, but not exactly how.
You can use a vector to specify at what height to draw the contours
% Draws contours at height = 1 and 2
contour(data, [1 2])
If you want only one height, just provide that value twice
% Contour at height 1
contour(data, [1 1])
If you want to just specify the number of levels to draw (and not the heights), you can use the LevelList property of the graphics object to determine at what height the lines were drawn.
[c, h] = contour(data, 1);
levels = get(h, 'LevelList')
You can also use the LevelList property to modify the height of the levels after creation.
[c, h] = contour(data, 1);
% A level at 2
set(h, 'LevelList', 2);
% Or two levels
set(h, 'LevelList', [1 2])
Update
As far as how MATLAB selects the levels when you specify the number of levels, it creates equally spaced levels between the minimum and maximum of the input data using the following formula:
minimum = min(real(double(data(:)));
maximum = max(real(double(data(:)));
tmp = linspace(minimum, maximum, nLevels + 2);
levels = tmp(2:end-1);

MeshGrid for Triangle Elements

I want to build a contourf plot of a certain aspect in my Plate. The plate is divided in triangle elements, which I have the coordinates (x,y) of each knot of the triangle.
So, How can I make a meshgrid for my knots so I can make my contourf plot?? I have the coordinates of everything and have the value of my function Z in each knot. (I'm a beginner in Matlab, sorry for this "basic" question)
If your goal is just to visualise the triangles then there is another way that's probably simpler and more robust (see the end of this post).
If you definitely need to generate contours then you will need to interpolate your triangular mesh over a grid. You can use the scatteredInterpolant class for this (documentation here). It takes the X and Y arguments or your triangular vertices (knots), as well as the Z values for each one and creates a 'function' that you can use to evaluate other points. Then you create a grid, interpolate your triangular mesh over the grid and you can use the results for the countour plot.
The inputs to the scatteredInterpolanthave to be linear column vectors, so you will probably need to reshape them using the(:)`notation.
So let's assume you have triangular data like this
X = [1 4; 8 9];
Y = [2 3; 4 5];
Z = [0.3 42; 16 8];
you would work out the upper and lower limits of your range first
xlimits = minmax(X(:));
ylimits = minmax(Y(:));
where the (:) notation serves to line up all the elements of X in a single column.
Then you can create a meshgrid that spans that range. You need to decide how fine that grid should be.
spacing = 1;
xqlinear = xlimits(1):spacing:xlimits(2);
yqlinear = ylimits(1):spacing:ylimits(2);
where linspace makes a vector of values starting at the first one (xlimits(1)) and ending at the third one (xlimits(2)) and separated by spacing. Experiment with this and look at the results, you'll see how it works.
These two vectors specify the grid positions in each dimension. To make an actual meshgrid-style grid you then call meshgrid on them
[XQ, YQ] = meshgrid(xqlinear, yqlinear);
this will produce two matrices of points. XQ holds the x-coordinates of every points in the grid, arranged in the same grid. YQ holds the y-coordinates. The two need to go together. Again experiment with this and look at the results, you'll see how it works.
Then you can put them all together into the interpolation:
F = scatteredInterpolant(X(:), Y(:), Z(:));
ZQ = F(XQ, YQ);
to get the interpolated values ZQ at each of your grid points. You can then send those data to contourf
contourf(XQ, YQ, ZQ);
If the contour is too blocky you will probably need to make the spacing value smaller, which will create more points in your interpolant. If you have lots of data this might cause memory issues, so be aware of that.
If your goal is just to view the triangular mesh then you might find trimesh does what you want or, depending on how your data is already represented, scatter. These will both produce 3D plots with wireframes or point clouds though so if you need contours the interpolation is the way to go.

Find Overlapping Region between 3-Dimensional Shapes

I'm currently plotting 2 separate 3-dimensional amorphous blobs which overlap each other. I have created the blobs by deforming a unit circle (as you can see in the code provided below). My question is: is there an easy way to isolate the overlapping region? I need to isolate the overlapping region and then color it differently (as in turn the region green, for example) to clearly show where the overlap is. My actual program has many shapes that overlap, however for the sake of simplicity, i have produced the following code to illustrate what i am trying to do:
% Create Sphere with 100 points
N = 100; % sphere grid points
[X,Y,Z] = sphere(N); % get x,y,z coordinates for sphere
num=size(X,1)*size(X,2); % get total amount of x-coordinates (m*n)
% Loop through every x-coordinate and apply scaling if applicable
for k=1:num % loop through every coordinate
value=X(k); % store original value of X(k) as value
if value<0 % compare value to 0
X(k)=0.3*value; % if < 0, scale value
end
end
% Loop through every z-coordinate and apply scaling if applicable
for k=1:num % loop through every coordinate
value=Z(k); % store original value of X(k) as value
if value>0 % compare value to 0
Z(k)=0.3*value; % if < 0, scale value
end
end
mesh(X,Y,Z,'facecolor','y','edgecolor','y','facealpha',...
0.2,'edgealpha',0.2);
hold on
mesh(-1*(X-1),Y,Z,'facecolor','r','edgecolor','r','facealpha',...
0.2,'edgealpha',0.2);
hold off
axis equal
I'm not necessarliy looking for code, just an effective algorithm or process to achieve the desired results as I need to adapt this result into the more sophisticated program I have.
Maintain an array (n-dimensional) of integers, as you draw your objects, increment each corresponding point in the array. When done, loop through the array, and each element > 1 has an overlap between two or more objects, use the array coordinate to color the objects based on the number of overlaps.
I have worked in 2D with the MATLAB builtin function inpolygon to find out overlapping areas. However, it does not natively support 3d. I would suggest you try the inhull function which you can find here at file exchange. Please note it only supports convex hulls.
If that doesn´t help you maybe you find some inspiration in this discussion.

annotated scatter graph matlab/octave

I have 25 pairs of (x,y) co-ordinates. Each of these pairs corresponds to a country. I want to plot the 25 points on a scatter graph, and have the country name for each point directly next to the point on the scatter graph. I can't figure out how to do this in MATLAB or Octave (I have both MATLAB and Octave and don't mind which I use, which is why I'm asking about both).
Let's say I put the (x,y) co-ordinates and corresponding country labels in a matrix of 25 rows and 3 columns, with the labels in the first column. Does anyone know the command I can use for the desired graph?
Strings don't play well with matrices, so I'm adjusting your storage format slightly. Here's the test data: a 25x2 matrix of coordinates, and a 25x1 cell array of strings.
p = rand(25,2);
names = repmat({'name'}, 25, 1)
You'll have to play with the offsets slightly, but here's the idea:
scatter(p(:,1), p(:,2))
%# Compute some offsets for the lower-left of the text box, based
%# on overall size of the plot
offset_x = diff(xlim) * .01;
offset_y = diff(ylim) * .01;
text(p(:,1)+offset_x, p(:,2)+offset_y, names)

How to plot 2D data with different colors and markers

Im faced with a problem where i need to plot a two dimensional data with different colors and markers.
We are given with 2 array, namely points (n x 2 dimension) and Label (n x 1 dimension). Im not sure about the number of unique values in the Label array but maximum could be 10. I would like to plot the points with different color and markers based on its corresponding Label value.
Can any one help me in this regard
Use gscatter, which does a scatter plot, using a group (Label in your case) to plot in different colours/makers.
GSCATTER(X,Y,G,CLR,SYM,SIZ) specifies the colors, markers, and
size to use. CLR is either a string of color specifications or
a three-column matrix of color specifications. SYM is a string
of marker specifications. Type "help plot" for more information.
For example, if SYM='o+x', the first group will be plotted with a
circle, the second with plus, and the third with x. SIZ is a
marker size to use for all plots. By default, the marker is '.'.
So you can specify colours like 'rgcmykwb' to do red for the first group, green for the second, etc or [] just to have Matlab sort it out.
By default Matlab uses the same marker for each group, so you need to specify what markers you want to be used for each group. If you do '.ox+*sdv^<>ph' you'll just cycle along all the markers that Matlab has.
n=50;
% make nx2 matrix of random points.
points = random('unif',0,1,n,2);
% make nx1 matrix of random labels from {1,2,...,5}
labels=round(random('unif',1,5,n,1));
% plot. Let Matlab sort out the colours and we will specify markers.
gscatter(points(:,1),points(:,2),labels,[],'ox+*sdv^<>ph.')
It looks a bit like this: