Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have an accumulation of points representing a body as you can see in the image below. From this data I want to generate a list of points or a curve, which is the envelope.

ListPlot of the data

The first idea was a convex hull, but the shape of the body is not convex.

ConvexHull of the datapoints

Is there a way to extract the points at the border?

click here for the data

share|improve this question
3  
Related: mathematica.stackexchange.com/q/4624/862 –  Simon Woods Mar 25 at 12:11
    
it may be useful to add that once you get your points on that integer lattice, you can use Picks to calculate the area of your funkalicious blob. –  PlaysDice Mar 25 at 14:29

3 Answers 3

up vote 18 down vote accepted

One very simple basic approach is the following (I assume you already loaded the variable spiel)

With[{m = Normal@SparseArray[spiel -> 1]}, 
 boundary = Position[m - Erosion[m, 1, Padding -> 0], 1];
 ListPlot[{Position[m, 1], boundary}, PlotStyle -> {Gray, Red}]]

Mathematica graphics

share|improve this answer

Given that your data is on an integer grid, it may be sufficient to define a boundary point as one which does not have 4 neighbours (up, down, left, right)

boundary = Complement[spiel, Intersection @@
    Outer[Plus, {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}, spiel, 1]];

ListPlot[boundary]

enter image description here

share|improve this answer
    
A +1 from me because opposed to my solution, your approach doesn't destroy the index information. It seems that Erosion doesn't work with SparseArray and the moment you call Normal, you destroy the information that y runs from -100 to -33.. –  halirutan Mar 25 at 13:40
    
+1. Can one extend this to a 3D situation? –  RunnyKine Mar 25 at 14:58
1  
@RunnyKine, sure, just put an appropriate list of neighbour coordinates into Outer. –  Simon Woods Mar 25 at 17:01
    
Thanks, I did just that after looking at your code. Works fine. –  RunnyKine Mar 25 at 17:20

This is not really direct answer to the question because the data points are given. But, I think, still it's fun to share image processing alternative solution.

img = Import@"http://i.stack.imgur.com/h2Ewf.png";
ii = CommonestFilter[img, 3]

enter image description here

iii = DeleteSmallComponents@ Closing[ColorNegate@ii, 6] // ImageAdjust
iiii = Thinning@EdgeDetect[ContourDetect[iii]]

enter image description here

corners = ImageCorners[iiii, MaxFeatures -> 1000];
HighlightImage[img, corners]

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.