One of my favorite professional publications is IEEE Signal Processing Magazine. It has a regular feature called "DSP Tips & Tricks." In the January 2006 issue, James McNames wrote a tips & tricks article called "An Effective Color Scale for Simultaneous Color and Gray-Scale Publications." Professor McNames, of Portland State University, wrote that while "color is increasingly available for electronic publications at no additional cost ... most color scales are distored when converted to gray scale. [... This] article proposes a color scale that appears as a monotonic gray scale in printed form and significantly enhances the image resolution when viewed in color."
McNames gives four design principles for selecting an effective color scale (or colormap, in MATLAB terminology):
- "[The] color scale should cover as much of the range of available colors as possible, subject to the constraint that the luminance increases monotonically (for gray scale publications).
- "Neighboring colors throughout the scale should be as distinct as possible."
- "The perceptual difference between two colors should be approximately proportional to the difference between their positions along the color scale."
- "The color scale should be intuitive."
The article goes on to show some math and some MATLAB code for creating such a color scale. Professor McNames provides a full MATLAB implementation of the idea (ColorSpiral.m) on his web site.
The McNames article describes a method for constructing a path through RGB space that has the desired properties, at least approximately. I thought it might be conceptually simpler to form a color scale by constructing a path through a different color space, L*a*b*. This color space separates luminance, L*, from two color difference components, a* and b*.
If you convert a* and b* to polar coordinates, the angle corresponds to hue, and the radius corresponds to chroma, or vividness of hue.
Let's make a color scale that is a uniform ramp in L*. In the a*-b* plane, trace a semicircular path of radius 50, with angle varying between 0 and pi/2.
radius = 50; theta = linspace(0, pi/2, 256).'; a = radius * cos(theta); b = radius * sin(theta); L = linspace(0, 100, 256).'; Lab = [L, a, b];
Now convert the L*a*b* values to sRGB so we can use it as a MATLAB colormap. Use the Image Processing Toolbox functions makecform and applycform.
map = applycform(Lab, makecform('lab2srgb'));
Let's use this colormap for looking at a Radon transform image.
I = zeros(100,100); I(25:75, 25:75) = 1; theta = 0:180; [R,xp] = radon(I,theta); imshow(R,,'InitialMagnification','fit') colormap(map)
The function color_scale on MATLAB Central lets you easily create color scales like this. You can choose different values for the radius and the starting angle, and you specify a clockwise or counterclockwise path through a*-b* space.
The same MATLAB Central submission contains the color_scale_tool function, which is a GUI that lets you control the color scale parameters with sliders. It also shows you both the color scale and the approximate grayscale equivalent. Here's a screen shot:
Give it a try.
Get the MATLAB code
Published with MATLAB® 7.2
Comments are closed.
40 CommentsOldest to Newest
I want to change Lightness, hue and chroma of image by using slider, how should I make function for that.
COuld you explain me.
colour – See my MATLAB GUI Programming Resources page.
i am final year student and i am working on project in image procssing.i am begineer to DSP. i know some basic theory of DSP. i worked on MATLAB for very small duration.
i want to convert colouring image in to B/W image.how can i do this? is it possible in MATLAB by writing some coding? if yes, then give me some example of coding.
Vmax—Take a look at the Image Processing Toolbox function im2bw.
i have got medical images similar to Ultrasonography in the gray scale, i want to convert them to the modified rainbow colour scale. I have never worked with MATLAB. Can i do this on MATLAB and how? Thank you.
Yori—You can display a grayscale image in MATLAB using any colormap you like. See the MATLAB graphics documentation for raster image display.
I would like to convert RGB colors to CIE La*b*. I would like to take the 16x16x16 bin RGB histogram of an image and convert to CIE La*b* bins. please help
V—You can use makecform and applycform to convert between the sRGB and L*a*b* color spaces. For computing a three-dimensional RGB histogram, you could use accumarray.
I am master student by research. I am working with color cervical images. I want to separate all colors CMYK or RGB using L*a*b* space but with 3D scatterplot.Can I do that? How? Thank you.
Fatimah—Use the Image Processing Toolbox functions makecform and applycform to convert to the L*a*b* color space, and then use the MATLAB function scatter3.
Could you explain how to use Matlab to calculate the color volume contained in a list of Lab colors? There are commercial applications that do this (XRite) but there is no documentation on how it is done and no explanation why one application, say Kodak, varies from another.
Perhaps best to build something in Matlab.
Ernest—I have no idea what color volume is.
Ernest—If you mean plotting the color gamut, I don’t know how to do that. I would be interested to learn more about it.
It’s easy to compute the volume in Lab space of a set of Lab colors with convhulln. Just pass in the nx3 matrix of Lab coordinates and the volume is the second output argument. However, you have to be careful about what you are comparing. It is not necessarily true that a color that is inside the convex hull is physically realizable with the system that is producing the colors (which is just another way of saying that the gamut is not convex). In that case the volume of the hull is a poor indication of the true gamut. That may be why applications vary — they are designed for use with different color systems.
Doug (former Kodaker)
Doug—Thanks for jumping in!
Thank you for the response. Much appreciated!
Former Kodaker’s seem to be good fellows.
Regarding tetrahedral interpolation for color space conversion (Nov 24, 2006) you explain that the view is hard to see, so you show individual tetrahedra in separate plots.
Can you explain how the individual plots can represent more accurate RGBCMY colors. I changed ‘jet’ to ‘prism’ and that was much closer, but I can not tell if the color order is correct nor how to adjust each fill color closer to actual color.
Appreciate your help.
Ernest—The plots are simply showing faces of a tetrahedra. The colors I chose to display the faces with don’t have anything to do “real” colors.
Understood. However, can you explain how to change the colors?
Ernest—Look at setting the FaceColor property. The code for setting that is shown on the page you asked about.
Not exactly on topic, but you seem like the man in the know!
I have two contour plots, one with range 0-10 and the other with range 0-5. When applying the colormap it is scaled to fit the data range, but when displaying the images next to each other I want them to share the same scale, so that like colour contours match up. Is there an easy way to achieve this without messing around with the original data for the plots?
Thanks in advance,
Malcolm—I’m not sure exactly how you are displaying the various pieces together (one figure? multiple figures? subplots?), but you might try explicitly setting the CLim property of the axes objects involved.
It’s single figure with two filled contour plots placed using subplot. I’ll take a look at CLim and see what I can do with that. Thanks for the heads up it’s appreciated.
I am working on a picture obtained via an infrared camera. Each color correspond to a specific temperature (i have the colormap giving the temperature correspondance), i would like to see this picture in gray so that cold colors will be in dark and colors corresponding to hot regions will be in white. Is it possible to do it simply? (Just using rgb2gray is not a solution).
Thank you for your help!
Herve—Compute the gray value you would like to see for each specified color in the original, and then form a new colormap by replicating the desired gray value in each of the three columns.
What would be best way to visually represent a 16x16x16 RGB histogram? I was thinking of using color to represent the count in each bin a 3-dimension space. Is this the right way to go about it? If not, could you give me some cues?
Jack—I’m sorry, but I don’t know. I’ve never done any work with 3-D histogram visualization.
I downloaded McNames ColorSpiral.m and am running it with the default parameters
cmap = ColorSpiral(64,2,0); colormap(cmap); pcolor(time,height,numbers);shading interp
I printed B&W copies of the resulting plots and discovered that they do *not* appear to be linear in greyscale, although they’ve got only 1 internal light band compared to the 2 in “Jet”. Has anyone else found this? Does anyone understand it? I’ve written to McNames but received no response.
Leslie—I remember also finding that McNames’ method didn’t actually have linear grayscale appearance, but I don’t remember the details. That was one of the reasons I wanted to experiment with a Lab-based method.
Yes, I’ve had the same trouble as Leslie. I can’t use Steve’s approach as I don’t have the image processing toolbox. Other colormaps seeking to be useful in grayscale are at
I am a master student working on color printing and gamut issues. I want to convert from RGB to Lab based on Adobe98 not based on sRGB. in makecform list there is not adobe just sRGB. Could you please let me know how to do that.
Thank you in advance
Nawar—Although makecform does not support conversions with AdobeRGB, the appropriate formulas are readily available online.
I hade the same problem.
This happens – I think – because McNames assumed gray = 1/3 r + 1/3 g + 1/3 b. I read from Matlab help online that this is not how the conversion is done if you use rgb2gray, therefore the issue. For those that like me do not have the Image Processing Toolbox, you can see this by just applying the formula that rgb2gray uses which is G=(0.2989 * R + 0.5870 * G + 0.1140 * B).
For my purposes (display to normal and color-deficient people) it was sufficient to being able to switch back and forth between colorspiral and an equivalent grayscale, which I derived by using the average of R, G, and B, I=(R/3 + G/3 + B/3).
Unfortunately I have not come across a solution for printing. If I recall this was posted as a challenge in the puzzler too but there was never a solution.
I am working on a perceptual rainbow in Lab space. If and when I get to it I will share it.
Matteo—I vaguely recall reaching the same conclusion about the assumed equal weighting of color components.
This submission seems very promising:
what is the expected range for radius/chroma, 0-100?
Matteo—There’s no fixed range.
Hi again Steve, maybe I asked the wrong question. What I really mean is: is there an upper limit to the value of Chroma? Thank you.
Have you seen any function to create and display the 3D outline of CRT gamut in Lab coordinates? it would be interesting to be able to plot your
Lab = [L, a, b];
line (and any other created with this method) to test if it’s within the gamut.
and see if