Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CIE plot using Matlab ?

1,672 views
Skip to first unread message

Geico Caveman

unread,
Dec 31, 2007, 10:52:36 PM12/31/07
to
Hello

I was wondering how one plots something like this :

http://en.wikipedia.org/wiki/Image:CIExy1931.svg

The axis is in "bent" into that shape and each x axis value corresponds to
the wavelength of light, which in turn corresponds (roughly) to the colour
shown on the plot. Monochromatic colours form the locus of the plot (the
axis), while mixed colors define the interior.

I have searched on file exchange, and though there are some hits that come
close (mainly relating to conversion of color spaces), there is really
nothing I could find.

Can anyone suggest how this plot may be plotted ? After plotting, I would
have to add contours / points to the plot to represent actual experimental
data.

Doug Schwarz

unread,
Jan 1, 2008, 1:52:41 AM1/1/08
to
In article <flcde4$rrg$1...@aioe.org>,
Geico Caveman <spammers...@spam.invalid> wrote:

Start by downloading the 1931 CIE color matching functions, x_bar, y_bar
and z_bar from

<http://www.cvrl.org/database/data/cmfs/ciexyz31_1.txt>

Next, compute x and y:

x = x_bar./(x_bar + y_bar + z_bar);
y = y_bar./(x_bar + y_bar + z_bar);

Then plot them:

plot(x,y)


That gets you the shape you want. To fill it with color, something like
what is shown on the web page, you need to make a patch:

% assume x_bar, etc. are column vectors.
n = length(x_bar);
rgb = reshape([x_bar,y_bar,z_bar],[n 1 3]);
p = patch(x,y,rgb);

The colors on that patch are about the correct hue, but most are too
dark. As I'm not sure exactly what you are trying to do I'll let you
figure out how to go from here.

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Geico Caveman

unread,
Jan 1, 2008, 3:01:32 AM1/1/08
to
Doug Schwarz wrote:

Thanks for the quick turn around (and happy new year !).

I tried out what you suggested.

All I get is a closed dark line defining the shape (that is what the patch
command does after the initial plot command plots an open curve in blue).
The area inscribed by this shape is white/blank (needs to be colored
according to the CIE coordinates). Further, I need tick marks along the
shape, marking out the locus of monochromatic emissions.

I am trying to plot out CIE values (as isolated points) calculated from the
spectra of a bunch of LEDs onto a colored CIE plot like the one in the URL.

I will try to take it from here, but was wondering if you had any further
pointers.

Geico Caveman

unread,
Jan 1, 2008, 10:16:40 PM1/1/08
to
Doug Schwarz wrote:

I am using the following table for the tristimulus values and x, y and z :

http://www.isc.tamu.edu/~astro/color/cie_xyz1964.html

The code you presented above has a bug : the reshape should be on x, y and
z, not the tristimulus values.

The hues are rather dark and it does not look like a CIE plot.


Doug Schwarz

unread,
Jan 4, 2008, 12:57:38 AM1/4/08
to
In article <flevmo$uf0$1...@aioe.org>,
Geico Caveman <spammers...@spam.invalid> wrote:

> Doug Schwarz wrote:
>
> > In article <flcde4$rrg$1...@aioe.org>,
> > Geico Caveman <spammers...@spam.invalid> wrote:
> >
> >> Hello
> >>
> >> I was wondering how one plots something like this :
> >>
> >> http://en.wikipedia.org/wiki/Image:CIExy1931.svg

[snip]

> > Start by downloading the 1931 CIE color matching functions, x_bar, y_bar
> > and z_bar from
> >
> > <http://www.cvrl.org/database/data/cmfs/ciexyz31_1.txt>
> >
> > Next, compute x and y:
> >
> > x = x_bar./(x_bar + y_bar + z_bar);
> > y = y_bar./(x_bar + y_bar + z_bar);
> >
> > Then plot them:
> >
> > plot(x,y)
> >
> >
> > That gets you the shape you want. To fill it with color, something like
> > what is shown on the web page, you need to make a patch:
> >
> > % assume x_bar, etc. are column vectors.
> > n = length(x_bar);
> > rgb = reshape([x_bar,y_bar,z_bar],[n 1 3]);
> > p = patch(x,y,rgb);
> >
> > The colors on that patch are about the correct hue, but most are too
> > dark. As I'm not sure exactly what you are trying to do I'll let you
> > figure out how to go from here.
> >
>
> I am using the following table for the tristimulus values and x, y and z :
>
> http://www.isc.tamu.edu/~astro/color/cie_xyz1964.html
>
> The code you presented above has a bug : the reshape should be on x, y and
> z, not the tristimulus values.
>
> The hues are rather dark and it does not look like a CIE plot.


