4
$\begingroup$

As everyone knows, MorphologicalComponents can create a list that shows only the difference between morphological clusters. But sometimes we need to find out the morphological properties as well as the original values.

For example:

l={{1,1,0,2,3},{1,2,0,2,2},{2,2,2,3,3}};

MorphologicalComponents[l,CornerNeighbors->False]
(*{{1,1,0,1,1},{1,1,0,1,1},{1,1,1,1,1}}*)

But of course that's not what I want. I would like to have a result like this:

{{1,1,0,2,3},{1,4,0,2,2},{4,4,4,5,5}}

There're several attemps, but none of them are satisfying. Are there any other elegant solutions?


My algorithm will require multiple MorphologicalComponents calculation, thus be quite slow in speed when there are a lot of diffenent values in a huge list.

So, I would like to have a solution requires only one calculation and be as fast as possible while as simple as possible (No fussying with Compile if the code is too long......)

$\endgroup$
1
$\begingroup$

Though I was not able to run your code, I thought my solution might be useful for you (as I think it runs a bit faster):

Clear[mylabeling];
mylabeling[list_List] := 
  Module[{maxlist = Max@list, temp, tempmap, lut},
   temp = Map[MorphologicalComponents[
        Image[ImageData@Binarize[Image@list, {#, #}]], 
        CornerNeighbors -> False] &, Range[maxlist]];
   tempmap = Map[FromDigits[Reverse@#, maxlist] &, 
     Transpose[temp, {3, 1, 2}], {2}];
   lut = Table[0, {Max@tempmap}];
   lut[[Union@Flatten@tempmap]] = 
    Range[0, -1 + Length@Union@Flatten@tempmap, 1];
   Return[Map[lut[[#]] &, tempmap, {2}]];
  ];

Calling

mylabeling@{{1, 1, 0, 2, 3}, {1, 2, 0, 2, 2}, {2, 2, 2, 3, 3}}

gives

{{1, 1, 0, 2, 4}, {1, 3, 0, 2, 2}, {3, 3, 3, 5, 5}}

This is not strictly identical to what you have written above, but I think the essence of your problem is simply to split all levels of your integer valued input list, so the order of resulting labels should not matter. I did not do extensive testing, let me know if it works for you. Also, ParallelMap might be useful when doing the MorphologicalComponents mapping. There is no useful solution without multiple calls of this built-in function. However, I am sure that a more effective way would be to implement a special solution of the flood-fill algorithm, but this seems to be beyond your intention.

|improve this answer|||||
$\endgroup$
  • $\begingroup$ Er, sorry for the late reply, but I suppose your method is almost identical to mine? We all used multiple MorphologicalComponents. Maybe a neat implementation of flood-fill algorithm will be great~ $\endgroup$ – Wjx Jan 6 '17 at 1:45
  • $\begingroup$ My original code still have some bugs inside, so I removed it. $\endgroup$ – Wjx Jan 6 '17 at 1:45
1
$\begingroup$

The output of my function is slightly different from the one you give, but I think it still meets your requirement?:

unitStepExpand = Simplify`PWToUnitStep@PiecewiseExpand@# &;

help = Function[{x, a}, #] &@unitStepExpand@If[x == a, 1, 0];

label[l_] := Module[{element = l // Flatten // Union // Rest, layer, coloredlayer},
  layer = MorphologicalComponents[#, CornerNeighbors -> False] &@help[l, #] & /@ element;
  coloredlayer = FoldList[Max@# (1 - UnitStep[-#] &)@#2 + #2 &, layer];
  Total@coloredlayer]

l = {{1, 1, 0, 2, 3}, {1, 2, 0, 2, 2}, {2, 2, 2, 3, 3}}; 
l // label // TraditionalForm

Mathematica graphics

|improve this answer|||||
$\endgroup$
  • $\begingroup$ yeah, this code is valid, but it still calls MorphologicalComponents Multiple times, can one aviod multiple calls to it? $\endgroup$ – Wjx Jan 6 '17 at 6:54
  • $\begingroup$ @wjx It's beyond my reach. I searched in the document for a while but didn't find any proper function, and I don't know any existing algorithm that can be used for the task. $\endgroup$ – xzczd Jan 6 '17 at 7:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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