- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想根据其 rgb 值查找颜色名称。
示例 RGB 值是:(237, 65, 83)
预定义值
array(11, 'Red', '#FF0000', '255,0,0'),
array(3, '棕色', '#A52A2A', '165,42,42')
如果我使用这种方法 distance calculation
我的颜色变成棕色。
但是如果我们测试那个 rgb 值,实际颜色是红色 here
已编辑 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);
}
?>
最佳答案
所以如果你想要两种颜色之间的距离(r0,g0,b0)
和 (r1,g1,b1)
检测最接近的颜色而不考虑其强度(这就是本例中基色的含义)你应该
// 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);
这种方法比较深色会变得不稳定,所以你可以添加简单的条件,比如
if (c0<treshold) color is dark
并且仅将此类颜色与灰色阴影进行比较或返回未知颜色。我们的视觉工作方式与我们无法安全地识别深色的方式类似......
无论如何,HSV 颜色空间更适合颜色比较,因为它更类似于人类的颜色识别。所以转换RGB -> HSV
并计算忽略值 V
的距离这是颜色的强度...
在 HSV 中你需要处理 H
作为一个周期性的完整圆值,所以变化只能是圆的一半大。 S
告诉你它是颜色还是灰度,必须单独处理,V
是强度。
// 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;
一些要比较的东西......
您应该目视检查您的源代码以真正了解发生了什么,否则您将原地踏步而没有任何结果。例如,我刚刚在 C++/VCL/mine image class 中编写了这个代码:
union color
{
DWORD dd; WORD dw[2]; byte db[4];
int i; short int ii[2];
color(){}; color(color& a){ *this=a; }; ~color(){}; color* operator = (const color *a) { dd=a->dd; return this; }; /*color* operator = (const color &a) { ...copy... return this; };*/
};
enum{ // this is inside my picture:: class
_x=0, // dw
_y=1,
_b=0, // db
_g=1,
_r=2,
_a=3,
_v=0, // db
_s=1,
_h=2,
};
void rgb2hsv(color &c)
{
double r,g,b,min,max,del,h,s,v,dr,dg,db;
r=c.db[picture::_r]; r/=255.0;
g=c.db[picture::_g]; g/=255.0;
b=c.db[picture::_b]; b/=255.0;
min=r; if (min>g) min=g; if(min>b) min=b;
max=r; if (max<g) max=g; if(max<b) max=b;
del=max-min;
v=max;
if (del<=1e-10) { h=0; s=0; } // grayscale
else{
s=del/max;
dr=(((max-r)/6.0)+(del/2.0))/del;
dg=(((max-g)/6.0)+(del/2.0))/del;
db=(((max-b)/6.0)+(del/2.0))/del;
if (fabs(r-max)<1e-10) h=db-dg;
else if (fabs(g-max)<1e-10) h=(1.0/3.0)+dr-db;
else if (fabs(b-max)<1e-10) h=(2.0/3.0)+dg-dr;
if (h<0.0) h+=1.0;
if (h>1.0) h-=1.0;
}
c.db[picture::_h]=h*255.0;
c.db[picture::_s]=s*255.0;
c.db[picture::_v]=v*255.0;
}
void hsv2rgb(color &c)
{
int i;
double r,g,b,h,s,v,vh,v1,v2,v3,f;
h=c.db[picture::_h]; h/=255.0;
s=c.db[picture::_s]; s/=255.0;
v=c.db[picture::_v]; v/=255.0;
if (s<=1e-10) { r=v; g=v; b=v; } // grayscale
else{
vh=h*6.0;
if (vh>=6.0) vh=0.0;
f=floor(vh); i=f;
v1=v*(1.0-s);
v2=v*(1.0-s*( vh-f));
v3=v*(1.0-s*(1.0-vh+f));
if (i==0) { r=v ; g=v3; b=v1; }
else if (i==1) { r=v2; g=v ; b=v1; }
else if (i==2) { r=v1; g=v ; b=v3; }
else if (i==3) { r=v1; g=v2; b=v ; }
else if (i==4) { r=v3; g=v1; b=v ; }
else { r=v ; g=v1; b=v2; }
}
c.db[picture::_r]=r*255.0;
c.db[picture::_g]=g*255.0;
c.db[picture::_b]=b*255.0;
}
struct _base_color
{
DWORD rgb,hsv;
const char *nam;
_base_color(DWORD _rgb,const char *_nam){ nam=_nam; rgb=_rgb; color c; c.dd=rgb; rgb2hsv(c); hsv=c.dd; }
_base_color(){};
_base_color(_base_color& a){};
~_base_color(){};
_base_color* operator = (const _base_color *a){};
//_base_color* operator = (const _base_color &a);
};
const _base_color base_color[]=
{
// 0x00RRGGBB
_base_color(0x00000000,"Black"),
_base_color(0x00808080,"Gray"),
_base_color(0x00C0C0C0,"Silver"),
_base_color(0x00FFFFFF,"White"),
_base_color(0x00800000,"Maroon"),
_base_color(0x00FF0000,"Red"),
_base_color(0x00808000,"Olive"),
_base_color(0x00FFFF00,"Yellow"),
_base_color(0x00008000,"Green"),
_base_color(0x0000FF00,"Lime"),
_base_color(0x00008080,"Teal"),
_base_color(0x0000FFFF,"Aqua"),
_base_color(0x00000080,"Navy"),
_base_color(0x000000FF,"Blue"),
_base_color(0x00800080,"Purple"),
_base_color(0x00FF00FF,"Fuchsia"),
_base_color(0x00000000,"")
};
void compare_colors()
{
picture pic0;
int h0,s0,v0,h1,s1,v1,x,y,i,d,i0,d0;
int r0,g0,b0,r1,g1,b1,c0,c1,q,xx;
color c;
pic0.resize(256*4,256);
pic0.pf=_pf_rgba;
for (y=0;y<256;y++)
for (x=0;x<256;x++)
{
// get color from image
c=pic0.p[y][x];
xx=x;
r0=c.db[picture::_r];
g0=c.db[picture::_g];
b0=c.db[picture::_b];
rgb2hsv(c);
h0=c.db[picture::_h];
s0=c.db[picture::_s];
v0=c.db[picture::_v];
// naive RGB
xx+=256;
for (i0=-1,d0=-1,i=0;base_color[i].nam[0];i++)
{
// compute distance
c.dd=base_color[i].rgb;
r1=c.db[picture::_r];
g1=c.db[picture::_g];
b1=c.db[picture::_b];
// no need for sqrt
d=((r1-r0)*(r1-r0))+((g1-g0)*(g1-g0))+((b1-b0)*(b1-b0));
// remember closest match
if ((d0<0)||(d0>d)) { d0=d; i0=i; }
}
pic0.p[y][xx].dd=base_color[i0].rgb;
// normalized RGB
xx+=256;
c0=sqrt((r0*r0)+(g0*g0)+(b0*b0));
if (!c0) i0=0; else
for (i0=-1,d0=-1,i=1;base_color[i].nam[0];i++)
{
// compute distance
c.dd=base_color[i].rgb;
r1=c.db[picture::_r];
g1=c.db[picture::_g];
b1=c.db[picture::_b];
c1=sqrt((r1*r1)+(g1*g1)+(b1*b1));
// no need for sqrt
q=((r0*c1)-(r1*c0))/4; q*=q; d =q;
q=((g0*c1)-(g1*c0))/4; q*=q; d+=q;
q=((b0*c1)-(b1*c0))/4; q*=q; d+=q;
d/=c1*c0; d<<=16; d/=c1*c0;
// remember closest match
if ((d0<0)||(d0>d)) { d0=d; i0=i; }
}
pic0.p[y][xx].dd=base_color[i0].rgb;
// HSV
xx+=256;
for (i0=-1,d0=-1,i=0;base_color[i].nam[0];i++)
{
// compute distance
c.dd=base_color[i].hsv;
h1=c.db[picture::_h];
s1=c.db[picture::_s];
v1=c.db[picture::_v];
// no need for sqrt
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 grayscales
}
q=v1-v0; q*=q; d+=q;
// remember closest match
if ((d0<0)||(d0>d)) { d0=d; i0=i; }
}
pic0.p[y][xx].dd=base_color[i0].rgb;
}
pic0.bmp->Canvas->Brush->Style=bsClear;
pic0.bmp->Canvas->Font->Color=clBlack;
x =256; pic0.bmp->Canvas->TextOutA(5+x,5,"Naive RGB");
x+=256; pic0.bmp->Canvas->TextOutA(5+x,5,"Normalized RGB");
x+=256; pic0.bmp->Canvas->TextOutA(5+x,5,"HSV");
pic0.bmp->Canvas->Brush->Style=bsSolid;
//pic0.save("colors.png");
}
你可以忽略pic0
东西它只是对图像的像素访问。我在 RGB 距离方程中添加了一些怪癖来移动子结果,使它们适合 32 位 int
s 以避免溢出。作为输入,我使用这张图片:
对于每个像素,然后从 LUT 中找到相应的基色。这是结果:
左边是源图,然后是朴素的RGB比较,然后是Normalized RGB比较(无法区分相同的颜色深浅)和右边的< strong>HSV比较。
对于标准化的 RGB,找到的颜色始终是 LUT 中颜色相同但强度不同的第一个颜色。比较选择较暗的只是因为它们在 LUT 中排在第一位。
正如我之前提到的,深色和灰度颜色是这方面的问题,应该单独处理。如果你得到了相似的结果,但检测仍然错误,那么你需要添加更多的基色来弥补差距。如果您根本没有类似的结果,那么您很可能遇到了以下问题:
<0,255>
每个 channel 某处溢出
当数字相乘时,使用的位被相加 !!!所以
8bit * 8bit * 8bit * 8bit = 32bit
如果数字是有符号的,你就有麻烦了……如果像我在上面的例子中那样使用 32 位变量,那么你需要稍微移动范围或在 <0.0,1.0>
上使用 FPU间隔。
为了确保我还添加了我的HSV/RGB 转换,以防您在那里遇到问题。
这里是原始 HSV 生成的转换:
关于algorithm - RGB 值基色名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37475739/
我正在尝试做这样的事情:Name[i] = "Name"+ (i+1) 在 forloop 中,这样数组的值将是:Name[0] = Name1,Name[1] = Name2,Name[2] = N
我读了here,在GSP中我们可以这样写: ${params.action} 从GSP中,我们可以使用${params.action}作为参数调用Javascript函数(请参阅here)。 是否有其
我的问题:非常具体。我正在尝试想出解析以下文本的最简单方法: ^^domain=domain_value^^version=version_value^^account_type=account_ty
我创建了一条与此类似的路线: Router::connect("/backend/:controller/:action/*"); 现在我想将符合此模式的每个 Controller 路由重命名为类似
我在 Visual Studio 2013 项目中收到以下警告: SQL71502 - Procedure has an unresolved reference to object 最佳答案 这可以
任何人都可以指导我使用名称/值 .NET 集合或 .NET 名称/值字典以获得最佳性能吗?请问最好的方法是什么?我的应用程序是 ASP.NET、WCF/WF Web 应用程序。每个集合应该有 10 到
我在 Zend Framework 2 中有一个默认模块: namespace Application\Controller; use Zend\Mvc\Controller\AbstractActi
这是表格: 关于javascript - 在 javascript 中,这是一个有效的结构吗? : document. 名称.名称.值?,我们在Stack Overflow上找到一个类似的
HtmlHelper.ActionLink(htmlhelper,string linktext,string action) 如何找出正确的路线? 如果我有这个=> HtmlHelper.Actio
我需要一些有关如何将 Controller 定义传递给嵌套在 outer 指令中的 inner 指令的帮助。请参阅http://plnkr.co/edit/Om2vKdvEty9euGXJ5qan一个
请提出一个数据结构来表示内存中的记录列表。每条记录由以下部分组成: 用户名 积分 排名(基于积分)- 可选字段- 可以存储在记录中或可以动态计算 数据结构应该支持高效实现以下操作: Insert(re
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我想要一个包含可变数量函数的函数,但我希望在实际使用它们之前不要对它们求值。我可以使用 () => type 语法,但我更愿意使用 => type 语法,因为它似乎是为延迟评估而定制的。 当我尝试这样
我正在编写一个 elisp 函数,它将给定键永久绑定(bind)到当前主要模式的键盘映射中的给定命令。例如, (define-key python-mode-map [C-f1] 'pytho
卡在R中的错误上。 Error in names(x) <- value : 'names' attribute must be the same length as the ve
我有字符串,其中包含名称,有时在字符串中包含用户名,后跟日期时间戳: GN1RLWFH0546-2020-04-10-18-09-52-563945.txt JOHN-DOE-2020-04-10-1
有人知道为什么我会收到此错误吗?这显示将我的项目升级到新版本的Unity3d之后。 Error CS0103: The name `Array' does not exist in the curre
由于 Embarcadero 的 NNTP 服务器从昨天开始就停止响应,我想我可以在这里问:我使用非数据库感知网格,我需要循环遍历数据集以提取列数、它们的名称、数量行数以及每行中每个字段的值。 我知道
在构建Android应用程序的子项目中,我试图根据根build.gradle中的变量设置版本代码/名称。 子项目build.gradle: apply plugin: 'com.android.app
示例用例: 我有一个带有属性“myProperty”的对象,具有 getter 和 setter(自 EcmaScript 5 起支持“Property Getters 和 Setters”:http
我是一名优秀的程序员,十分优秀!