2
$\begingroup$

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?

$\endgroup$
2
  • $\begingroup$ Components are disconnected. In fact, that is the definition of component ... a disconnected area $\endgroup$ Commented Jul 18, 2013 at 1:28
  • $\begingroup$ @belisarius Thanks - I've noted your answer to that part of my question! $\endgroup$ Commented Jul 18, 2013 at 1:55

1 Answer 1

10
$\begingroup$

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}}*)
$\endgroup$
6
  • 1
    $\begingroup$ how do you create these cool animated gifs? $\endgroup$
    – bill s
    Commented Jul 18, 2013 at 2:54
  • $\begingroup$ @bills This is a small app that comes with Ubuntu. Nothing special. $\endgroup$
    – halirutan
    Commented Jul 18, 2013 at 2:56
  • $\begingroup$ @halirutan Great answer! However, why do we write: "Round[2 POI]" in the second part? $\endgroup$ Commented Jul 18, 2013 at 3:26
  • $\begingroup$ @halirutan Also, shouldn't: Dilation[Image@SparseArray[Round[POI] + 1 -> 1], 2] be Dilation[Image@SparseArray[Floor[POI] + 1 -> 1], 2]? $\endgroup$ Commented Jul 18, 2013 at 3:57
  • $\begingroup$ @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? $\endgroup$ Commented Jul 18, 2013 at 8:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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