Seperating labeled array areas using contourf

I want to seperate areas which are stored in a labeled array. My intention was to use contourf as the built-in interpolation prevents sharp edges. As seen in the following picture, this is what I do not wan't to achieve (just as an example, contourf is not doing that!):
When I use
[M, c] = contourf(image_array, 200)
then 200 areas are succesfully distinguished. I know before how many areas there will be. However the above code results in a strange behaviour as lines are not only surrounding the labeled area, but instead other areas as well. The next picture is illustratin what I'm talking about:
As seen at most boundaries more than one line is seperating the areas.
My two questions are:
  1. How can I prevent contourf from using multiple lines around an area? What I want is just a single line as in the top right or bottom middle part of the picture.
  2. Any ideas how I can export the resulting seperation lines to mesh the areas e. g. with gmsh?
I attatched a file showing a cropped part of my areas.

 Réponse acceptée

darova
darova le 4 Avr 2020
You want x,y coordinates of boundaries? Or what kind of format it should be?
clc,clear
load areas.mat
I = (image_array);
lev = unique(I); % number of levels (unique values)
I2 = false(size(I)); % matrix for edge pixels
for i = 1:length(lev)
I1 = I == lev(i); % find region
I2 = I2 | edge(I1); % create edge and store
end
I1 = I;
I1(I2) = 50; % put boundaries into original image
imagesc([I 50*I2 I1])
axis equal off

9 commentaires

darova
darova le 4 Avr 2020
Alan Meier
Alan Meier le 4 Avr 2020
I'm not looking for the coordinates but instead for lines seperating the areas. So more something like a surrounding polygon. That's why I tried contourf as it is providing boundary lines instead of coordinates.
try this
clc,clear
load areas.mat
I = (image_array);
lev = unique(I); % number of levels (unique values)
data = cell(numel(lev),2);
imagesc(I)
hold on
for i = 1:length(lev)
I1 = I == lev(i); % find region
[~,h] = contour(I1,[0.99 0.99],'linewidth',2,'color','g');
data{i,1} = get(h,'xdata');
data{i,2} = get(h,'ydata');
pause(0.5)
end
hold off
Alan Meier
Alan Meier le 4 Avr 2020
Modifié(e) : Alan Meier le 4 Avr 2020
@darova
Your input is very helpful, appreciate that!
I changed it slightly, so that I can get stl files instead of shapefiles, which was the original purpose. Therefor one need the addon from file exchange: https://www.mathworks.com/matlabcentral/fileexchange/20922-stlwrite-write-ascii-or-binary-stl-files
I'm still looking for two improvements:
The first is about the boundary lines. Can I enlarge them, so that they are overlaying each other. Something like in the following picture:
As all "displacements" have the same value, although it dosen't seem like that in the picture, I think this can't be too difficult.
The second issue I'm still struggeling with is the stl export. Well it is working but the points are not connected "as expected". Instead it seems more like a convex hull they are forming. See the last area as an example (upside down).
Here is the code:
clc,clear
load areas.mat
I = (image_array);
lev = unique(I); % number of levels (unique values)
data = cell(numel(lev),2);
imagesc(I)
hold on
for i = 1:length(lev)
I1 = I == lev(i); % find region
[c,h] = contour(I1,[0.99 0.99],'linewidth',2,'color','g');
data{i,1} = get(h,'xdata');
data{i,2} = get(h,'ydata');
pause(0.5)
contour2stl(c, i)
end
hold off
function contour2stl(cmatrix, i)
%Converts a contour matrix to a stl structure
%needs https://www.mathworks.com/matlabcentral/fileexchange/43162-c2xyz-contour-matrix-to-coordinates
[x, y, z] = C2xyz(cmatrix);
z = zeros(1,size(x{1}',1))';
stlwrite([pwd '\', 'test_', num2str(i), '.stl'], x{1}', y{1}', z, 'mode', 'binary');
end
darova
darova le 4 Avr 2020
Where is the actual boundary should be?
What about center?
[~,h] = contour(I1,[0.5 0.5],'linewidth',2,'color','g');
Alan Meier
Alan Meier le 5 Avr 2020
Yes centering is way better! I still want to get rid of the small 'no area' areas when multiple boundaries come together.
I don't have special requirements how to do that. The best would probably be to split this equal between the neighbouring areas, e. g.:
Honestly have no idea how to eliminate those smal non-areas
About triangulation: since stlwrite wants triangles to write geometry you can triangulate manually
simple example
clc,cla
x = data{1,1};
y = data{1,2};
ix1 = isnan(x) | isnan(y);
x(ix1) = [];
y(ix1) = [];
x = [x; x(end)];
y = [y; y(1)];
gd = [2;length(x); x(:); y(:)];
dl = decsg(gd);
[p,e,t] = initmesh(dl); % return points, edges, triangles
fv.vertices = p'; % add points/vertices to struct
fv.faces = t(1:3,:)'; % add tiangles/faces to struct
patch(fv,'facecolor','g') % display patch
stlwrite(fv)
Alan Meier
Alan Meier le 8 Avr 2020
This solution worked out for me. Instead of contour I used contours, which is described here. It has the advantage of not creating a visualization and is therefor faster, especially when processing larger data.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Agriculture dans Centre d'aide et File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by