Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Dynare
dynare
Commits
ba780220
Commit
ba780220
authored
Jan 09, 2017
by
Marco Ratto
Committed by
Stéphane Adjemian
Mar 17, 2017
Browse files
end of lines
parent
06176caf
Changes
2
Expand all
Hide whitespace changes
Inline
Side-by-side
matlab/utilities/graphics/colorspace.m
View file @
ba780220
This diff is collapsed.
Click to expand it.
matlab/utilities/graphics/distinguishable_colors.m
View file @
ba780220
function
colors
=
distinguishable_colors
(
n_colors
,
bg
,
func
)
% DISTINGUISHABLE_COLORS: pick colors that are maximally perceptually distinct
%
% When plotting a set of lines, you may want to distinguish them by color.
% By default, Matlab chooses a small set of colors and cycles among them,
% and so if you have more than a few lines there will be confusion about
% which line is which. To fix this problem, one would want to be able to
% pick a much larger set of distinct colors, where the number of colors
% equals or exceeds the number of lines you want to plot. Because our
% ability to distinguish among colors has limits, one should choose these
% colors to be "maximally perceptually distinguishable."
%
% This function generates a set of colors which are distinguishable
% by reference to the "Lab" color space, which more closely matches
% human color perception than RGB. Given an initial large list of possible
% colors, it iteratively chooses the entry in the list that is farthest (in
% Lab space) from all previously-chosen entries. While this "greedy"
% algorithm does not yield a global maximum, it is simple and efficient.
% Moreover, the sequence of colors is consistent no matter how many you
% request, which facilitates the users' ability to learn the color order
% and avoids major changes in the appearance of plots when adding or
% removing lines.
%
% Syntax:
% colors = distinguishable_colors(n_colors)
% Specify the number of colors you want as a scalar, n_colors. This will
% generate an n_colors-by-3 matrix, each row representing an RGB
% color triple. If you don't precisely know how many you will need in
% advance, there is no harm (other than execution time) in specifying
% slightly more than you think you will need.
%
% colors = distinguishable_colors(n_colors,bg)
% This syntax allows you to specify the background color, to make sure that
% your colors are also distinguishable from the background. Default value
% is white. bg may be specified as an RGB triple or as one of the standard
% "ColorSpec" strings. You can even specify multiple colors:
% bg = {'w','k'}
% or
% bg = [1 1 1; 0 0 0]
% will only produce colors that are distinguishable from both white and
% black.
%
% colors = distinguishable_colors(n_colors,bg,rgb2labfunc)
% By default, distinguishable_colors uses the image processing toolbox's
% color conversion functions makecform and applycform. Alternatively, you
% can supply your own color conversion function.
%
% Example:
% c = distinguishable_colors(25);
% figure
% image(reshape(c,[1 size(c)]))
%
% Example using the file exchange's 'colorspace':
% func = @(x) colorspace('RGB->Lab',x);
% c = distinguishable_colors(25,'w',func);
% Copyright 2010-2011 by Timothy E. Holy
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% * Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
% Parse the inputs
if
(
nargin
<
2
)
bg
=
[
1
1
1
];
% default white background
else
if
iscell
(
bg
)
% User specified a list of colors as a cell aray
bgc
=
bg
;
for
i
=
1
:
length
(
bgc
)
bgc
{
i
}
=
parsecolor
(
bgc
{
i
});
end
bg
=
cat
(
1
,
bgc
{:});
else
% User specified a numeric array of colors (n-by-3)
bg
=
parsecolor
(
bg
);
end
end
% Generate a sizable number of RGB triples. This represents our space of
% possible choices. By starting in RGB space, we ensure that all of the
% colors can be generated by the monitor.
n_grid
=
30
;
% number of grid divisions along each axis in RGB space
x
=
linspace
(
0
,
1
,
n_grid
);
[
R
,
G
,
B
]
=
ndgrid
(
x
,
x
,
x
);
rgb
=
[
R
(:)
G
(:)
B
(:)];
if
(
n_colors
>
size
(
rgb
,
1
)/
3
)
error
(
'You can
''
t readily distinguish that many colors'
);
end
% Convert to Lab color space, which more closely represents human
% perception
if
(
nargin
>
2
)
lab
=
func
(
rgb
);
bglab
=
func
(
bg
);
else
C
=
makecform
(
'srgb2lab'
);
lab
=
applycform
(
rgb
,
C
);
bglab
=
applycform
(
bg
,
C
);
end
% If the user specified multiple background colors, compute distances
% from the candidate colors to the background colors
mindist2
=
inf
(
size
(
rgb
,
1
),
1
);
for
i
=
1
:
size
(
bglab
,
1
)
-
1
dX
=
bsxfun
(
@
minus
,
lab
,
bglab
(
i
,:));
% displacement all colors from bg
dist2
=
sum
(
dX
.^
2
,
2
);
% square distance
mindist2
=
min
(
dist2
,
mindist2
);
% dist2 to closest previously-chosen color
end
% Iteratively pick the color that maximizes the distance to the nearest
% already-picked color
colors
=
zeros
(
n_colors
,
3
);
lastlab
=
bglab
(
end
,:);
% initialize by making the "previous" color equal to background
for
i
=
1
:
n_colors
dX
=
bsxfun
(
@
minus
,
lab
,
lastlab
);
% displacement of last from all colors on list
dist2
=
sum
(
dX
.^
2
,
2
);
% square distance
mindist2
=
min
(
dist2
,
mindist2
);
% dist2 to closest previously-chosen color
[
~
,
index
]
=
max
(
mindist2
);
% find the entry farthest from all previously-chosen colors
colors
(
i
,:)
=
rgb
(
index
,:);
% save for output
lastlab
=
lab
(
index
,:);
% prepare for next iteration
end
end
function
c
=
parsecolor
(
s
)
if
ischar
(
s
)
c
=
colorstr2rgb
(
s
);
elseif
isnumeric
(
s
)
&&
size
(
s
,
2
)
==
3
c
=
s
;
else
error
(
'MATLAB:InvalidColorSpec'
,
'Color specification cannot be parsed.'
);
end
end
function
c
=
colorstr2rgb
(
c
)
% Convert a color string to an RGB value.
% This is cribbed from Matlab's whitebg function.
% Why don't they make this a stand-alone function?
rgbspec
=
[
1
0
0
;
0
1
0
;
0
0
1
;
1
1
1
;
0
1
1
;
1
0
1
;
1
1
0
;
0
0
0
];
cspec
=
'rgbwcmyk'
;
k
=
find
(
cspec
==
c
(
1
));
if
isempty
(
k
)
error
(
'MATLAB:InvalidColorString'
,
'Unknown color string.'
);
end
if
k
~=
3
||
length
(
c
)
==
1
,
c
=
rgbspec
(
k
,:);
elseif
length
(
c
)
>
2
,
if
strcmpi
(
c
(
1
:
3
),
'bla'
)
c
=
[
0
0
0
];
elseif
strcmpi
(
c
(
1
:
3
),
'blu'
)
c
=
[
0
0
1
];
else
error
(
'MATLAB:UnknownColorString'
,
'Unknown color string.'
);
end
end
end
function
colors
=
distinguishable_colors
(
n_colors
,
bg
,
func
)
% DISTINGUISHABLE_COLORS: pick colors that are maximally perceptually distinct
%
% When plotting a set of lines, you may want to distinguish them by color.
% By default, Matlab chooses a small set of colors and cycles among them,
% and so if you have more than a few lines there will be confusion about
% which line is which. To fix this problem, one would want to be able to
% pick a much larger set of distinct colors, where the number of colors
% equals or exceeds the number of lines you want to plot. Because our
% ability to distinguish among colors has limits, one should choose these
% colors to be "maximally perceptually distinguishable."
%
% This function generates a set of colors which are distinguishable
% by reference to the "Lab" color space, which more closely matches
% human color perception than RGB. Given an initial large list of possible
% colors, it iteratively chooses the entry in the list that is farthest (in
% Lab space) from all previously-chosen entries. While this "greedy"
% algorithm does not yield a global maximum, it is simple and efficient.
% Moreover, the sequence of colors is consistent no matter how many you
% request, which facilitates the users' ability to learn the color order
% and avoids major changes in the appearance of plots when adding or
% removing lines.
%
% Syntax:
% colors = distinguishable_colors(n_colors)
% Specify the number of colors you want as a scalar, n_colors. This will
% generate an n_colors-by-3 matrix, each row representing an RGB
% color triple. If you don't precisely know how many you will need in
% advance, there is no harm (other than execution time) in specifying
% slightly more than you think you will need.
%
% colors = distinguishable_colors(n_colors,bg)
% This syntax allows you to specify the background color, to make sure that
% your colors are also distinguishable from the background. Default value
% is white. bg may be specified as an RGB triple or as one of the standard
% "ColorSpec" strings. You can even specify multiple colors:
% bg = {'w','k'}
% or
% bg = [1 1 1; 0 0 0]
% will only produce colors that are distinguishable from both white and
% black.
%
% colors = distinguishable_colors(n_colors,bg,rgb2labfunc)
% By default, distinguishable_colors uses the image processing toolbox's
% color conversion functions makecform and applycform. Alternatively, you
% can supply your own color conversion function.
%
% Example:
% c = distinguishable_colors(25);
% figure
% image(reshape(c,[1 size(c)]))
%
% Example using the file exchange's 'colorspace':
% func = @(x) colorspace('RGB->Lab',x);
% c = distinguishable_colors(25,'w',func);
% Copyright 2010-2011 by Timothy E. Holy
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% * Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
% Parse the inputs
if
(
nargin
<
2
)
bg
=
[
1
1
1
];
% default white background
else
if
iscell
(
bg
)
% User specified a list of colors as a cell aray
bgc
=
bg
;
for
i
=
1
:
length
(
bgc
)
bgc
{
i
}
=
parsecolor
(
bgc
{
i
});
end
bg
=
cat
(
1
,
bgc
{:});
else
% User specified a numeric array of colors (n-by-3)
bg
=
parsecolor
(
bg
);
end
end
% Generate a sizable number of RGB triples. This represents our space of
% possible choices. By starting in RGB space, we ensure that all of the
% colors can be generated by the monitor.
n_grid
=
30
;
% number of grid divisions along each axis in RGB space
x
=
linspace
(
0
,
1
,
n_grid
);
[
R
,
G
,
B
]
=
ndgrid
(
x
,
x
,
x
);
rgb
=
[
R
(:)
G
(:)
B
(:)];
if
(
n_colors
>
size
(
rgb
,
1
)/
3
)
error
(
'You can
''
t readily distinguish that many colors'
);
end
% Convert to Lab color space, which more closely represents human
% perception
if
(
nargin
>
2
)
lab
=
func
(
rgb
);
bglab
=
func
(
bg
);
else
C
=
makecform
(
'srgb2lab'
);
lab
=
applycform
(
rgb
,
C
);
bglab
=
applycform
(
bg
,
C
);
end
% If the user specified multiple background colors, compute distances
% from the candidate colors to the background colors
mindist2
=
inf
(
size
(
rgb
,
1
),
1
);
for
i
=
1
:
size
(
bglab
,
1
)
-
1
dX
=
bsxfun
(
@
minus
,
lab
,
bglab
(
i
,:));
% displacement all colors from bg
dist2
=
sum
(
dX
.^
2
,
2
);
% square distance
mindist2
=
min
(
dist2
,
mindist2
);
% dist2 to closest previously-chosen color
end
% Iteratively pick the color that maximizes the distance to the nearest
% already-picked color
colors
=
zeros
(
n_colors
,
3
);
lastlab
=
bglab
(
end
,:);
% initialize by making the "previous" color equal to background
for
i
=
1
:
n_colors
dX
=
bsxfun
(
@
minus
,
lab
,
lastlab
);
% displacement of last from all colors on list
dist2
=
sum
(
dX
.^
2
,
2
);
% square distance
mindist2
=
min
(
dist2
,
mindist2
);
% dist2 to closest previously-chosen color
[
~
,
index
]
=
max
(
mindist2
);
% find the entry farthest from all previously-chosen colors
colors
(
i
,:)
=
rgb
(
index
,:);
% save for output
lastlab
=
lab
(
index
,:);
% prepare for next iteration
end
end
function
c
=
parsecolor
(
s
)
if
ischar
(
s
)
c
=
colorstr2rgb
(
s
);
elseif
isnumeric
(
s
)
&&
size
(
s
,
2
)
==
3
c
=
s
;
else
error
(
'MATLAB:InvalidColorSpec'
,
'Color specification cannot be parsed.'
);
end
end
function
c
=
colorstr2rgb
(
c
)
% Convert a color string to an RGB value.
% This is cribbed from Matlab's whitebg function.
% Why don't they make this a stand-alone function?
rgbspec
=
[
1
0
0
;
0
1
0
;
0
0
1
;
1
1
1
;
0
1
1
;
1
0
1
;
1
1
0
;
0
0
0
];
cspec
=
'rgbwcmyk'
;
k
=
find
(
cspec
==
c
(
1
));
if
isempty
(
k
)
error
(
'MATLAB:InvalidColorString'
,
'Unknown color string.'
);
end
if
k
~=
3
||
length
(
c
)
==
1
,
c
=
rgbspec
(
k
,:);
elseif
length
(
c
)
>
2
,
if
strcmpi
(
c
(
1
:
3
),
'bla'
)
c
=
[
0
0
0
];
elseif
strcmpi
(
c
(
1
:
3
),
'blu'
)
c
=
[
0
0
1
];
else
error
(
'MATLAB:UnknownColorString'
,
'Unknown color string.'
);
end
end
end
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment