从RGB获得Hue的最快公式

时间:2014-04-15 16:59:41

标签: colors rgb

如果给出的红色,绿色和蓝色值范围为0-255,那么获得色调值的最快计算是什么?该公式将以30fps(每秒920万次)的速度用于640x480图像的每个像素,因此速度优化的每一点都有帮助。

我见过其他公式,但我不满意他们涉及多少步骤。我正在寻找一个实际的公式,而不是内置的库函数。

5 个答案:

答案 0 :(得分:26)

  1. 将RGB值转换为0-1范围,这可以通过将值除以255得到8位颜色深度(r,g,b - 给定值):

    { {2}}

  2. 查找R,G和B的最小值和最大值。

  3. 取决于RGB颜色通道的最大值。三个不同的公式是: If Red is max, then Hue = (G-B)/(max-min) If Green is max, then Hue = 2.0 + (B-R)/(max-min) If Blue is max, then Hue = 4.0 + (R-G)/(max-min)
  4. 您获得的Hue值需要乘以60才能将其转换为色环上的度数。如果Hue变为负值,则需要添加360,因为圆圈有360度。

    这是full article

答案 1 :(得分:17)

除了Umriyaev的回答:

如果只需要色调,则不需要将0-255范围的颜色除以255.

e.x的结果。 (green - blue) / (max - min)对于任何范围都是相同的(只要颜色在相同的范围内)。

以下是获取Hue的java示例:

public int getHue(int red, int green, int blue) {

    float min = Math.min(Math.min(red, green), blue);
    float max = Math.max(Math.max(red, green), blue);

    if (min == max) {
        return 0;
    }

    float hue = 0f;
    if (max == red) {
        hue = (green - blue) / (max - min);

    } else if (max == green) {
        hue = 2f + (blue - red) / (max - min);

    } else {
        hue = 4f + (red - green) / (max - min);
    }

    hue = hue * 60;
    if (hue < 0) hue = hue + 360;

    return Math.round(hue);
}

编辑:添加检查min和max是否相同,因为在这种情况下不需要其余的计算,并且避免除以0(参见注释)

编辑:修复java错误

答案 2 :(得分:2)

// convert rgb values to the range of 0-1
var h;
r /= 255, g /= 255, b /= 255;

// find min and max values out of r,g,b components
var max = Math.max(r, g, b), min = Math.min(r, g, b);

if(max == r){
    // if red is the predominent color
    h = (g-b)/(max-min);
}
else if(max == g){
    // if green is the predominent color
    h = 2 +(b-r)/(max-min);
}
else if(max == b){
    // if blue is the predominent color
    h = 4 + (r-g)/(max-min);
}

h = h*60; // find the sector of 60 degrees to which the color belongs
// https://www.pathofexile.com/forum/view-thread/1246208/page/45 - hsl color wheel

if(h > 0){
    // h is a positive angle in the color wheel
    return Math.floor(h);
}
else{
    // h is a negative angle.
    return Math.floor(360 -h);
}

答案 3 :(得分:0)

您必须指定所需的语言。 C#,Java和C是非常不同的语言,可以在不同的平台上运行

与当前常见分辨率相比,640x480并不是很大。您必须尝试所有可能的解决方案和基准。具有多个步骤的算法并不一定比较短的算法慢,因为指令周期不固定,并且还有许多其他因素会影响性能,例如缓存一致性。

对于上面提到的算法Umriyaev,你可以用1.0/255乘以乘以255的除法,这样可以提高性能并带来一点可接受的错误。

在C中你可以对其进行矢量化以进一步改进它。您也可以使用硬件加速。

在C#和Java中,你没有多少选择。您可以在C#中运行不安全的代码,或者如果您使用Mono,则可以使用已经支持SSE的矢量类型。在Java中,您可以通过JNI

运行本机代码

答案 4 :(得分:0)

网页Math behind colorspace conversions, RGB-HSL对此进行了介绍,但其中包含我认为是错误的内容。它说明了色相计算要除以max-min,但是如果将其除以该分数,则该值会增加并且很容易超过-1到5的整个预期范围。我发现,将max-min乘以预期即可工作。

代替此:

If Red is max, then Hue = (G-B)/(max-min)
If Green is max, then Hue = 2.0 + (B-R)/(max-min)
If Blue is max, then Hue = 4.0 + (R-G)/(max-min)

我建议这样做:

If Red is max, then Hue = (G-B)*(max-min)
If Green is max, then Hue = 2.0 + (B-R)*(max-min)
If Blue is max, then Hue = 4.0 + (R-G)*(max-min)