【问题标题】:Randomly generate 3 distinct colors随机生成 3 种不同的颜色
【发布时间】:2017-09-11 05:34:10
【问题描述】:

我查看了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”

【问题讨论】:

  • 你能定义“从彼此中脱颖而出”吗?为什么这不是在 RGB 或 HSV 空间(或其他一些变换空间)中最大化数值距离的简单案例?如果您发布几个好坏图像并用所使用的文本(#TTTTTT)、圆圈(#CCCCCC)、正方形(#SSSSSS)值标记每个图像,这可能会有很大帮助,因此读者可以对此有所了解.
  • d.b,计算这两个调色板在 RGB 和 HSV 空间中的(欧几里得?)距离,归一化为单位立方体/圆柱体。就像我说的,我认为这应该能说明问题。这称为色差
  • 几乎相同的问题:How to compare two colors for similarity/difference,但更笼统
  • 如果我们随意设置圆圈为黑色(/白色)的约束,是否会使这个问题更客观?
  • 一些不错的 java 答案 here 可以很容易地移植到 R。library(randomcoloR) 也有一个简洁的函数 distinctColorPalette()

标签: r colors rgb color-scheme hsv


【解决方案1】:

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

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

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

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

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 空间中),并对所有三种颜色使用相同的 L 值。您可以改为扩展此方法以使用实验室空间的所有三个维度。此外,您可以随机选择第一种颜色,然后要求选择接下来的两种颜色,以使所有三种颜色在 Lab 空间中最大程度地相互分离,而不是要求与原点保持恒定距离。

原答案

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

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)

这里还有九个随机抽奖。如您所见,有些组合效果不太好。但也许您可以尝试不同的方法来分割色彩空间,看看是否可以得到更好的结果。

【讨论】:

    【解决方案2】:

    一种超级简单的方法是在八种“标准”颜色中进行采样。

    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)
    

    【讨论】:

      猜你喜欢
      • 2016-07-17
      • 1970-01-01
      • 2018-10-22
      • 2021-06-02
      • 2021-04-17
      • 1970-01-01
      • 2011-12-29
      • 2021-07-20
      • 1970-01-01
      相关资源
      最近更新 更多