Having centroids of superpixels for an image, is there any MATLAB function for drawing region adjacency graph ?
L = superpixels(A, 200);
K=regionprops(L, 'Centroid'); % Detemining centroid coordinates of each superpixels
P.S. Similar but not exact solutions :
https://www.mathworks.com/matlabcentral/fileexchange/16938-region-adjacency-graph-rag
https://www.mathworks.com/matlabcentral/fileexchange/53614-image-graphs
There are a huge amount of ways of generating graphs from nodes, and you have not specified which one you want.
One that resembles the image you provided (but its not the same) would be triangulating the domain with delaunay(). You can generate a triangulation() object from that, which contains more usable information than the output of delaunay
Alternatively, if you have your own criteria for connecting the nodes that you decided not to share, you can use graph() to generate any topology of graphs.
If you have it in a triangulation format, plotting it can be done with triplot(), trimesh() or some others. With a hold on and triplot() you will find the closest to the figure you posted.
If you want working code I am happy to provide if you add a runnable snippet in the question.
Related
Context: I want to create an interactive heatmap with areas separated by a ZIP code. I've found no way of displaying it directly (i.e. using Google Maps or OSM), so I want to create curves or lines that are separating those areas, and visualize it in maps.
I have a set of points, represented by their coordinates and their according class (ZIP code). I want to get a curve separating them. The problem is that these points are not linearly separable.
I tried to use softmax regression, but that doesn't work well with non-linearly separable classes. The only methods I know which are able to separate non-linearly are nearest neighbors and neural networks. But such classifiers only classify, they don't tell me the borders between classes.
Is there a way to get the borders somehow?
If you have a dense cloud of known points within each Zip code with coordinates [latitude. longitude, zip code], using machine learning to find the boundary enclosing those points sounds like overkill.
You could probably get a good approximation of the boundary by using computational geometry, e.g finding the 2D convex hull of each Zip code's set of points using the Matlab convhull function
K = convhull(X,Y)
The result K would be a vector of points enclosing the input X, Y vector of points, that could be used to draw a polygon.
The only complication would be what coordinate system to work in, you might need to do a bit of work going between (lat, lon) and map (x,y) coordinates. If you do not have the Matlab Mapping Toolbox, you could look at the third party library M_Map M_Map home page, which offers some of the same functionality.
Edit: If the cloud of points for Zip codes has a bounding region that is non convex, you may need a more general computational geometry technique to find a better approximation to the bounding region. Performing a Voronoi tesselation of the region, as suggested in the comments, is one such possibility.
I have an adjacency matrix without coordinates that I would like to represent nicely using gplot.
I am able to get it to show as a biograph object with a good spacing between all the nodes, so I was wondering if there was a way to extract the coordinates from the biograph object to then use with gplot?
EDIT:
I got some negative feedback (with no comments) about this question for some reason, so I will try to elaborate further.
The data I am using is for a graph represented as a weighted adjacency matrix. I would like to be able to display it using the gplot function in MATLAB, however gplot requires cartesian coordinates for each vertex, information that I haven't been given.
I don't really want to have to go to the trouble of using a force directed graph algorithm to calculate the coordinates in order to display the graph, because that would be overkill, I just want a way to display the graph so that the vertices aren't completely randomly distributed.
An easy way to do this is to use the biograph function like so:
G = <adjacency matrix>
ids = <vertex labels>
bg = biograph(G,ids,'ShowArrows','off','ShowWeights','on',...
'EdgeType','straight','LayoutType','equilibrium');
h=view(bg);
which displays a reasonable looking representation of the graph, however I would like it if I didn't have to use the biograph environment and I could use the gplot one instead.
The MATLAB documentation says that to find the x-y coordinates of node 3 (for example) I can use:
bg.nodes(3).Position
to query the position of the node; however when do that it returns [ ]
strangely though, if I double click on a node in the graphical representation I can access this information in the pop up window, so I am sure it exists somewhere..
Does anyone have any idea of how I can extract this information from a biograph object? I just need a n*2 matrix with the x and y coordinates for each vertex.
Sorry if my original question was too vague, I hope this is better
For anyone who is looking for the answer to this question, the original biograph object does not contain the position information, this is only calculated once the object is viewed - so in order to find the information you need to reference the figure handle, not the original object. This can be done using:
h.nodes(3).Position
I am currently doing some image segmentation on a bone qCT picture, see for instance images below.
I am trying to find the different borders in the picture for instance the outer border separating the bone to the noisy background. In this analysis I am getting a list of points (vec(1,:) containing x values and vex(2,:) containing the y values) in random order.
To get them into order I am using using a block of code which effectively takes the first point vec(1,1),vec(1,2) and then finds the closest point among the rest of the points in the vector. And then repeats.
Now my problem is that I want to smooth the data but how do I do that as the points lie in a circular formation? (I do have the Curve Fitting Toolbox)
Not exactly a smoothing procedure, but a way to simplify your data would be to compute the boundary of the convex hull of the data.
K = convhull(O(1,:), O(2,:));
plot(O(1,K), O(2,K));
You could also consider using alpha shapes if you want more control.
I am trying to find the points with edge-adjacent Voronoi regions in a given dataset. I'm new to computational geometry, but from reading up online, it appeared that using the Delaunay tessellation would be an easy way to do this. This PDF in particular even has a lemma that states
Lemma 2.4 Two points of S are joined by a Delaunay edge iff their Voronoi regions
are edge-adjacent.
So, I found the delaunay tessellation of my dataset as
dt = delaunay(dataset); %using delaunayn() since dataset can be multidimensional
But now, when I plot this along with the voronoi diagram for this dataset, I find that the delaunay edges returned connect points whose regions are not actually edge-adjacent.
Here is the code I used to plot Voronoi and Delaunay together:
voronoi(dataset(:, 1),dataset(:, 2));
hold on;
dt = delaunayn(dataset);
triplot(dt, dataset(:, 1), dataset(:, 2), 'red');
And here is the output:
As an example of the problem, see the point X on the right end of the figure connected to point Y near the lower left corner.
Another example is in this SO question - the point 1 is connected to 2 and 3, even though they're not adjacent, and there doesn't seem to be any way 1 and 2 could share an edge even if extended to infinity. This question is actually what prompted me to test the delaunayn output with the above code.
Why is this happening, and how do I actually get the edge-adjacent neighbour regions that I need?
Note: For seeing the image in full size and clarity, please right click and choose 'View image' or similar.
As far as I can see (the quality of the diagram is not so good), the regions for X and Y should be adjacent below the plotted part. If you zoom out far enough, you should see them.
I.e. the edge where X and Y meet exists, but is just not shown on the plot.
The following diagram does not show the voronoi diagram outside of the plotting area, but how to find the intersection point described above (note, the bisector is not shown here):
I'm currently working with DICOM-RT files (which contain DICOM along with dose delivery data and structure set files). I'm mainly interested in the "structure set" file (i.e. RTSS.dcm), which contains the set of contour points for an ROI of interest. In particular, the contour points surround a tumor volume. For instance, a tumor would have a set of 5 contours, each contour being a set of points that encircle that slice of the tumor.
I'm trying to use MatLab to use these contour points to construct a tumor volume in a binary 3D matrix (0 = nontumor, 1=tumor), and need help.
One possible approach is to fill each contour set as a binary slice, then interpolate the volume between slices. So far I've used the fill or patch function to create binary cross-sections of each contour slice, but I'm having difficulty figuring out how to interpolate these binary slices into a 3D volume. None of the built-in functions appear to apply to this particular problem (although maybe I'm just using them wrong?). A simple linear interpolation doesn't seem appropriate either, since the edges of one contour should blend into the adjacent contour in all directions.
Another option would be to take the points and tesselate them (without making slices first). However, I don't know how to make MatLab only tesselate the surface of the tumor and not intersecting the tumor volume. Currently it seems to find triangles within the tumor. If I could get it into just a surface, I'm not sure how to take that and convert it into a binary 3D matrix volume either.
Does anyone have experience with either 3D slice interpolation OR tesselation techniques that might apply here? Or perhaps any relevant toolkits that exist? I'm stuck... :(
I'm open to approaches in other languages as well: I'm somewhat familiar with C# and Python, although I assumed MatLab would handle the matrix operations a little easier.
Thanks in advance!
I'm not sure from what program you're exporting your dicom-rt structure files, but I believe I found a more elegant solution for you, already described in an open-source software (GDCM, CMake, ITK) in an Insight journal article.
I was discussing a similar problem with one of our physicists, and we saw your solution. It's fine if whatever structure you're attempting to binarize has no concavities, but if so, they'll be rendered inaccurately.
This method is verified for dicom-rt structure sets from Eclipse and Masterplan. Hope it helps.
http://www.midasjournal.org/download/viewpdf/701/4
I think I found an answer in another post (here). Rather than trying to interpolate the "missing slices" between the defined contours, treating the contour points as a point cloud and finding the convex hull might be a more efficient way of doing it. This method created the binary 3D volume that I was after.
Here is the code I used, hope it might be helpful to those who need to work with DICOM-RT files:
function mask = DicomRT2BinaryVol(file)
points = abs(getContourPoints(file));
%%NOTE: The getContourPoints function simply reads the file using
%%'dicominfo' method and organizes the contour points into an n-by-3
%%matrix, each column being the X,Y,Z coordinates.
DT = DelaunayTri(points);
[X,Y,Z] = meshgrid(1:50,1:50,1:50);
simplexIndex = pointLocation(DT, X(:), Y(:), Z(:));
mask = ~isnan(simplexIndex);
mask = reshape(mask,size(X));
end
This method is a slightly modified version of the method posted by #gnovice in the link above.
iTk is an excellent library for this sort of thing: http://www.itk.org/
HTH