根据绿色对蓝色和红色的数量计算值
Calculate value based on amount of green against blue and red
这个有点卡住了。
这是我的困境:
一种颜色有红、绿、蓝 (RGB) 三种元素。
所有颜色的值都在 0-255 之间。
例如:
var red:int = 53;
var green:int = 150;
var blue:int = 28;
我的评分系统是这样的,颜色越绿,分数越高,满分 10。
所以:
var red:int = 0;
var green:int = 255;
var blue:int = 0;
将获得最高分 (10) 并且:
var red:int = 255;
var green:int = 0;
var blue:int = 255;
将获得最低分数 (0)。
我需要生成某种方程式。 Bayes' Theorum 是我该去的地方吗?
真的一点头绪都没有。
如果只是检查颜色值以从 0 - 255
范围中提取分数 0 - 10
那么只需执行:
score = Math.round( (green / 255 ) * 10 );
根据这个逻辑,我们可以看到:
green = 253 gives score of 10
green = 190 gives score of 7
green = 128
gives score of 5
green = 47 gives score of 2
有一个阈值,如果数字高于 X 但小于 Y,它将给出相同的分数,例如任何 green
介于 243 和 255 之间的分数为 10。
PS:一些可测试的代码:
var score:int = 0;
var green:int = 128; //#change this for testing
score = Math.round( (green / 255 ) * 10 );
trace ("score is : " + score);
这有点棘手,因为有3个组成部分,但如果我理解正确的话,只有一个组成部分决定了你的排名。
你可以完全忽略红色和蓝色成分,只在0-255绿色等级上排名;结果将是绿色 = 64 的两种颜色,但交换了红色和蓝色的值,例如 rgb[100, 64, 50] 和 rgb[50, 64, 100] 将获得相同的分数,因为它们具有相同数量的绿色.这个结果意味着绿色分数是 3D RGB 坐标在 'green axis'.
上的投影
我想出了一个正确的方法。
请查看以下代码:
var color = parseInt(colorString);
var fitness:Number = 0;
var red:int = (color>> 16) & 0xFF;
var green:int = (color>> 8) & 0xFF;
var blue:int = color & 0xFF;
var greenPercentage = (green/255)*100;
var redAndBluePercentage = ((red+blue)/510)*100;
fitness = greenPercentage-redAndBluePercentage;
fitness = (fitness+100)/2;
trace(fitness);
数学是这样的:
把你的颜色分成红色、绿色和蓝色。
计算颜色中绿色的百分比。 (x/255)
取颜色中红色和蓝色的百分比(x/510)
从绿色中减去红色和蓝色百分比。
向其中添加一些数学运算,为您提供 0-100 之间的可能分数。
colorFitness("0xFF00FF"); //Outputs 0
colorFitness("0x00FF00"); //Outputs 100
不幸的是,我不擅长 Action 脚本,因此可以提供真实的代码,但我想我有一些想法可能会对您有所帮助。 AFAIU 你的问题是你想测量给定 RGB 颜色的 "greenishess",同时考虑到所有 3 个分量,使得
- 绿色将获得 100% rait
- 红色或蓝色或洋红色将获得 0%
- 白色(所有 3 个均等混合)会在中间得到一些东西
如果我需要设计这样的方案,我会从 RGB 切换到一些不同的着色方案,例如 YUV or rather HSL/HSV. Actually the "H" component aka Hue 似乎是您所需要的。根据 wiki
Hue is one of the main properties (called color appearance parameters) of a color, defined technically (in the CIECAM02 model), as "the degree to which a stimulus can be described as similar to or different from stimuli that are described as red, green, blue, and yellow"
要计算色调,您首先需要确定最大和最小分量以及它们之间的差异:
M = max(R, G, B)
m = min(R, G, B)
C = M - m
然后
If Red is the Max, then Hue = (G - B)/C
If Green is the Max, then Hue = 2.0 + (B - R)/C
If Blue is the Max, then Hue = 4.0 + (R - G)/C
这会产生 [-1, 5] 范围内的值。您可以将其转换为更传统的度数,将其乘以 60 并将其环绕到 fir [0, 360] 但这并不重要,因为这只是一个线性比例。因此,使用前面定义的 Hue
计算,您可以通过 Hue
值接近 2(或接近 120 的度数)来测量颜色的 "greenishess"。
请注意,对于接近绿色的颜色(即绿色是最大分量的颜色),根据此公式 "greenishess" 计算为
"greenishess" = abs(B - R)/(G - min(B,R))
这对我来说很有意义。 B = R 的部分指定了颜色的饱和度,并且只有 "excess" 的 R 或 B 超过另一个会使颜色从 "pure" 绿色变为黄色或蓝色。
另请注意,您必须为从黑色到白色的所有 "gray" 颜色分配一些任意 "greenishess" 值,因为 C
将为 0,并且您不能除以减少 0.
最后,您不必直接使用 Hue
。您可以基于它构建更复杂的公式。例如,您可以放置一些截止点以将 0% 评级分配给纯红色和蓝色,即分配给 [0; 之外的所有内容。 4] 范围(或 [0; 240] 度)。默认情况下,Hue 只会将 0% 分配给洋红色,即 {Red = 255, Green = 0, Blue = 255}。像
"greenishness" = [2 - abs(min(4, max(0, Hue)) - 2)] / 2 * 100%
您也可以通过应用一些非线性变换来 "curve" 测量。
你的问题是select(r,g,b)
的正确函数return值从0到10。你说(0,255,0)
应该return 10.0,而其他值应 return 更少,而 (255,0,255)
应 return 0。因此,您至少需要 select 该函数的两个参数。一个是 (x,x,x)
处的值(如果你希望那个值相等,否则参数将是 X 的函数),另一个是非极值的插值规则。因此,您的函数应如下所示:
function score(r,g,b:int):Number {
var rc:int=Math.max(0,Math.min(255,r)); // clamp
var gc:int=Math.max(0,Math.min(255,g));
var bc:int=Math.max(0,Math.min(255,b));
const GRAY:Number=5.0; // value at (x,x,x)
if ((rc==rg) and (rc==rb)) return GRAY;
return ir(r,g,b); // interpolation rule
}
事实上,您可以指定所有 8 个角的值,并根据您能想象到的任何法则简单地对它们进行插值。例如,通过相对距离。像这样:
const SCORES:Array=[
0, // black, (0,0,0)
0, // red, (255,0,0)
10, // green, (0,255,0)
6.66666, // yellow, (255,255,0)
0, // blue, (0,0,255)
0, // magenta, (255,0,255)
6.66666, // cyan, (0,255,255)
5.0 // white, (255,255,255)
];
const POINTS:Array=[
{r:0;g:0;b:0},
{r:255;g:0;b:0},
{r:0;g:255;b:0},
{r:255;g:255;b:0},
{r:0;g:0;b:255},
{r:255;g:0;b:255},
{r:0;g:255;b:255},
{r:255;g:255;b:255}
]; // respective points
function score(r,g,b:int):Number {
var rc:int=Math.max(0,Math.min(255,r)); // clamp
var gc:int=Math.max(0,Math.min(255,g));
var bc:int=Math.max(0,Math.min(255,b));
var dists:Array=new Array();
var td:Number=0;
for (var i:int=POINTS.length-1;i>=0;i--)
var dist:Number=distance({r=rc;g=gc;b=bc},POINTS[i]); // TODO
if (dist<1e-6) return SCORES[i]; // we're at the corner
dists.unshift(1.0/dist);
td+=1.0/dist;
}
var result:Number=0;
for (i=POINTS.length-1;i>=0;i--)
result+=SCORES[i]*dists[i]/td;
return result;
}
你没有指定你想要这个等式的目的。我相信这已经说过你有 3 个参数的函数,但你只为两种情况下的单个参数给出预期的输出,并且有许多函数可以满足你的期望,但在这两个输出之间工作完全不同。
我不知道您是否注意到了这一点,但是例如您的 colorFitness
给出了 50
的 0x000000
分数 - 这是您期望的吗?
对于你问题的当前状态,我也可以提出这样的建议。
function score(c:uint) {
var g:uint = (c >>> 8) & 0xFF;
var s:uint = g + (c >>> 16 & g ^ g);
s = (s + (c & 0xFF & g ^ g)) / 0x2FD * 100;
trace("score for", c.toString(16), ":", s);
}
score(0x00FF00); //100
score(0x000000); //0
score(0xFF00FF); //0
score(0xFF7FFF); //16
score(0xFFFFFF); //33
score(0x00FFFF); //66
score(0xFFFF00); //66
score(0x7FFF7F); //66
但是,如果您告诉我们您需要该公式做什么,或者更准确地说明它应该做什么,那就太好了。
这个有点卡住了。
这是我的困境:
一种颜色有红、绿、蓝 (RGB) 三种元素。
所有颜色的值都在 0-255 之间。
例如:
var red:int = 53;
var green:int = 150;
var blue:int = 28;
我的评分系统是这样的,颜色越绿,分数越高,满分 10。
所以:
var red:int = 0;
var green:int = 255;
var blue:int = 0;
将获得最高分 (10) 并且:
var red:int = 255;
var green:int = 0;
var blue:int = 255;
将获得最低分数 (0)。
我需要生成某种方程式。 Bayes' Theorum 是我该去的地方吗?
真的一点头绪都没有。
如果只是检查颜色值以从 0 - 255
范围中提取分数 0 - 10
那么只需执行:
score = Math.round( (green / 255 ) * 10 );
根据这个逻辑,我们可以看到:
green = 253 gives score of 10
green = 190 gives score of 7
green = 128 gives score of 5
green = 47 gives score of 2
有一个阈值,如果数字高于 X 但小于 Y,它将给出相同的分数,例如任何 green
介于 243 和 255 之间的分数为 10。
PS:一些可测试的代码:
var score:int = 0;
var green:int = 128; //#change this for testing
score = Math.round( (green / 255 ) * 10 );
trace ("score is : " + score);
这有点棘手,因为有3个组成部分,但如果我理解正确的话,只有一个组成部分决定了你的排名。
你可以完全忽略红色和蓝色成分,只在0-255绿色等级上排名;结果将是绿色 = 64 的两种颜色,但交换了红色和蓝色的值,例如 rgb[100, 64, 50] 和 rgb[50, 64, 100] 将获得相同的分数,因为它们具有相同数量的绿色.这个结果意味着绿色分数是 3D RGB 坐标在 'green axis'.
上的投影我想出了一个正确的方法。
请查看以下代码:
var color = parseInt(colorString);
var fitness:Number = 0;
var red:int = (color>> 16) & 0xFF;
var green:int = (color>> 8) & 0xFF;
var blue:int = color & 0xFF;
var greenPercentage = (green/255)*100;
var redAndBluePercentage = ((red+blue)/510)*100;
fitness = greenPercentage-redAndBluePercentage;
fitness = (fitness+100)/2;
trace(fitness);
数学是这样的: 把你的颜色分成红色、绿色和蓝色。
计算颜色中绿色的百分比。 (x/255)
取颜色中红色和蓝色的百分比(x/510)
从绿色中减去红色和蓝色百分比。
向其中添加一些数学运算,为您提供 0-100 之间的可能分数。
colorFitness("0xFF00FF"); //Outputs 0
colorFitness("0x00FF00"); //Outputs 100
不幸的是,我不擅长 Action 脚本,因此可以提供真实的代码,但我想我有一些想法可能会对您有所帮助。 AFAIU 你的问题是你想测量给定 RGB 颜色的 "greenishess",同时考虑到所有 3 个分量,使得
- 绿色将获得 100% rait
- 红色或蓝色或洋红色将获得 0%
- 白色(所有 3 个均等混合)会在中间得到一些东西
如果我需要设计这样的方案,我会从 RGB 切换到一些不同的着色方案,例如 YUV or rather HSL/HSV. Actually the "H" component aka Hue 似乎是您所需要的。根据 wiki
Hue is one of the main properties (called color appearance parameters) of a color, defined technically (in the CIECAM02 model), as "the degree to which a stimulus can be described as similar to or different from stimuli that are described as red, green, blue, and yellow"
要计算色调,您首先需要确定最大和最小分量以及它们之间的差异:
M = max(R, G, B)
m = min(R, G, B)
C = M - m
然后
If Red is the Max, then Hue = (G - B)/C
If Green is the Max, then Hue = 2.0 + (B - R)/C
If Blue is the Max, then Hue = 4.0 + (R - G)/C
这会产生 [-1, 5] 范围内的值。您可以将其转换为更传统的度数,将其乘以 60 并将其环绕到 fir [0, 360] 但这并不重要,因为这只是一个线性比例。因此,使用前面定义的 Hue
计算,您可以通过 Hue
值接近 2(或接近 120 的度数)来测量颜色的 "greenishess"。
请注意,对于接近绿色的颜色(即绿色是最大分量的颜色),根据此公式 "greenishess" 计算为
"greenishess" = abs(B - R)/(G - min(B,R))
这对我来说很有意义。 B = R 的部分指定了颜色的饱和度,并且只有 "excess" 的 R 或 B 超过另一个会使颜色从 "pure" 绿色变为黄色或蓝色。
另请注意,您必须为从黑色到白色的所有 "gray" 颜色分配一些任意 "greenishess" 值,因为 C
将为 0,并且您不能除以减少 0.
最后,您不必直接使用 Hue
。您可以基于它构建更复杂的公式。例如,您可以放置一些截止点以将 0% 评级分配给纯红色和蓝色,即分配给 [0; 之外的所有内容。 4] 范围(或 [0; 240] 度)。默认情况下,Hue 只会将 0% 分配给洋红色,即 {Red = 255, Green = 0, Blue = 255}。像
"greenishness" = [2 - abs(min(4, max(0, Hue)) - 2)] / 2 * 100%
您也可以通过应用一些非线性变换来 "curve" 测量。
你的问题是select(r,g,b)
的正确函数return值从0到10。你说(0,255,0)
应该return 10.0,而其他值应 return 更少,而 (255,0,255)
应 return 0。因此,您至少需要 select 该函数的两个参数。一个是 (x,x,x)
处的值(如果你希望那个值相等,否则参数将是 X 的函数),另一个是非极值的插值规则。因此,您的函数应如下所示:
function score(r,g,b:int):Number {
var rc:int=Math.max(0,Math.min(255,r)); // clamp
var gc:int=Math.max(0,Math.min(255,g));
var bc:int=Math.max(0,Math.min(255,b));
const GRAY:Number=5.0; // value at (x,x,x)
if ((rc==rg) and (rc==rb)) return GRAY;
return ir(r,g,b); // interpolation rule
}
事实上,您可以指定所有 8 个角的值,并根据您能想象到的任何法则简单地对它们进行插值。例如,通过相对距离。像这样:
const SCORES:Array=[
0, // black, (0,0,0)
0, // red, (255,0,0)
10, // green, (0,255,0)
6.66666, // yellow, (255,255,0)
0, // blue, (0,0,255)
0, // magenta, (255,0,255)
6.66666, // cyan, (0,255,255)
5.0 // white, (255,255,255)
];
const POINTS:Array=[
{r:0;g:0;b:0},
{r:255;g:0;b:0},
{r:0;g:255;b:0},
{r:255;g:255;b:0},
{r:0;g:0;b:255},
{r:255;g:0;b:255},
{r:0;g:255;b:255},
{r:255;g:255;b:255}
]; // respective points
function score(r,g,b:int):Number {
var rc:int=Math.max(0,Math.min(255,r)); // clamp
var gc:int=Math.max(0,Math.min(255,g));
var bc:int=Math.max(0,Math.min(255,b));
var dists:Array=new Array();
var td:Number=0;
for (var i:int=POINTS.length-1;i>=0;i--)
var dist:Number=distance({r=rc;g=gc;b=bc},POINTS[i]); // TODO
if (dist<1e-6) return SCORES[i]; // we're at the corner
dists.unshift(1.0/dist);
td+=1.0/dist;
}
var result:Number=0;
for (i=POINTS.length-1;i>=0;i--)
result+=SCORES[i]*dists[i]/td;
return result;
}
你没有指定你想要这个等式的目的。我相信这已经说过你有 3 个参数的函数,但你只为两种情况下的单个参数给出预期的输出,并且有许多函数可以满足你的期望,但在这两个输出之间工作完全不同。
我不知道您是否注意到了这一点,但是例如您的 colorFitness
给出了 50
的 0x000000
分数 - 这是您期望的吗?
对于你问题的当前状态,我也可以提出这样的建议。
function score(c:uint) {
var g:uint = (c >>> 8) & 0xFF;
var s:uint = g + (c >>> 16 & g ^ g);
s = (s + (c & 0xFF & g ^ g)) / 0x2FD * 100;
trace("score for", c.toString(16), ":", s);
}
score(0x00FF00); //100
score(0x000000); //0
score(0xFF00FF); //0
score(0xFF7FFF); //16
score(0xFFFFFF); //33
score(0x00FFFF); //66
score(0xFFFF00); //66
score(0x7FFF7F); //66
但是,如果您告诉我们您需要该公式做什么,或者更准确地说明它应该做什么,那就太好了。