>>>>> John Fox <j...@mcmaster.ca> >>>>> on Thu, 30 May 2013 09:58:18 -0400 writes:
> 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). Yes, of course. The problem with introducing nearRcolor() as a standard function is that -- for back compatibility reasons -- one should rather choose all the defaults "right" in the sense that we cannot easily *change* the defaults later. But I agree that demos are probably too much hidden, and we (?) should probably consider adding some of these functions to grDevices so they are seen and used. > 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? actually, his original used only RGB distance, and I've added the whole idea of "distance with respect to color space", and I did chose HSV as clearly more sensical than RGB. I remember having thought about choosing Lab / Luv as default, but do no longer remember via I ended up staying with HSV. Martin > 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.