RGB 值基色名称

use*_*nan 3 algorithm rgb colors

我想找到颜色名称,给出它的 RGB 值。

RGB 值示例为:(237, 65, 83)

预定义值

数组(11, '红色', '#FF0000', '255,0,0'),

array(3, '棕色', '#A52A2A', '165,42,42')

如果我使用这种方法距离计算

我得到的颜色是棕色的。

但如果我们在这里测试 RGB 值,实际颜色是红色

已编辑 1

<?php 

 $colors = array(
 array(1, 'Black', '#000000', '0,0,0'),
 array(2, 'Blue',  '#0000FF', '0,0,255'),
 array(3, 'Brown', '#A52A2A', '165,42,42'),    
 array(4, 'Cream', '#FFFFCC', '255,255,204'),   
 array(5, 'Green', '#008000', '0,128,0'),        
 array(6, 'Grey',  '#808080', '128,128,128'),
 array(7, 'Yellow', '#FFFF00', '255,255,0'),
 array(8, 'Orange', '#FFA500', '255,165,0'),          
 array(9, 'Pink', '#FFC0CB', '255,192,203'), 
 array(11, 'Red', '#FF0000', '255,0,0'),  
 array(10, 'Purple', '#800080', '128,0,128'),
 array(12, 'Tan', '#d2b48c', '210,180,140'),
 array(13, 'Turquoise', '#40E0D0', '64,224,208'),
 array(14, 'White', '#FFFFFF', '255,255,255')
   );



 $miDist = 99999999999999999 ;
 $loc = 0 ; 



 $findColor = RGBtoHSV(72, 70, 68);
 for( $i = 0 ; $i < 14 ; $i++){
  $string =  $colors[$i][3];
  $pieces = explode(',' , $string);
  $r0 = $pieces[0];
  $g0 = $pieces[1];
  $b0 = $pieces[2];

  $storedColor = RGBtoHSV($r0,$g0,$b0);

 echo $storedColor[0] ."-" . $storedColor[1] ;
 // distance between colors (regardless of intensity)


 $d = sqrt( ($storedColor[0]-$findColor[0])
      *($storedColor[0]-$findColor[0])
      + 
      ($storedColor[1]-$findColor[1])
      *($storedColor[1]-$findColor[1])



      );



  echo $colors[$i][1] ."=" .$d;
  //echo $d ;
     if( $miDist >= $d )
       {
       $miDist = $d;
       $loc = $i ;    
       } 
      echo "<br>" ;


 }

 echo $colors[$loc][1];









 function RGBtoHSV($R, $G, $B)    // RGB values:    0-255, 0-255, 0-255
 {                                // HSV values:    0-360, 0-100, 0-100
// Convert the RGB byte-values to percentages
$R = ($R / 255);
$G = ($G / 255);
$B = ($B / 255);

// Calculate a few basic values, the maximum value of R,G,B, the
//   minimum value, and the difference of the two (chroma).
$maxRGB = max($R, $G, $B);
$minRGB = min($R, $G, $B);
$chroma = $maxRGB - $minRGB;

// Value (also called Brightness) is the easiest component to calculate,
//   and is simply the highest value among the R,G,B components.
// We multiply by 100 to turn the decimal into a readable percent value.
$computedV = 100 * $maxRGB;

// Special case if hueless (equal parts RGB make black, white, or grays)
// Note that Hue is technically undefined when chroma is zero, as
//   attempting to calculate it would cause division by zero (see
//   below), so most applications simply substitute a Hue of zero.
// Saturation will always be zero in this case, see below for details.
if ($chroma == 0)
    return array(0, 0, $computedV);

// Saturation is also simple to compute, and is simply the chroma
//   over the Value (or Brightness)
// Again, multiplied by 100 to get a percentage.
$computedS = 100 * ($chroma / $maxRGB);

// Calculate Hue component
// Hue is calculated on the "chromacity plane", which is represented
//   as a 2D hexagon, divided into six 60-degree sectors. We calculate
//   the bisecting angle as a value 0 <= x < 6, that represents which
//   portion of which sector the line falls on.
if ($R == $minRGB)
    $h = 3 - (($G - $B) / $chroma);
elseif ($B == $minRGB)
    $h = 1 - (($R - $G) / $chroma);
else // $G == $minRGB
    $h = 5 - (($B - $R) / $chroma);

// After we have the sector position, we multiply it by the size of
//   each sector's arc (60 degrees) to obtain the angle in degrees.
$computedH = 60 * $h;

return array($computedH, $computedS, $computedV);
 }

 ?>
