[R] measuring distances between colours?

John Fox jfox at mcmaster.ca
Sat Jun 1 18:44:23 CEST 2013


Hi Ken,

I just tried that, and with a distance of 15 as the criterion, which seemed to work well for Lav distances, I get fewer matches for the following example that we've been using:

> cols <- c("#010101", "#EEEEEE", "#AA0000", "#00AA00", "#0000AA", "#AAAA00", "#AA00AA", "#00AAAA")
> (nms <- rgb2col(cols, near=15))
[1] "black"         "gray93"        "firebrick"     "#00AA00"      
[5] "#0000AA"       "#AAAA00"       "#AA00AA"       "lightseagreen"

Do you know what a JND is supposed to be on the Luv distance scale? The Wikipedia article on CIELUV colours doesn't say.

Best,
 John

> -----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
> formulated to
> > provide uniform perceptual differences between colours, with a JND of
> > approximately of 2.3. Ken Knoblauch made a similar point. The article
> goes
> > on to describe relatively complicated adjustments meant to improve
> the LAV
> > distance metric, which are probably overkill for my application.
> >
> > I've programmed Lab colour matching as follows, using Euclidean
> distances
> > 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",
> to="Lab",
> > 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
> (as I
> > did previously) direct RGB distances, matching more colours to names
> and
> > providing (to my eye, with my monitor) perceptually closer matches,
> though
> > 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",
> "#AAAA00",
> > "#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,
> question.
> >
> > Best,
> > John
> >
> >> -----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
> in
> >> 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
> >> Eik
> >>> Vettorazzi's suggestion for improved conversion of hexadecimal RGB
> >> colours
> >>> to decimal numbers, and Martin Maechler's hint to look at
> >> demo(colors). I've
> >>> loosened the default definition of "close enough" from the latter,
> >> since the
> >>> 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) %%
> >> 256)
> >>>     }
> >>>     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",
> >> "AAAA00",
> >>> "AA00AA", "00AAAA"))
> >>> [1] "black"         "gray93"        "darkred"       "green4"
> >>> [5] "blue4"         "darkgoldenrod" "darkmagenta"   "cyan4"
> >>>
> >>>> rgb2col(c("010101", "090909", "090000", "000900", "000009",
> >> "090900",
> >>> "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
> >
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-
> guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list