Dear Martin, > -----Original Message----- > From: Martin Maechler [mailto:maech...@stat.math.ethz.ch] > Sent: Thursday, May 30, 2013 9:18 AM > To: John Fox > Cc: r-help@r-project.org > Subject: Re: [R] measuring distances between colours? > > Dear John, > > >>>>> John Fox <j...@mcmaster.ca> > >>>>> on Thu, 30 May 2013 08:13:19 -0400 writes: > > > Dear r-helpers, > > I'm interested in locating the named colour that's "closest" to > an arbitrary RGB colour. > > Hmm, maybe I was not really marketing well enough > what I had added for R 3.0.0 :
Or I didn't look carefully enough! I think that I would have found nearRcolor() had it been a function in R rather than in a demo, but I didn't think to try demo(color). This provides the solution that I was looking for, in that there's a criterion for acceptable proximity for colour matches. I see that the default comparison is in the HSV colour space, so I suppose that Marius judged that to be best, at least for close colours. Is that right? Thank you, John > > ----------------------------------------------------------------------- > - > r61127 | maechler | 2012-11-17 20:00:58 +0100 (Sat, 17 Nov 2012) | 1 > line > > new option colors(distinct=TRUE); new demo(colors) & demo(hclColors) > ----------------------------------------------------------------------- > - > > demo(colors) contains a few niceties, some originating from > ------------ Marius Hofert, > notably for you the function nearRcolor() > > which has the nice extra that you can specify the color *space* > in which to measure nearness. > > > ##' Find close R colors() to a given color {original by Marius Hofert) > ##' using Euclidean norm in (HSV / RGB / ...) color space > nearRcolor <- function(rgb, cSpace = c("hsv", "rgb255", "Luv", "Lab"), > dist = switch(cSpace, "hsv" = 0.10, "rgb255" = > 30, > "Luv" = 15, "Lab" = 12)) > { > if(is.character(rgb)) rgb <- col2rgb(rgb) > stopifnot(length(rgb <- as.vector(rgb)) == 3) > Rcol <- col2rgb(.cc <- colors()) > uniqC <- !duplicated(t(Rcol)) # gray9 == grey9 (etc) > Rcol <- Rcol[, uniqC] ; .cc <- .cc[uniqC] > cSpace <- match.arg(cSpace) > convRGB2 <- function(Rgb, to) > t(convertColor(t(Rgb), from="sRGB", to=to, scale.in=255)) > ## the transformation, rgb{0..255} --> cSpace : > TransF <- switch(cSpace, > "rgb255" = identity, > "hsv" = rgb2hsv, > "Luv" = function(RGB) convRGB2(RGB, "Luv"), > "Lab" = function(RGB) convRGB2(RGB, "Lab")) > d <- sqrt(colSums((TransF(Rcol) - as.vector(TransF(rgb)))^2)) > iS <- sort.list(d[near <- d <= dist])# sorted: closest first > setNames(.cc[near][iS], format(d[near][iS], digits=3)) > } > > > You should use the full > > demo(colors) > > or browse > > https://svn.r- > project.org/R/trunk/src/library/grDevices/demo/colors.R > > to also get a few nice examples.. > > Martin > > > > > > The best that I've been able to come up is the following, which uses > HSV colours for the comparison: > > > > > r2c <- function(){ > > hexnumerals <- 0:15 > > names(hexnumerals) <- c(0:9, LETTERS[1:6]) > > hex2decimal <- function(hexnums){ > > hexnums <- strsplit(hexnums, "") > > decimals <- matrix(0, 3, length(hexnums)) > > decimals[1, ] <- sapply(hexnums, function(x) > > sum(hexnumerals[x[1:2]] * c(16, 1))) > > decimals[2, ] <- sapply(hexnums, function(x) > > sum(hexnumerals[x[3:4]] * c(16, 1))) > > decimals[3, ] <- sapply(hexnums, function(x) > > sum(hexnumerals[x[5:6]] * c(16, 1))) > > decimals > > } > > colors <- colors() > > hsv <- rgb2hsv(col2rgb(colors)) > > function(cols){ > > cols <- sub("^#", "", toupper(cols)) > > dec.cols <- rgb2hsv(hex2decimal(cols)) > > colors[apply(dec.cols, 2, function(dec.col) > > which.min(colSums((hsv - dec.col)^2)))] > > } > > } > > > > rgb2col <- r2c() > > > > I've programmed this with a closure so that hsv gets computed only > once. > > > > Examples: > > > > > rgb2col(c("AA0000", "002200", "000099", "333300", "BB00BB", > "#005555")) > > [1] "darkred" "darkgreen" "blue4" "darkgreen" "magenta3" > "darkgreen" > > > rgb2col(c("AAAA00", "#00AAAA")) > > [1] "darkgoldenrod" "cyan4" > > > > Some of these colour matches, e.g., "#005555" -> "darkgreen" seem > poor to me. Even if the approach is sound, I'd like to be able to > detect that there is no sufficiently close match in the vector of named > colours. That is, can I establish a maximum acceptable distance in the > HSV (or some other) colour space? > > > > I vaguely recall a paper or discussion concerning colour > representation in R but can't locate it. > > > > Any suggestions would be appreciated. > > > > John > > > > ------------------------------------------------ > > John Fox > > Sen. William McMaster Prof. of Social Statistics > > Department of Sociology > > McMaster University > > Hamilton, Ontario, Canada > > http://socserv.mcmaster.ca/jfox/ ______________________________________________ R-help@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.