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 a set of points in an image, for example:

POI = {{32.5, 257.5}, {73., 250.5}, {55.5, 248.5}, {209., 246.5}, {186.5, 245.5}, {154.5, 241.}, {213.5, 235.5}, {169.5, 233.5}, {212.5, 233.5}, {104., 231.5}, {18., 229.5}, {93., 228.5}, {203.5, 227.5}, {109.5, 224.5}, {138., 223.5}, {222., 222.}, {208.5, 218.5}, {0.5, 210.5}, {65.5, 209.5}, {98.5, 208.5}, {7.16667, 205.167}, {30.5, 205.5}, {257., 205.5}, {88., 203.}, {210., 202.5}, {246.5, 203.5}, {257.5, 199.}, {40.5, 198.5}, {217.5, 198.5}, {193.5, 197.5}, {0.5, 195.5}, {44.5, 192.5}, {159.5, 188.}, {120.75, 185.}, {39.8333, 183.833}, {207., 184.}, {239., 184.5}, {178.5, 183.5}, {52.5, 182.5}, {19.3, 178.9}, {155.5, 180.5}, {167.5, 179.5}, {19.5, 174.5}, {89.5, 174.}, {206.5, 173.5}, {44., 169.5}, {32.5, 169.}, {130.5, 168.5}, {106.833, 166.833}, {202.9, 165.7}, {215.167, 164.833}, {231.5, 165.5}, {46.5, 164.5}, {242.5, 164.5}, {200.5, 160.5}, {255., 155.5}, {108.5, 154.5}, {197.167, 154.167}, {192., 153.}, {10.5, 151.5}, {32.5, 149.5}, {111.3, 146.3}, {136.5, 147.5}, {187.5, 147.5}, {257.5, 146.5}, {63.1667, 146.167}, {122.5, 144.}, {135.5, 144.5}, {177., 144.}, {218.5, 144.5}, {26.1667, 143.167}, {211.5, 141.5}, {188.5, 140.5}, {106.833, 137.833}, {0.5, 136.5}, {29., 136.}, {98.5, 135.5}, {185.5, 134.5}, {145.5, 133.5}, {113.5, 131.5}, {219., 130.5}, {70., 129.5}, {11.1667, 128.167}, {183.5, 128.5}, {63.5, 125.5}, {60.5, 124.}, {85.5, 124.5}, {67.5, 122.5}, {43.5, 121.}, {182.5, 121.5}, {155.5, 119.5}, {252.5, 119.5}, {124., 118.5}, {97.5, 117.5}, {45., 115.5}, {104.167, 114.833}, {69.5, 112.}, {40.5, 111.5}, {117.5, 111.}, {1., 110.}, {34.5, 109.5}, {189.5, 109.5}, {32.1667, 107.833}, {100.5, 106.5}, {45.5, 105.5}, {106.5, 104.5}, {205.5, 104.}, {167.5, 103.}, {173.5, 103.5}, {185.5, 102.5}, {123.5, 95.5}, {181.5, 95.}, {45.5, 94.5}, {26.5, 87.5}, {74.5, 86.5}, {179., 86.5}, {93.5, 83.}, {188.5, 83.5}, {13.5, 80.5}, {75.5, 79.5}, {41.5, 78.5}, {162.5, 78.5}, {9.83333, 76.1667}, {179.5, 76.5}, {151.5, 74.5}, {182., 72.5}, {141.167, 67.1667}, {235.5, 66.5}, {156., 64.5}, {167.5, 64.5}, {212.5, 64.5}, {199.833, 60.8333}, {157.5, 60.}, {121.5, 54.}, {198.5, 54.5}, {83.5, 48.5}, {179.5, 46.5}, {228.5, 46.5}, {127., 44.5}, {204.5, 44.5}, {35.5, 42.5}, {79.5, 41.5}, {66.5, 40.5}, {80.8333, 38.8333}, {190.5, 38.5}, {51., 36.5}, {243.5, 31.5}, {93., 29.5}, {232.5, 29.5}, {232.5, 22.5}, {35.5, 20.5}, {121.5, 20.5}, {159., 17.5}, {219.5, 14.5}, {253.5, 13.}, {214.5, 11.5}, {77.5, 9.5}, {7.,8.5}, {168., 8.5}, {219.833, 6.83333}, {83.8333, 4.83333}, {22.5, 3.}, {140.5, 0.5}, {227.5, 0.5}, {253.5, 0.5}};

I would like to generate rectangular morphological components (compatible with ComponentMeasurements) of a certain size that are centered on each of these points. Specifically, I would like the components to have a side length of $l$ pixels, and where each point in the morphological component is at most a fixed Manhattan distance $d_{max}$ away from its centerpoint.

