&引用;“距离”;PHP中的颜色之间
我正在寻找一个函数,可以准确地表示两种颜色之间的距离作为一个数字或东西 例如,我希望有一个十六进制值数组或RGB数组,我想找到给定颜色数组中最相似的颜色&引用;“距离”;PHP中的颜色之间,php,colors,Php,Colors,我正在寻找一个函数,可以准确地表示两种颜色之间的距离作为一个数字或东西 例如,我希望有一个十六进制值数组或RGB数组,我想找到给定颜色数组中最相似的颜色 例如,我向函数传递一个RGB值,并返回数组中“最近”的颜色每种颜色都表示为十六进制代码中的元组。要确定紧密匹配,需要分别减去每个RGB分量 例如: Color 1: #112233 Color 2: #122334 Color 3: #000000 Difference between color1 and color2: R=1, G=
例如,我向函数传递一个RGB值,并返回数组中“最近”的颜色每种颜色都表示为十六进制代码中的元组。要确定紧密匹配,需要分别减去每个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) ;
}
一种非常简单的方法是计算三个维度之间的总距离。例如,简单距离(“12,10255”、“10,10250”)=7 一种更复杂的方法是取每个组件的距离平方并求和——这样,过远的组件将受到更多的“惩罚”:平方距离(“12,10255”,“10,10250”)=2*2+0*0+5*5=29
当然,您必须在颜色列表上迭代并找到最接近的颜色。您可以将RGB值转换为HSL或HSV。这样就很容易比较颜色:先按色调,然后按饱和度,再按亮度对颜色进行排序。在生成的顺序中,相邻的两种颜色将显示为在感知上非常接近 请注意,色调环绕:对于从0到255的色调,0和255的色调非常接近 有关将RGB转换为HSL的公式,请参阅wikipedia关于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…)
上面的公式没有考虑环绕的色调…,这应该是一个很好的答案
我想把HSL/HSV转换为一个好主意,但后来我意识到,在S/L/V的极端值下,H并不重要,在中间,它最重要。p>
我认为如果你想要一个简单的解决方案,留在RGB空间会更明智。我会使用笛卡尔距离。如果您考虑将颜色rgb
与Ri-Gi-Bi
进行对比,以获得几个i
,那么您需要最小化的i
(R - Ri)^2 + (G - Gi)^2 + (B - Bi)^2
首先,您必须选择希望进行颜色比较的适当颜色空间(RGB、HSV、HSL、CMYK等) 假设您想知道三维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;
颜色感知不是线性的 你需要使用一个特殊的公式
看。类似问题:我知道我需要获得RGB值,但我正在寻找一个函数,它可以返回给定颜色数组中“最相似”的颜色。一个简单的例子:[蓝、红、暗、绿]如果函数的颜色为浅蓝色,从上面的数组中,我希望函数返回“蓝色”欢呼声,如果你根本没有使用十六进制值,只需创建一个带有大switch语句的函数,该语句采用颜色名称,并返回您认为最接近的颜色名称。colofDiff函数很好,但必须修复一个bug作为回报,“return abs($red1-$red2)+abs($green1-$green2)+abs($blue1-$blue2);“我知道这篇文章已经有好几年了。。。但我注意到,对于这项工作,必须改变两件事:1。我们正在寻找最小的diff(为了获得最接近的颜色,对吗?),所以将
colordff($rgbColor,$rgb)>$largestDiff
更改为,这没有意义。如果颜色A和B的亮度略有不同,色调相同,而颜色A和C的亮度相同,色调差异很大(比如一个是红色,另一个是绿色…),那么A和B之间的距离将大于A和C之间的距离……看来你误解了我提出的顺序:你首先按色调排序,然后按饱和度排序色调相等的颜色,最后按亮度排序色调相等和饱和度相等的颜色。考虑到这种顺序,颜色A和B具有相同的色调,距离(A,B)小于(A,C)。我编辑了我的答案,加入了一个小的数学公式,我希望这有助于更好地理解顺序……对不起,这也没有任何意义。就拿我的第一条评论来说,把“亮度”和“色调”这两个词互换一下,去掉括号里的部分。