23
$\begingroup$

The Colorize function is often used to display the results produced by MorphologicalComponents:

i = ImageTake[
   ExampleData[{"TestImage", "Mandrill"}], {1, -1, 10}, {1, -1, 10}];
b = Binarize[i, .5];
mc = MorphologicalComponents[b];
Colorize[mc]

mandrill taken

The colors represent the integer index values of each foreground component, so the magenta area is 2, the black background is 0, 42 is browney-orange, 19 is violet, and - well, my question is, what is this color scheme?

I'm working on images like the following, to try to understand morphological images, but a legend-type approach might be better:

Show[
 ArrayPlot[mc,
  Epilog -> {
    MapIndexed[{Text[Style[#1, 10, Gray],
        Reverse[#2 - {.5, .5}]]} &,
     Reverse[mc],
     {2}]}, PlotRangePadding -> 0],
 Colorize[mc]
 ]

labeled

Update

Thanks to stefan's amazing detective work, I've got a way to list the colors, although this isn't available until you run Colorize once or set up the colors another way first:

colorizeColors[n_] := 
 Part[RGBColor[N@#1/256, N@#2/256, N@#3/256] & @@ 
     Image`ColorOperationsDump`hashcolor[#1] & /@ Range[1, 100], n]
Graphics[Table[{colorizeColors[x], Rectangle[{x, 0}, {x + 1, 1}], 
   White, Text[x, {x + 0.5, -.5}]}, {x, 1, 30}], Background -> Black, 
 ImageSize -> 800] 

colorize legend

$\endgroup$
6
  • $\begingroup$ Whohoo!! That looks just amazing!! Wow. Nice job @cormullion :) $\endgroup$
    – Stefan
    Jun 26, 2013 at 6:49
  • $\begingroup$ @stefan it's all your fault :) $\endgroup$
    – cormullion
    Jun 26, 2013 at 6:50
  • $\begingroup$ I found out how to initialize the internal data structures as well...see my update :) That's what I call a good start of a day. $\endgroup$
    – Stefan
    Jun 26, 2013 at 6:51
  • 1
    $\begingroup$ @stefan yes you've lifted up a rock and looked at the strange things crawling around underneath! :) $\endgroup$
    – cormullion
    Jun 26, 2013 at 6:55
  • 3
    $\begingroup$ @Pickett well, yes, but where's the fun :) $\endgroup$
    – cormullion
    Jun 26, 2013 at 7:04

1 Answer 1

21
$\begingroup$

How does Colorize work

Colorize does use DarkRainbow as a default color scheme.

What Colorize does first is setting up a hashtable with RGB values from DarkRainbow through DataPaclets`ColorDataDump`

The next operation is setting up a list of indices from the original image, iterating through the internal hash-table to fill a list of color triplets and call an internal mapping function, to join it all together.

I'll show here an example for your result from your MorphologicalComponents.

1) create the indices table

indices = Cases[Tally[Flatten[mc]][[All, 1]], _?Positive]  

2) allocate a color list

colors = ConstantArray[0, {Max[0, indices], 3}]

3) fill the colors list with the hashcolor values

((colors[[#]] = Quiet[Image`ColorOperationsDump`hashcolor[#1]]) &) /@ indices;

4) join it all together to create an image

Image[Image`ColorOperationsDump`mapFunc2D1[mc, colors, indices],
    Byte, ColorSpace -> "RGB"]

enter image description here

There is one problem with this approach. I didn't find out, how the internal hash-table is generated with the values from DarkRainbow. What that means is, that if my approach should succeed, there must've been an execution of Colorize before.

Agreed, that setting up the internal hash-table is a critical step in the coloring process of Colorize, it does by all means solve your legend problem.

Update: Setting up the internal hash-table

I wrote before that I couldn't find out how the internal hash-table was generated. Well, now I know how:

Caution! This makes heavy use of undocumented functionality and may be deprecated.

The internal data-structures are set up from the first time any function is called with Colorize and/or HighlighImage functionality.

What they do is, they call but do not evaluate them. This seems to be enough in order to initialize the internal data structures, they just construct the object.

System`Dump`AutoLoad[Hold[Colorize], 
    Hold[Colorize, HighlightImage, 
        Image`ColorOperationsDump`colorspaceToColor, 
        Image`ColorOperationsDump`colorToColorspace], 
        "ImageProcessing`ColorOpsColorize`"
]

So if you evaluate this code block everything else I described works just perfectly.

Update 2: Cleaner Initialisation

Although the above code block works I didn't like it. There must be another way to initialise the internal data-structures for Colorize. Something that does not rely on undocumented functionality which may change in future versions.

It seems to me that a load of Mathematica implementation is loaded from a dump file, the first time it gets used.

Let's check that for Colorize:

ClearAttributes[Colorize, ReadProtected]
Information[Colorize]

This sequence yields the same code that I listed above. Obviously this is the initialisation sequence specific for Colorize (and HighlighImage).

In C++/Java there is something called a Constructor. So my question was is there a way to avoid the above ugly code block and simply initialize the Colorize functionality prior any usage, meaning calling a Constructor.

Actually it is. Evaluate!

What this means is. You can completely replace the above System`Dump sequence with a simple call to Evaluate in order to initialise the internal data-structures:

Evaluate[Colorize]; (*construct the object and initialise internal data-structures*)

Done. As long as WRI continues with their load on demand paradigm this will hold true. Btw. this works on version 8 as well.

$\endgroup$
5
  • $\begingroup$ More complicated than I thought! Thanks, will experiment... (+1) $\endgroup$
    – cormullion
    Jun 25, 2013 at 14:12
  • $\begingroup$ Cheers :) I tried to find out the hash-table generation as well, but then my notebook crashed several times. I'm working here from linux. Maybe someone else on another platform, with more ram, has more luck. $\endgroup$
    – Stefan
    Jun 25, 2013 at 14:19
  • 4
    $\begingroup$ The Evaluate is not needed, just Colorize; will trigger the autoload. $\endgroup$ Jun 27, 2013 at 12:28
  • $\begingroup$ @SimonWoods yes indeed, but does it also held the attributes held unevaluated. i wasn't sure about that. that's why i encapsulated it inside an Evaluate $\endgroup$
    – Stefan
    Jun 27, 2013 at 12:31
  • 1
    $\begingroup$ Actually Image`ColorOperationsDump`hashcolor has nothing to do with the "DarkRainbow" color scheme: it's implementation is based on Hash as can be seen from its definition: Compile[{{i, _Integer}}, 30 + IntegerDigits[Hash[i], 200, 3]] (checked with Mathematica 8.0.4). $\endgroup$ Jun 13, 2017 at 8:48

Your Answer

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

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