随机生成 3 种不同的颜色

Randomly generate 3 distinct colors

我看过 this one 但对随机部分没有帮助。有没有更好的方法来随机生成 3 种不同的颜色,以便在下面的代码中正方形、圆形和文本在视觉上彼此脱颖而出。颜色必须是随机生成的,并且彼此之间必须有足够的区别。当前代码可能只有一半时间有效

plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
    ann = FALSE, axes = FALSE, asp = 1)

cols = colorRampPalette(sample(2:9,2), alpha = TRUE)(8)

polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])

symbols(x = 5, y = 5, circles = 4, inches = FALSE,
    add = TRUE, bg = cols[4], fg = NA)

text(x = 5, y = 5, labels = "Hi", col = cols[7], font = 2, cex = 3)

例子

多边形:“#FF00FFFF”,圆形:“#916DFFFF”,文本:“#24DAFFFF”

不好

多边形:“#00FFFFFF”,圆形:“#51E3E3FF”,文本:“#A2C7C7FF”

我的原始答案使用 hcl 颜色 space,经常生成难以区分的颜色组合。此更新后的答案使用 Lab 颜色 space,它根据颜色之间的感知距离进行缩放,因此 Lab space 中的相似距离应该对应于相似的感知颜色差异。在 Lab 中,L 是亮度或亮度,范围为 0 到 100。a 表示绿色到红色,b代表蓝色到黄色,都在-100到100之间。

下面的代码为 ab 生成两个随机值。如果我们将这两个值视为代表 ab 平面中的一个点,则通过先将该点旋转 120 度然后旋转 240 度,我们可以生成另外两种具有最大感知距离的颜色。然后我们选择一个 L 值来为我们提供三种相同的 spaced 颜色。

下面我将其封装在一个函数中,以便轻松生成多个具有随机颜色的图。我还为 a 和 b 设置了一个最小绝对值,这样我们就不会得到太相似的颜色,并包含一个 Lval 参数来选择 Lab 颜色的 L 值。

基于几次运行,看起来这种方法比我原来的 hcl 版本执行得更好(尽管这可能不仅仅是因为使用 Lab space 而不是 hcl space ,还因为我只使用了 hcl space 的一维,而使用了 Lab space) 的二维。

library(colorspace)

random.colors = function(Lval=80, ABmin=50) {
  
  # 120 deg rotation matrix
  aa = 2*pi/3
  rot = matrix(c(cos(aa), -sin(aa), sin(aa), cos(aa)), nrow=2, byrow=TRUE)
  
  # Generate random A and B points in LAB space
  x = runif(2, ABmin, 100) * sample(c(-1,1), 2,replace=TRUE) 
  
  # Create three equally spaced colors in Lab space and convert to RGB
  cols = LAB(cbind(rep(Lval,3), rbind(x, x %*% rot, x %*% rot %*% rot)))
  cols = rgb(convertColor(cols@coords, from="Lab", to="sRGB"))
  
  plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
       ann = FALSE, axes = FALSE, asp = 1)
  
  polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])
  
  symbols(x = 5, y = 5, circles = 4, inches = FALSE,
          add = TRUE, bg = cols[2], fg = NA)
  
  text(x = 5, y = 5, labels = "Hi", col = cols[3], font = 2, cex = 3)
}

par(mfrow=c(3,3), mar=rep(0,4))
replicate(9,random.colors())  

为简单起见,上面的示例将 a 和 b 值限制为与原点(在 ab-space 中)的恒定距离,并对所有三种颜色使用相同的 L 值。您可以改为扩展此方法以使用实验室的所有三个维度 space。此外,不需要与原点保持恒定距离,您可以随机选择第一种颜色,然后要求选择接下来的两种颜色,使得所有三种颜色在 Lab space 中彼此最大程度地分开。

原答案

您可以生成在色相维度上等 spaced 的颜色(即,彼此之间具有最大可能的色相分离)。例如:

set.seed(60)
cols = hcl(runif(1,0,359.99) + c(0,120,240), 100, 65)

plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
     ann = FALSE, axes = FALSE, asp = 1)

polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])

symbols(x = 5, y = 5, circles = 4, inches = FALSE,
        add = TRUE, bg = cols[2], fg = NA)

text(x = 5, y = 5, labels = "Hi", col = cols[3], font = 2, cex = 3)

这里还有九次随机抽奖。如您所见,有些组合效果不佳。但也许你可以尝试不同的方法来分割颜色 space 看看你是否能得到更好的东西。

一种超级简单的方法是在八种 "standard" 颜色中取样。

par(mar=c(0, 0, 0, 0))
set.seed(1)
plot(0, type = "n", xlim = c(0,10), ylim = c(0,10),
    ann = FALSE, axes = FALSE, asp = 1)

cols <- sample(2:8, 3)

polygon(x = c(1,9,9,1), y = c(1,1,9,9), border = NA, col = cols[1])

symbols(x = 5, y = 5, circles = 4, inches = FALSE,
    add = TRUE, bg = cols[2], fg = NA)

text(x = 5, y = 5, labels = "Hi", col = cols[3], font = 2, cex = 3)