最快的公式来从RGB获得色相

问题描述 投票:20回答:4

如果你是因为从0到255不等的红色,绿色和蓝色的值,这将是最快的计算得到公正的色调值?这个公式将在640×480图像的每个像素30fps的(920万次),这样的速度优化的每一点帮助可以使用。

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

colors rgb
4个回答
29
投票
  1. 转换的RGB值到0-1范围内,这可以通过除以255的数值为8位颜色深度来完成(R,G,B - 给出的值): R = R / 255 = 0.09 G =克/ 255 = 0.38 B = B / 255 = 0.46
  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)

你需要的色调值60相乘将其转换成度上的颜色圈。如果色相为负则需要加360,因为圆具有360度。

这里是full article


18
投票

除了Umriyaev的回答:

如果只需要色调,它不要求用255来划分0-255范围的颜色。

e.x.结果(green - blue) / (max - min)将是任何范围相同(只要颜色是在相同范围内当然)。

这里是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);
}

编辑:加入检查,如果最小和最大是相同的,因为在这种情况下,不需要计算的其余部分,并通过0以避免分裂(见注释)

编辑:固定Java错误


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);
}

0
投票

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

640×480是不是很大相比目前常见的解决方案。你必须尝试所有可能的解决方案和标杆。因为指令周期不是固定的,并有会影响性能的许多其它因素,例如高速缓存一致性,有许多步骤的算法不一定比较短的一个更慢。

对于Umriyaev上述算法,可以通过255与1.0/255乘法代替除法,那将改善与位可接受的误差性能。

在C语言中,你可以做矢量化使其更加完善它。您也可以使用硬件加速。

在C#和Java,你没有太多的选择。您可以在C#中运行不安全的代码,如果你使用单声道,您可以使用一个已经为SSE支持向量类型。在Java中,你可以运行通过JNI本地代码

© www.soinside.com 2019 - 2024. All rights reserved.