Run Code Online (Sandbox Code Playgroud)

Spe*_*tre 5

因此,如果您想要两种颜色之间的距离(r0,g0,b0)并(r1,g1,b1)检测最接近的颜色,无论其强度如何(这就是本例中基色的含义),您应该

  1. 将颜色向量标准化为通用大小
  2. 计算距离
  3. 将结果按比例缩小
// variables
int r0,g0,b0,c0;
int r1,g1,b1,c1,d;
// color sizes
c0=sqrt(r0*r0+g0*g0+b0*b0);
c1=sqrt(r1*r1+g1*g1+b1*b1);
// distance between normalized colors
d = sqrt((r0*c1-r1*c0)^2 + (g0*c1-g1*c0)^2 + (b0*c1-b1*c0)^2) / (c0*c1);
Run Code Online (Sandbox Code Playgroud)

比较深色时,这种方法会变得不稳定,因此您可以添加简单的条件,例如

if (c0<treshold)  color is dark 
Run Code Online (Sandbox Code Playgroud)

并且仅将这种颜色与灰色阴影进行比较或返回未知颜色。我们的视觉工作原理类似,我们无法安全地识别深色......

无论如何,HSV 颜色空间更适合颜色比较,因为它更类似于人类颜色识别。因此,转换RGB -> HSV和计算距离忽略V颜色强度值......

在HSV中,您需要将其处理H为周期性整圆值,因此变化只能是圆大的一半。S告诉您它是颜色还是灰度,必须单独处理,并且V是强度。

if (c0<treshold)  color is dark 
Run Code Online (Sandbox Code Playgroud)

有些事情需要比较...

您应该对源进行目视检查,以实际了解发生了什么,否则您将原地踏步而没有任何结果。例如,我刚刚在C++/VCL/mine 图像类中编写了这个代码:

// variables
int h0,s0,v0;
int h1,s1,v1,d,q;
q=h1-h0;
if (q<-128) q+=256; // use shorter angle
if (q>+128) q-=256; // use shorter angle
         q*=q; d =q;
q=s1-s0; q*=q; d+=q;
if (s0<32)          // grayscales
    {
    d=0;            // ignore H,S
    if (s1>=32) continue; // compare only to gray-scales so ignore this color
    }
q=v1-v0; q*=q; d+=q;
Run Code Online (Sandbox Code Playgroud)

您可以忽略这些pic0内容,它只是对图像的像素访问。我在 RGB 距离方程中添加了一些怪癖来移动子结果,使它们适合 32 位,int以避免溢出。我使用这张图片作为输入:

在

然后对于每个像素,从LUT中找到相应的基色。这是结果:

出去

左边是源图像,然后是朴素的RGB比较,然后是标准化RGB比较(无法区分相同的色调),右边是HSV比较。

对于标准化RGB,找到的颜色始终是LUT中颜色相同但强度不同的第一个颜色。比较仅选择较暗的颜色,因为它们位于LUT中的第一个。

正如我之前提到的,深色和灰度颜色是有问题的,应该单独处理。如果您得到类似的结果但检测仍然错误,那么您需要添加更多的基色来弥补差距。如果您根本没有类似的结果,那么您很可能遇到以下问题:

  1. 我的每个通道的HSV或RGB范围错误<0,255>
  2. 溢出某处

    当数字相乘时,所使用的位被相加!所以

    8bit * 8bit * 8bit * 8bit = 32bit
    
    Run Code Online (Sandbox Code Playgroud)

    如果数字有符号,你就有麻烦了......如果像我在上面的例子中一样使用 32 位变量,那么你需要稍微改变范围或在间隔上使用FPU<0.0,1.0>。

为了确保万一您遇到问题,我还添加了我的HSV/RGB转换。

这里是原始 HSV 生成的转换:

出去