Skip to main content

image processing - Color scheme used by Colorize?


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



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



Answer



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.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...