[R] measuring distances between colours?
Jim Lemon
jim at bitwrit.com.au
Thu May 30 14:30:18 CEST 2013
On 05/30/2013 10:13 PM, John Fox wrote:
> Dear r-helpers,
>
> I'm interested in locating the named colour that's "closest" to an arbitrary RGB colour. 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
>
Hi John,
Ben Bolker contributed a function (color.id) to the plotrix package that
does something like this. Although it uses RGB colorspace, it might be
useful:
color.id<-function (col) {
c2 <- col2rgb(col)
coltab <- col2rgb(colors())
cdist <- apply(coltab, 2, function(z) sum((z - c2)^2))
colors()[which(cdist == min(cdist))]
}
Jim
More information about the R-help
mailing list