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 start with a photograph of a shape (physically made by the flow of a liquid into another), of which I can extract the border, manually or using Mathematica's feature detect feature :

Example

Using the method described here, I extract some points of the shape, in a standard list form ({{x,y},{x,y}, ...}). Here is the example plot of such data :

A plot of the obtained data

How to :

  1. Obtain the shape's area (area of the enclosed zone)
  2. How to get an algebraic fit of the shape (and/or part of it)?
  3. How to compare one shape against another, on their respective "jaggedness".

Question 3 is more of a mathematical question, but I'm just searching for an approximate comparison tool, more in the spirit of the following example than something absolute:

this example

I expected CornerFilter to work, but it seems to give no result whatsoever. As for 2, I can fit small part of the curve using Fit[], but the general shape has multiple point with the same x, which forbid this.

share|improve this question
3  
For the first: here's a short routine for computing the signed area, assuming your points have already been ordered either clockwise or anticlockwise: PolygonSignedArea[pts_?MatrixQ] := Total[Det /@ Partition[pts, 2, 1, {1, 1}]]/2. If the points aren't already sorted, Sjoerd says to look at ListCurvePathPlot[] (and the related function FindCurvePath[]). –  J. M. May 22 '12 at 18:58
2  
For "respective jaggedness" you could use Box Counting method used on fractal shapes: this en.wikipedia.org/wiki/Box_counting or this en.wikipedia.org/wiki/Fractal_dimension_on_networks –  Vitaliy Kaurov May 22 '12 at 19:35
    
@J.M. are you sure your routine sorts them anticlockwise (or clockwise)? Also, even if you sort by the polar angle, that does not guarantee that a ray coming out of the centre of the shape will not intersect it twice. –  acl May 22 '12 at 19:46
    
@acl: hmm, yes; that is indeed a caveat of sorting by polar angle. I don't have a better approach at the moment. –  J. M. May 22 '12 at 19:49
3  
Could you tell us your requirements regarding your "algebraic fit"? –  Sjoerd C. de Vries May 22 '12 at 20:20

2 Answers 2

up vote 22 down vote accepted

You can use Mathematica's image processing functions for questions 1 and 3. Here's how:

1: Area

img = Binarize@Import["http://i.stack.imgur.com/I2gkK.jpg"] ~Erosion~ 1;
(m = MorphologicalComponents[img]) // Colorize

enter image description here

To get the area of the pink part in sq. pixels, use ComponentMeasurements:

2 /. ComponentMeasurements[{m, img}, "Area"]
(* 25168.1 *)

3: Jaggedness

Given two shapes with a similar area, the more jagged one will have a larger perimeter. So a simple way to approximate "jaggedness" would be to use the same function, ComponentMeasurements and compare the perimeters (provided the areas are similar)

2 /. ComponentMeasurements[{m, img}, "PerimeterLength"]
(* 1352 *)

If the areas are not the same, you could find the "EquivalentDiskRadius" (which gives you the radius of the circle with the same area as the shape) for each shape and see by what percentage the corresponding perimeter lengths are off from that of the respective circles.

share|improve this answer
3  
+1, though I'm not sure about "Given two shapes with a similar area, the more jagged one will have a larger perimeter." What about two rectangles with the same area but different circumference? Intuitively I'd say both have the same jaggedness. –  Sjoerd C. de Vries May 22 '12 at 20:55
1  
@SjoerdC.deVries I see your point. I took the spirit of the question to be along the lines of "Here's this irregular blob and here's another irregular blob. How can I tell which is approximately smoother, for some definition of 'smooth'." –  rm -rf May 22 '12 at 21:01
1  
+1, and I think ComponentMeasurements can answer question 2, too, with the Length/Width/SemiAxis/Orientation/Elongation/Eccentricity measurements –  nikie May 23 '12 at 9:23

For computing the area of a non-intersecting polygon, I propose:

polyarea = 
 Compile[{{v, _Real, 2}}, 
   Block[{x, y},
    {x, y} = Transpose[v]; 
    Abs[x.RotateLeft[y] - RotateLeft[x].y]/2
   ]
 ]

Example:

Needs["ComputationalGeometry`"]
poly = #[[ConvexHull @ #]] & @ RandomReal[100, {15, 2}];

Graphics[Polygon @ poly]

polyarea @ poly

Mathematica graphics

5429.68
share|improve this answer
    
The question wasn't about polygons, right? Because all three questions would be straightforward, if it were. Besides, I'd use Graphics`Mesh`PolygonArea@Polygon[poly] for the area... –  rm -rf May 23 '12 at 17:05
    
@R.M I assumed that converting the shape to a polygon would be one avenue of approach. That function isn't in version 7; how does its performance compare to mine? –  Mr.Wizard May 23 '12 at 17:19
    
Hmm... I did not know it's not available in 7. They both give the exact same answer and are equally fast (also, it isn't necessary to wrap the points in Polygon as I wrote above) –  rm -rf May 23 '12 at 17:55

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.