Map grayscale to random RGB colors

I am working with 3D grayscale stacks in 16 bits and I want to assign each gray value to a random RGB color value. A simple way I do this is by first creating an indexed lookup table where each channel (R, G, and B) is a shuffle of the [0,255] values. The table (dictionary) thus has entries (v r g b) which can be used to map a gray value ‘v’ to a random ‘r g b’ value. I then use a combination of append and split to create my randomly colored stack and save it as a tif file.

But I think I might be missing a built in feature of gmic that can do this automatically. I tried using map, colormap, index, clut but didn’t find a way to get what I wanted. Any suggestions?

Thanks,

  • Alex

Command map is probably the way to go:

$ gmic volume16bits.cimgz {iM+1},1,1,3,u(255) map.. . rm.  # Short version
$ gmic volume16bits.cimgz input {iM+1},1,1,3 rand[-1] 0,255 map[-2] [-1] remove[-1]  # Long version :)

should be working. (you may have to quote the braces and parentheses depending on the shell you use).

2 Likes

:exploding_head:

@alosca, may one ask, why to do this? Sounds pretty interesing magic :mage:.

Very handy and quick! Thanks for the pipeline. My lack of experience would not come up with the {iM+1},1,1,3,u(255) part, which is probably very basic. I will investigate what this does. I had to add ‘append z’ so to color the entire stack.

I use this to color regions that have been created after image segmentation where pixels/voxels are labeled discrete numbers.

Oh! Once more a superb solution from David :slight_smile:
Merci!

I kindly wonder if we should change questions from
“what can g’mic do” to “what can g’mic not do”?
That seems easier…

Amicalement,
Claes en Lund, La Suède

Yes, that is actually quite simple to understand :slight_smile:
This part just inputs a new image with width={iM+1}, height=depth=1 and nb_channels=3 (color image) with random values in range [0,255]. This colormap image is needed by command map and define the color correspondences for each index x.
Expression {iM+1} is actually substituted by the max value of your original image + 1 (so the number of values, probably 65536 if you work with 16bits images). And u(255) is the formula that is used to fill the image values (u() being a function that returns a random number).

I was just taking a look at the reference page now:

‘im’,‘iM’,‘ia’,‘iv’,‘is’,‘ip’,‘ic’: Respectively the minimum, maximum, average,
variance, sum, product and median value of the associated image…
‘u(max)’ or ‘u(min,max)’: return a random value between [0,max] or [min,max], following a uniform distribution.

I admit G’MIC syntax looks so weird sometimes… :smiley:
But at the same time, all is very logical and is working the same for all commands. Once you get used to the possible substitutions and the syntax of the math expressions, it just becomes a pleasure to use !

Now I need a bit more control of mapped values: I want to map gray value 1 to black and gray value 0 to white and the others continue to be random. More generically, map gray value ‘g’ to a certain color ‘r g b’ and all the others to random values or all the otehrs to a given color. This will allow me to highlight certain regions of my segmentation.

I thought ‘replace’ would do the job but then after ‘map’ the reference gray values I want to control have been lost in the randomization process and I cannot issue e.g. ‘replace 0 …’. What would you recommend?

If you don’t have so many values to set, just change the formula used to create the colormap, like:

{iM+1},1,1,3,"x==0?[255,255,255]:x==1?[0,0,0]:u([255,255,255])"

I said it once and I will repeat again: gmic is awesome, magnifique! Very useful and I use it constantly. I am a command line advocate and gmic has what I like and I am comfortable with it. What I need to improve my proficiency is some clear documentation with many examples, something like a ‘gmic programming language’ reference card/book/document, It is probably already there somewhere (?) and I just need to roll my sleeves and tackle it!

1 Like

Thanks again! I need to understand more how map works as I need to color my gray value stack in different ways. For example, by size of region, location with respect to a reference point, etc. This will probably entail sorting of values followed by mapping. Would this be the right approach within gmic?

I currently use gmic to convert the stack to -.asc then use awk to process, set values, and save in .asc which is then read back by gmic and exported in a colored tiff.

   . 'x': current processed column of the associated image, if any (0 otherwise).

This is actually a very basic command. It maps a user-defined colormap C to an indexed scalar image I, such that the returned image J is defined for each pixel (x,y) as J(x,y) = C[ I(x,y) ].
The colormap C is more often an image with size width=Nb_entries x height=1 x depth=1 and may have an arbitrary number of channels.

If your regions have constant colors, then combining map, area and label is a solution to display segmented regions in colors. The example below show how to do it.

$ gmic 400,400 repeat 100 circle "{u([w,h,40])}",1,{u} done area_fg 0,0 "(0,0,0;0,1,1;60,1,1)" permute. yzcx r. "{-2,iM+1}",1,1,3,3 hsv2rgb. map.. . rm.

It generates an image of discs and map it with a ‘hot’ color so that near black = small areas and bright yellow = large areas.
map_areas

Many thanks for the detailed information and examples. I have tried these with success in my 3D segmented images. Very handy, One caveat is that when one region is much larger than the others, most of the colors presented are at the end of the colormap spectrum. I need to change the colormap accordingly to avoid such ‘saturation’. A 3D view example is below.

3dvolumes

While we are in the subject of coloring, is there any ‘graph coloring’ algorithm implemented in gmic? I want to avoid painting neighbouring regions with similar colors which are randomly pick using the methods described earlier. It is not an easy problem but I wonder if there is something close to that already implemented. Any suggestions?

Well, two options to consider I think :

  • Use a non-linear scale : for instance, areas of regions are expressed in number of pixels, and it has often more sense to consider the square root of the areas for the mapping. Or you can also use log scales.
  • Cut your values (command cut) so that the max area is never higher than a given threshold.

No there is nothing like this for the moment in G’MIC.

Many thanks for the suggestions and information about graph coloring. I will try the sqrt and log scales.

For instance, with the square root of the areas:

$ gmic 400,400 repeat 100 circle "{u([w,h,40])}",1,{u} done area_fg 0,0 sqrt "(0,0,0;0,1,1;60,1,1)" permute. yzcx r. "{-2,iM+1}",1,1,3,3 hsv2rgb. map.. . rm.

See the differences : without sqrt (left) and with sqrt (right).
comp_sqrt

Thanks for the examples. Noticeable differences. I would use another colormap though, maybe it can be more revealing of the differences.