How might I do this, perhaps using Dilate? And is it possible to have overlapping morphological components?

Update : Answer to the last point on whether components can overlap: No (see comment by belisarius below).

Update 2 : The command:

Dilation[Components, r]

Will take a single pixel, and blow it up it up into a square block with $r$ pixels on either side of the centerpoint. If there were some manner of generating a single-pixel component at each of my POI positions, I believe that would solve my problem. Is there an easy manner of doing this?

share|improve this question
    
Components are disconnected. In fact, that is the definition of component ... a disconnected area –  belisarius Jul 18 '13 at 1:28
    
@belisarius Thanks - I've noted your answer to that part of my question! –  Intemediocre Jul 18 '13 at 1:55
add comment

1 Answer 1

up vote 6 down vote accepted

I see two possible pitfalls here. The first one is, that your coordinates are not integers > 0. This is problematic, because a point in an image is per definition a pixel which has always integer coordinates. What you could do here is multiply your coordinates by 10 and round the values to integers. In this way you get at least rid of the .5 coordinates.

Another problem is, that you need to be careful with the distance $d_{max}$ you are using, because if two positions in your array happen to be too close together, they get merged into one morphological component. This is probably not what you want.

The rest is simple: Use SparseArray to create a pixel-matrix which is 1 at the positions you specified. Make an image from it and use Dilation. With your points POI defined the following one-liner works

Dilation[Image@SparseArray[Round[POI] + 1 -> 1], 2]

The `+1 is necessary because arrays in Mathematica indexed starting by 1 and your coordinates contain values 0.

Mathematica graphics

Another approach you may wanna try is using a combination of DistanceTransform and Binarize

enter image description here

With[{img = Image@SparseArray[Round[2 POI] + 1 -> 1]},
 Manipulate[
  ColorNegate@
   Binarize[
    DistanceTransform[ColorNegate[img], 
      DistanceFunction -> distFunc] // ImageAdjust, t],
  {t, 0, .5},
  {distFunc, {EuclideanDistance, SquaredEuclideanDistance, 
    ManhattanDistance, ChessboardDistance}, 
   ControlType -> PopupMenu}]
 ]

More Details

why do we write: "Round[2 POI]" in the second part

Let me explain this further. Assume you have two points in your data {1.5,2} and {2,2}. For the pixel matrix, we need integer coordinates. If we simply use Round here, we end up with the two points being the same.

By a simple scaling of all coordinates with 2, we ensure these two points stay distinct: {3,4} and {4,4}. Since your POI list contains things like 9.83333 a final Round is still necessary.

What you have to keep in mind is, that the coordinate transformation we used

Round[2 POI] + 1

scales and shifts your coordinate system. To come back to your original system, you have to invert this by (p-1)/2 when p is a pixel-position from your image.

Also, shouldn't: Dilation[Image@SparseArray[Round[POI] + 1 -> 1], 2] be Dilation[Image@SparseArray[Floor[POI] + 1 -> 1], 2]?

I wouldn't know why you should use Floor, but you surely can do this. Round is just more exact, because a coordinate 12.9991 gets converted to 13 and not 12.

I've found this correction mathematica.stackexchange.com/questions/28756/… to be necessary in terms of matching up the coordinates for the morphological components in your answer and the original POI coordinates taken from my image of interest. Why is that?

In addition to the coordinate transform we did, you have to understand, that Image uses a reversed system and the coordinates coming ComponentMeasurments are transposed. Furthermore, measures like "Centroid" give half-pixel coordinates.

Here an example where input and output matches:

mycoords = {{55, 10}, {230, 45}};
img = Image[Reverse@Transpose@SparseArray[mycoords -> 1, {256, 256}]]
ComponentMeasurements[MorphologicalComponents[img], "Centroid"]
(* {1 -> {229.5, 44.5}, 2 -> {54.5, 9.5}}*)
share|improve this answer
    
how do you create these cool animated gifs? –  bill s Jul 18 '13 at 2:54
    
@bills This is a small app that comes with Ubuntu. Nothing special. –  halirutan Jul 18 '13 at 2:56
    
@halirutan Great answer! However, why do we write: "Round[2 POI]" in the second part? –  Intemediocre Jul 18 '13 at 3:26
    
@halirutan Also, shouldn't: Dilation[Image@SparseArray[Round[POI] + 1 -> 1], 2] be Dilation[Image@SparseArray[Floor[POI] + 1 -> 1], 2]? –  Intemediocre Jul 18 '13 at 3:57
    
@halirutan I've found this correction mathematica.stackexchange.com/questions/28756/… to be necessary in terms of matching up the coordinates for the morphological components in your answer and the original POI coordinates taken from my image of interest. Why is that? –  Intemediocre Jul 18 '13 at 8:06
show 1 more comment

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.