PHP中颜色之间的“距离”
Posted
技术标签:
【中文标题】PHP中颜色之间的“距离”【英文标题】:"Distance" between colours in PHP 【发布时间】:2010-12-10 16:02:11 【问题描述】:我正在寻找一个可以将两种颜色之间的距离准确地表示为数字或其他东西的函数。
例如,我希望有一个 HEX 值数组或 RGB 数组,并且我想在数组中找到给定颜色最相似的颜色
例如。我向函数传递一个 RGB 值,然后返回数组中“最接近”的颜色
【问题讨论】:
类似问题:***.com/questions/1313/… 【参考方案1】:每种颜色在十六进制代码中都表示为一个元组。要确定紧密匹配,您需要分别减去每个 RGB 分量。
例子:
Color 1: #112233
Color 2: #122334
Color 3: #000000
Difference between color1 and color2: R=1, G=1 B=1 = 0x3
Difference between color3 and color1: R=11, G=22, B=33 = 0x66
So color 1 and color 2 are closer than
1 and 3.
编辑
所以你想要最接近的命名颜色?使用每种颜色的十六进制值创建一个数组,对其进行迭代并返回名称。像这样的东西;
function getColor($rgb)
// these are not the actual rgb values
$colors = array(BLUE =>0xFFEEBB, RED => 0x103ABD, GREEN => 0x123456);
$largestDiff = 0;
$closestColor = "";
foreach ($colors as $name => $rgbColor)
if (colorDiff($rgbColor,$rgb) > $largestDiff)
$largestDiff = colorDiff($rgbColor,$rgb);
$closestColor = $name;
return $closestColor;
function colorDiff($rgb1,$rgb2)
// do the math on each tuple
// could use bitwise operates more efficiently but just do strings for now.
$red1 = hexdec(substr($rgb1,0,2));
$green1 = hexdec(substr($rgb1,2,2));
$blue1 = hexdec(substr($rgb1,4,2));
$red2 = hexdec(substr($rgb2,0,2));
$green2 = hexdec(substr($rgb2,2,2));
$blue2 = hexdec(substr($rgb2,4,2));
return abs($red1 - $red2) + abs($green1 - $green2) + abs($blue1 - $blue2) ;
【讨论】:
我知道我需要获取 RGB 值,但我正在寻找一个函数,它可以返回数组中给定颜色的“最相似”颜色。一个简单的例子:[BLUE , RED, DARKRED, GREEN] 如果函数被赋予颜色 LIGHTBLUE,从上面的数组中,我希望函数返回 "BLUE" Cheers Philip 如果您根本不使用十六进制值,只需创建一个带有大 switch 语句的函数,该语句采用颜色名称并返回您认为最接近的颜色名称。 colofDiff 函数很好,但必须修复一个错误作为回报,“返回 abs($red1 - $red2) + abs($green1 - $green2) + abs($blue1 - $blue2 ) ;" 我知道这篇文章已经有多年历史了......但我注意到,这也需要改变两件事:1.我们正在寻找最小的Diff(为了 gt 最接近的颜色,对?) 所以将colorDiff($rgbColor,$rgb) > $largestDiff
更改为<
和2. 我们应该将数字保存为字符串而不是十六进制数字,因为我们使用的是substr()
。
这篇文章现在已经有多年历史了,但你是对的@Deproblemify 和其他问题。正如您所说:1)colorDiff($rgbColor,$rgb) > $largestDiff)
需要为colorDiff($rgbColor,$rgb) < $largestDiff)
,但也 2)$largestDiff 的初始值应设置为 256 而不是 0,以便可以比较每种颜色以查看它是否比最大范围更近跨度>
【参考方案2】:
Here is a paper on the subject 应该会给出一个很好的答案。
我认为首先转换为 HSL/HSV 也是一个好主意,但后来我意识到,在 S & L/V 的极端值下,H 无关紧要,而在中间,它最重要。
我认为如果你想要一个简单的解决方案,留在 RGB 空间会更明智。我会使用笛卡尔距离。如果您正在考虑将颜色R G B
与Ri Gi Bi
对比为几个i
,您需要最小化的i
(R - Ri)^2 + (G - Gi)^2 + (B - Bi)^2
【讨论】:
【参考方案3】:首先,您必须选择要进行颜色比较的适当颜色空间(RGB、HSV、HSL、CMYK 等)。
假设您想知道 3 维 RGB 空间中的两个点之间的距离,您可以计算它们之间的毕达哥拉斯距离,即,
d2 = (r1 - r2)**2 + (g1 - g2)**2 + (b1 - b2)**2;
这实际上给出了距离的平方。 (如果您只比较平方值,则不需要平方根。)
这假设您希望平等对待 R、G 和 B 值。如果您更愿意对各个颜色分量进行加权,例如将 RGB 转换为灰度时会发生什么,则必须为距离的每个项添加一个系数,即,
d2 = 30*(r1-r2)**2 + 59*(g1-g2)**2 + 11*(b1-b2)**2;
这假设了从 RGB 到 30% 红色 + 59% 绿色 + 11% 蓝色的灰度的流行转换。
更新
最后一个方程应该是
d2 = (30*(r1-r2))**2 + (59*(g1-g2))**2 + (11*(b1-b2))**2;
【讨论】:
【参考方案4】:一个非常简单的方法是计算三个维度之间的汇总距离。例如 simple_distance("12,10,255","10,10,250")=7
更复杂的方法是将每个组件的距离平方并将它们相加 - 这样组件太远将受到更多“惩罚”: square_distance("12,10,255","10,10,250") =2*2+0*0+5*5=29。
当然,您必须遍历颜色列表并找到最接近的颜色。
【讨论】:
【参考方案5】:您可以将 RGB 值转换为 HSL 或 HSV。那么颜色很容易比较:首先按色调排列颜色,然后按饱和度,然后按亮度排列。在结果顺序中,彼此相邻的 2 种颜色在感知上会显得非常接近。
注意色相环绕:对于从 0 到 255 的色相,0 的色相和 255 的色相非常接近。
请参阅有关 HSL http://en.wikipedia.org/wiki/HSL_and_HSV 的***文章,了解允许您将 RGB 转换为 HSL 的公式
(请注意,其他颜色空间,如 L.a.b.,可能会提供更好的结果,但转换更复杂)
让我们用数学来定义:
distance(A(h,s,l), B(h,s,l)) = (A(h)-B(h)) * F^2 + (A(s)-B(s)) * F + (A(l)-B(l))
其中 F 是一个精心选择的因子(例如 256...)
上面的公式没有考虑色调环绕...
【讨论】:
这毫无意义。如果颜色 A 和 B 的亮度差异很小,色调相同,而颜色 A 和 C 的亮度相同,色调差异很大(比如说一个是红色,另一个是绿色......),那么 A 和 C 之间的距离B 会大于 A 和 C 之间的距离... 您似乎误解了我建议的排序:您首先按色调排序,然后按饱和度排序具有相同色调的颜色,最后按亮度排序具有相同色调和饱和度的颜色。鉴于此顺序,颜色 A 和 B 具有相同的色调,并且距离 (A,B) 小于 (A,C)。 我编辑了我的答案以包含一个小的数学公式,我希望这有助于更好地理解排序...... 这也没有任何意义,抱歉。就拿我的第一条评论,交换“亮度”和“色调”这两个词,然后删除括号中的部分。【参考方案6】:颜色感知不是线性的because the human eye is more sensitive to certain colors than others.
你需要使用一个特殊的公式。
看here。
【讨论】:
以上是关于PHP中颜色之间的“距离”的主要内容,如果未能解决你的问题,请参考以下文章