根据绿色对蓝色和红色的数量计算值

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 给出了 500x000000 分数 - 这是您期望的吗?

对于你问题的当前状态,我也可以提出这样的建议。

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

但是,如果您告诉我们您需要该公式做什么,或者更准确地说明它应该做什么,那就太好了。