【问题标题】:Mapping hex/hsl values to a color range将 hex/hsl 值映射到颜色范围
【发布时间】:2019-11-26 01:52:38
【问题描述】:

给定一个 hex/rgb/hsl 值,我如何将该值放入自定义范围内,比如 11 种基本颜色,如红色、蓝色等

我能做的最好的就是通过肉眼匹配 hsl 中的色调范围,但饱和度和亮度会改变感知的颜色。

我正在寻找一种算法来适应颜色范围内的所述值。

【问题讨论】:

  • 好吧,只是一个非常笼统的想法:如果通道值50(RGB 或其他)在0 - 255 的范围内,则该值是完整的0.1961范围。您还可以结合所有渠道来获得这样的价值。现在假设您将基本颜色映射到01 之间的范围,您可以将0.1961 映射到其中一种颜色。

标签: php hex rgb hsl


【解决方案1】:

如果您只说 11 种基本颜色(例如红色、橙色、黄色、绿色、青色、蓝色、紫色、洋红色、黑色、白色、灰色),我会说您已经在那里了。只要颜色在 S 和 L 的合理范围内,您只需要色调匹配即可匹配颜色本身。

在我看来,任何大于 95ish 的 L 都足够接近白色,而任何小于 5ish 的 L 都足够接近黑色。

然后,如果您的 S 小于 10,则您的选项是黑色、灰色和白色,具体取决于 L,您甚至可以使用相同的规则。黑色 = 95,否则为灰色。

然后,为了匹配色调,使用我的示例颜色列表,您不能真正使用统一的范围,因为光谱红色端的颜色差异远小于青色端的颜色差异。您可以手动定义它们,也可以使用逻辑函数获得相当好的结果。


TL:DR;数学的东西,可能有点矫枉过正。

我只关注色调,因为为此制定公式是不必要且复杂的。

话虽如此,这是我对与常见颜色感知相匹配的逻辑函数的尝试。

您可以根据需要调整 k 值。我认为 1.1 给出了合理的价差(尽管我只尝试了几个值)。 8 为您提供了您希望从此函数中获得的值的数量。因此,由于我们尝试匹配 8 种不同的颜色(除了黑色、白色和灰色),因此我使用了 8 种。

3 将域向右移动 3 个单位。我使用 3 是因为它是我们将用于此函数的域的一半(中点两侧各 3 个单位)。

为了澄清,这是最终的功能:

对于 x,此公式已调整为具有最小值 0 和最大值 6,并且将从青色开始。所以如果0 <= f(x) < 1,它是绿色的;如果1 <= f(x) < 2 是青色等。

由于它从青色开始,您必须调整色调输入值,使 0 等于您认为是青色而不是绿色的边缘。让我们以 150 为例。这意味着青色的宽度为 60 度,这是我得到 1.1 K 值的地方,因为它排列得非常好。

那么我们的 x 值将是 x = ((hue + (360 - 150)) % 360) / 60.0x = (hue + 210) % 360) / 60.0

然后我们可以将它代入我们的 f(x) 并得到一个 0 到 8 之间的数字,我们可以使用它来获得我们怀疑的颜色。如果我们制作一个颜色数组,我们可以将值取底并将其用作索引,因为我们的 0-6 域将为我们提供大约 0.36-7.7 的范围,所以它永远不会超过 8 或低于 0。

[cyan, blue, purple, magenta, red, orange, yellow, green]

这是矫枉过正吗?可能。

它更有趣吗?肯定的。


最后是代码

function hsl($h, $s, $l){
    $options = array("cyan", "blue", "purple", "magenta", "red", "orange", "yellow", "green");
    if($l >= 95)
        return "white";
    else if($l <= 5)
        return "black";
    else if($s <= 10)
        return "gray";

    //Convert hue to x value
    $x = (($h + 210) % 360) / 60.0;
    $match = matchHue($x);
    return $options[$match];
}

function matchHue($x){
    return intval(floor(8 / (1 + pow(M_E, (-1.1 * ($x - 3))))));
}

这完全取决于您的用例以及您尝试使用的颜色,所以 ymmv,但是如果您想要一个公式而不是硬编码列表,那么像这样的逻辑函数可能是您反映感知颜色的最佳选择从色调。


更加矫枉过正。因为为什么不呢?

如果您想要 S 和 L 的更多选项,例如具有额外的颜色深浅,您可以使用相同样式的逻辑函数,甚至只是线性函数。

亮度将遵循相同的功能。中等灰色将是最大的一块,因此您可以将 x=0 设置为中等灰色的下限。

饱和度更像是一个对数函数。前 25% 左右有几种可识别的色调,而上面的 75% 则少得多。像

其中 N 是要识别的阴影数。这个函数的域是0-100,范围是0-N。您可以根据自己的喜好调整 k 以更改台阶的宽度,但即使将 k 保留为 1 也应该会产生足够的结果。

【讨论】:

  • 是的,这几乎就是我所做的,一个硬编码的色调值列表和一些 L 发挥作用的边缘情况,例如低 L 的黄色和绿色。非常感谢大卫,你放了一些努力回答你的问题
猜你喜欢
  • 2014-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多