-----Original Message-----
From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-
project.org] On Behalf Of Ken Knoblauch
Sent: Saturday, June 01, 2013 12:18 PM
To: John Fox
Cc: <r-help at r-project.org>; Michael Friendly; Martin Maechler
Subject: Re: [R] measuring distances between colours?
Hi John,
Out of curiosity and if it is not much trouble, I would be curious if
Luv worked any better than Lab. I think that Luv is supposed to be
preferred for monitors and Lab for surfaces but they are generally
pretty similar.
Best,
Ken
Sent from my iPhone
___
Ken Knoblauch
Inserm U846
Stem-Cell and Brain Research Institute
18 av du Doyen L?pine
69500 Bron France
Tel : 04 72 91 34 77
Fax : 04 72 91 34 61
portable : 06 84 10 64 10
http://www.sbri.fr/members/kenneth-knoblauch.html
On 1 juin 2013, at 17:31, "John Fox" <jfox at mcmaster.ca> wrote:
Hi Michael,
Thanks for the Wikipedia tip -- I'd looked there but didn't find this
article. The article explains that the Lab colour space was
provide uniform perceptual differences between colours, with a JND of
approximately of 2.3. Ken Knoblauch made a similar point. The article
on to describe relatively complicated adjustments meant to improve
distance metric, which are probably overkill for my application.
I've programmed Lab colour matching as follows, using Euclidean
and adapting Kevin Wright's modification of my original code. I used
convertColor(), which Martin Maechler pointed out to me.
----------- snip --------------
r2c <- function(){
all.names <- colors()
all.lab <- t(convertColor(t(col2rgb(all.names)), from="sRGB",
scale.in=255))
find.near <- function(x.lab) {
sq.dist <- colSums((all.lab - x.lab)^2)
rbind(all.names[which.min(sq.dist)], min(sq.dist))
}
function(cols.hex, near=2.3){
cols.lab <- t(convertColor(t(col2rgb(cols.hex)), from="sRGB",
to="Lab", scale.in=255))
cols.near <- apply(cols.lab, 2, find.near)
ifelse(cols.near[2, ] < near^2, cols.near[1, ], cols.hex)
}
}
rgb2col <- r2c()
----------- snip --------------
A bit of experimentation suggests that this works better than using
did previously) direct RGB distances, matching more colours to names
providing (to my eye, with my monitor) perceptually closer matches,
sometimes with (again to my eye) perceptible differences. Here's an
illustration, adapting one of Kevin's examples:
----------- snip --------------
cols <- c("#010101", "#EEEEEE", "#AA0000", "#00AA00", "#0000AA",
"#AA00AA", "#00AAAA")
(nms <- rgb2col(cols))
pie(rep(1, 2*length(cols)), labels=c(cols, nms), col=c(cols, nms))
----------- snip --------------
Thanks again to everyone who responded to my original, na?ve,
-----Original Message-----
From: Michael Friendly [mailto:friendly at yorku.ca]
Sent: Friday, May 31, 2013 10:24 AM
To: John Fox
Cc: r-help at r-project.org; 'Martin Maechler'
Subject: Re: measuring distances between colours?
Hi John
This has been an interesting discussion.
Though you have a solution for your needs, you might be interested
this javascript implementation that allows you to visually compare
color
distances in various color spaces
http://stevehanov.ca/blog/index.php?id=116
And, all the theory of color distance is described in
http://en.wikipedia.org/wiki/Color_difference
PS: This is a very handy function. When I last tried
aplpack::bagplot(), it was annoying that the colors could *only*
be specified in hex.
-Michael
On 5/30/2013 5:14 PM, John Fox wrote:
Dear all,
My thanks to everyone who addressed my question. I've incorporated
Vettorazzi's suggestion for improved conversion of hexadecimal RGB
to decimal numbers, and Martin Maechler's hint to look at
loosened the default definition of "close enough" from the latter,
following seems to work well for my purposes.
r2c <- function(){
hex2dec <- function(hexnums) {
# suggestion of Eik Vettorazzi
sapply(strtoi(hexnums, 16L), function(x) x %/% 256^(2:0) %%
}
findMatch <- function(dec.col) {
sq.dist <- colSums((hsv - dec.col)^2)
rbind(which.min(sq.dist), min(sq.dist))
}
colors <- colors()
hsv <- rgb2hsv(col2rgb(colors))
function(cols, near=0.25){
cols <- sub("^#", "", toupper(cols))
dec.cols <- rgb2hsv(hex2dec(cols))
which.col <- apply(dec.cols, 2, findMatch)
matches <- colors[which.col[1, ]]
unmatched <- which.col[2, ] > near^2
matches[unmatched] <- paste("#", cols[unmatched], sep="")
matches
}
}
rgb2col <- r2c()
For example,
rgb2col(c("010101", "EEEEEE", "AA0000", "00AA00", "0000AA",
"AA00AA", "00AAAA"))
[1] "black" "gray93" "darkred" "green4"
[5] "blue4" "darkgoldenrod" "darkmagenta" "cyan4"
rgb2col(c("010101", "090909", "090000", "000900", "000009",
"090009", "000909"))
[1] "black" "gray3" "#090000" "#000900" "#000009" "#090900"
[7] "#090009" "#000909"
Thanks again,
John
--
Michael Friendly Email: friendly AT yorku DOT ca
Professor, Psychology Dept. & Chair, Quantitative Methods
York University Voice: 416 736-2100 x66249 Fax: 416 736-5814
4700 Keele Street Web: http://www.datavis.ca
Toronto, ONT M3J 1P3 CANADA