I finally had a chance to work on this some more. Try this code:

% x_bar, etc are column vectors at wavelengths, wl.


x = x_bar./(x_bar + y_bar + z_bar);
y = y_bar./(x_bar + y_bar + z_bar);

wl = wl(:);
n = length(wl);

% blue blue cyan green yellow orange red red
wl0 = [360 470 492 520 575 600 630 830]'; % wavelengths in nm.
rgb0 = [0 0 1;0 0 1;0 1 1;0 1 0;1 1 0;1 0.5 0;1 0 0;1 0 0];
rgb = [pchip(wl0,rgb0(:,1),wl), pchip(wl0,rgb0(:,2),wl),...
pchip(wl0,rgb0(:,3),wl)];

for k = 1:n-1
rgb2 = permute([1 1 1;rgb(k,:);rgb(k+1,:)],[1 3 2]);
patch([1/3;x(k:k+1)],[1/3;y(k:k+1)],rgb2,'edgecolor','none');
end
rgb2 = permute([1 1 1;rgb(end,:);rgb(1,:)],[1 3 2]);
patch([1/3;x([end 1])],[1/3;y([end 1])],rgb2,'edgecolor','none');

patch(x,y,'-k','facecolor','none','edgecolor','k')

hold on
plot(1/3,1/3,'ok')
hold off

axis equal
axis([0 .8 0 .9])

This code can be vectorized -- I just didn't bother. The appearance
isn't identical to the plot from wikipedia, but it's close. You can
play with the reference wavelengths, wl0, if you think you might be able
to do better.

Basically, instead of a single polygon, we now have a series of small
wedges with the color of the common center point being white.

I didn't plot the wavelengths around the arc, but you should be able to
handle that.

Interesting problem.

Jonathan

unread,
Dec 1, 2009, 1:50:11 PM12/1/09
to
Try out the following code. To plot any points or contours you'll have to convert the CIE coordinates to MATLAB image coordinates (see the creation of nciex and nciey for example). The first function used can be found on the file exchange. Also note that an srgb display can't display the whole gamut so the colors out side of this region shouldn't be trusted. To see only the valid colors you can uncomment the 'mask' line and comment out the other one.

[WL, xFcn, yFcn, zFcn] = colorMatchFcn('CIE_1931');

v=[0:.001:1];
[x,y]=meshgrid(v,v); y=flipud(y);
z=(1-x-y);
rgb=applycform(cat(3,x,y,z),makecform('xyz2srgb'));
ciex=xFcn./sum([xFcn; yFcn; zFcn],1);
ciey=yFcn./sum([xFcn; yFcn; zFcn]);
nciex=ciex*size(rgb,2);
nciey=size(rgb,1)-ciey*size(rgb,1);

%mask=~any(rgb==0,3); mask=cat(3,mask,mask,mask);
mask=roipoly(rgb,nciex,nciey); mask=cat(3,mask,mask,mask);
figure; imshow(rgb.*mask+~mask); hold on;

[C,IA,IB]=intersect(WL,[400 460 470 480 490 520 540 560 580 600 620 700]);
text(nciex(IA),nciey(IA),num2str(WL(IA).'));
axis on;
set(gca,'XTickLabel',get(gca,'XTick')/(size(rgb,2)-1));
set(gca,'YTickLabel',1-get(gca,'YTick')/(size(rgb,1)-1));

title('CIE Chromaticity'); xlabel('x'); ylabel('y');

Adi

unread,
Nov 16, 2010, 9:13:04 AM11/16/10
to
"Jonathan " <froma...@hotmail.com> wrote in message <hf3oh3$jes$1...@fred.mathworks.com>...

Hello Jonathan,

I am trying to plot the CIE 1976 Lu'v' chromaticity diagram. I've tried adapting your code to it but it did not work. I am having trouble creating the L, u' and v' mesh grids. While with the XYZ coordinates the Z is dependent on the X and Y, with the Lu'v' coordinates I cannot find such dependancy which I could implement in the code. Do you have any suggestions?

I thank you in advance, Adi.

0 new messages