如何将 RGB 颜色转换为 HSV?

Posted

技术标签:

【中文标题】如何将 RGB 颜色转换为 HSV?【英文标题】:How to Convert RGB Color to HSV? 【发布时间】:2010-09-26 10:53:49 【问题描述】:

如何使用 C# 将 RGB 颜色转换为 HSV? 我在不使用任何外部库的情况下搜索了一种快速方法。

【问题讨论】:

不是完全重复。 HSL != HSV。 如何调整 HSL 帖子中的代码以用于 HSV 解决方案? ***:两者在数学上都是圆柱形的,但 HSV 在概念上可以被认为是一个倒锥形,HSL 在概念上代表一个双锥或球体。虽然 HSL 和 HSV 中的“色调”指的是相同的属性,但它们对“饱和度”的定义却大相径庭。 @Adam:我希望 Paint.NET 的人能弄清楚这一点! :) 重新迭代:HSV 与 HSL 非常不同。 HSV 有时也称为 HSB(尤其是在 Photoshop 和 .NET 中) 【参考方案1】:

我也有同样的需求。

下面我将分享迄今为止我能找到的最好、最简单的解决方案。 这是 Greg (found here) 的修改答案;但代码更简陋且易于理解。

对于那些正在学习的人,我添加了一些参考资料,为了理解起见,这些参考资料值得查看。


参考文献

    "Lukas Stratmann" HSV Model Tool (Incl. Other Model Systems: CMY / CMYK / HSL) "The HSV Color Model in Graphic Design" "Formula to Determine Perceived Brightness of RGB Color" Fastest Formula to Get Hue from RGB "Color Conversion Algorithms" "Program to Change RGB color model to HSV color model" "RGB to HSV Color Conversion Algorithm" "RGB to HSV Color Space Conversion (C)" "How to Convert RGB Color to HSV"

代码

    /// <summary> Convert RGB Color to HSV. </summary>
    /// <param name="color"></param>
    /// <returns> A double[] Containing HSV Color Values. </returns>
    public double[] rgbToHSV(Color color)
    
        double[] output = new double[3];

        double hue, saturation, value;

        int max = Math.Max(color.R, Math.Max(color.G, color.B));
        int min = Math.Min(color.R, Math.Min(color.G, color.B));

        hue = color.GetHue();
        saturation = (max == 0) ? 0 : 1d - (1d * min / max);
        value = max / 255d;

        output[0] = hue;
        output[1] = saturation;
        output[2] = value;

        return output;
    

【讨论】:

【参考方案2】:

您是否考虑过简单地使用 System.Drawing 命名空间?例如:

System.Drawing.Color color = System.Drawing.Color.FromArgb(red, green, blue);
float hue = color.GetHue();
float saturation = color.GetSaturation();
float lightness = color.GetBrightness();

请注意,这并不完全符合您的要求(请参阅 differences between HSL and HSV 并且 Color 类没有从 HSL/HSV 转换回来,但后者是合理的 easy to add。

【讨论】:

正如您所指出的,这实际上并不能回答问题,因为这些方法提供 RGB 到 HSL 的转换,而不是 RGB 到 HSV。 @greg:我同意,这将导致可怕的结果,正如我自己所经历的那样。 -1:因为这不是问题的答案。 HSV 与 HSL 非常不同。 注意:HSV 有时也称为 HSB(尤其是在 Photoshop 和 .NET 中) 我不确定亮度、亮度和价值之间有什么区别(一直认为它们是同义词),但是查看System.Drawing.Color 实现我发现它不是基于 NTSC 权重红色、绿色和蓝色,但对它们一视同仁,产生次优结果。 @IanBoyd 虽然你在说什么。 HSV、HSL 和 HSB 是正确的,问题在于 HSB 的 System.Drawing 实现实际上是用词不当:他们实现了 HSL。 .NET API 声明 Color.GetBrightness() returns lightness,而不是值(即,它不是 HSV 中的“V”,而是 HSL 中的“L”)。【参考方案3】:

首先:确保您有颜色作为位图,如下所示:

Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
paintcolor = bmp.GetPixel(e.X, e.Y);

(e 来自选择我的颜色的事件处理程序!)

不久前遇到这个问题时,我首先得到了 rgba(红色、绿色、蓝色和 alpha)值。 接下来我创建了 3 个浮动:浮动色调、浮动饱和度、浮动亮度。然后你只需这样做:

hue = yourcolor.Gethue;
saturation = yourcolor.GetSaturation;
brightness = yourcolor.GetBrightness;

全部看起来像这样:

Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
            paintcolor = bmp.GetPixel(e.X, e.Y);
            float hue;
            float saturation;
            float brightness;
            hue = paintcolor.GetHue();
            saturation = paintcolor.GetSaturation();
            brightness = paintcolor.GetBrightness();

如果您现在想在标签中显示它们,只需:

yourlabelname.Text = hue.ToString;
yourlabelname.Text = saturation.ToString;
yourlabelname.Text = brightness.ToString;

在这里,您现在将 RGB 值转换为 HSV 值:)

希望对你有帮助

【讨论】:

这不是 HSV 而是 HSL。 ***.com/questions/15668623/hsb-vs-hsl-vs-hsv【参考方案4】:

请注意,Color.GetSaturation()Color.GetBrightness() 返回 HSL 值,而不是 HSV。 下面的代码演示了不同之处。

Color original = Color.FromArgb(50, 120, 200);
// original = Name=ff3278c8, ARGB=(255, 50, 120, 200)

double hue;
double saturation;
double value;
ColorToHSV(original, out hue, out saturation, out value);
// hue        = 212.0
// saturation = 0.75
// value      = 0.78431372549019607

Color copy = ColorFromHSV(hue, saturation, value);
// copy = Name=ff3278c8, ARGB=(255, 50, 120, 200)

// Compare that to the HSL values that the .NET framework provides: 
original.GetHue();        // 212.0
original.GetSaturation(); // 0.6
original.GetBrightness(); // 0.490196079

以下 C# 代码是您想要的。它使用Wikipedia 中描述的算法在 RGB 和 HSV 之间进行转换。 hue 的范围是 0 - 360,saturationvalue 的范围是 0 - 1。

public static void ColorToHSV(Color color, out double hue, out double saturation, out double value)

    int max = Math.Max(color.R, Math.Max(color.G, color.B));
    int min = Math.Min(color.R, Math.Min(color.G, color.B));

    hue = color.GetHue();
    saturation = (max == 0) ? 0 : 1d - (1d * min / max);
    value = max / 255d;


public static Color ColorFromHSV(double hue, double saturation, double value)

    int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
    double f = hue / 60 - Math.Floor(hue / 60);

    value = value * 255;
    int v = Convert.ToInt32(value);
    int p = Convert.ToInt32(value * (1 - saturation));
    int q = Convert.ToInt32(value * (1 - f * saturation));
    int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));

    if (hi == 0)
        return Color.FromArgb(255, v, t, p);
    else if (hi == 1)
        return Color.FromArgb(255, q, v, p);
    else if (hi == 2)
        return Color.FromArgb(255, p, v, t);
    else if (hi == 3)
        return Color.FromArgb(255, p, q, v);
    else if (hi == 4)
        return Color.FromArgb(255, t, p, v);
    else
        return Color.FromArgb(255, v, p, q);

【讨论】:

我认为您在答案中转置了 Saturation 和 Value 的样本值。当我将 rgb(50,120,200) 转换为色相饱和度值 (HSV) 时,我得到 hsv(212, 75%, 78.4%)。查看 HSV 的***公式:V=Max(r,g,b)。在这种情况下,最大值(50,120,200)=200。 200/255 = 0.7843 我将只编辑答案,转置饱和度和值数字。饱和度应为 0.75,值应为 0.7843... 知道如何将饱和度从 0-1 转换为 MS Paint 使用的饱和度值(即 0-240 比例)吗? 很好的答案!也许考虑使用 float 而不是 double,以与 .NET color.GetHue() 返回的内容保持一致? 知道了。 HSV 变量使用double 类型,其粒度远高于 8 位 RGB 通道所能容纳的粒度。因此 100% 的往返映射是不可能的。但是,我很想知道是否可以改进这些功能以安全地执行 RGB 子集。【参考方案5】:

EasyRGB 有许多色彩空间转换。 Here is the code 用于 RGB->HSV 转换。

【讨论】:

【参考方案6】:

这是从 BlaM 帖子中的 C 代码移植过来的 VB.net 版本,对我来说很好用。

这里有一个 C 实现:

http://www.cs.rit.edu/~ncs/color/t_convert.html

转换为 C# 应该非常简单,因为几乎没有函数被调用 - 只是 > 计算。


Public Sub HSVtoRGB(ByRef r As Double, ByRef g As Double, ByRef b As Double, ByVal h As Double, ByVal s As Double, ByVal v As Double)
    Dim i As Integer
    Dim f, p, q, t As Double

    If (s = 0) Then
        ' achromatic (grey)
        r = v
        g = v
        b = v
        Exit Sub
    End If

    h /= 60 'sector 0 to 5
    i = Math.Floor(h)
    f = h - i 'factorial part of h
    p = v * (1 - s)
    q = v * (1 - s * f)
    t = v * (1 - s * (1 - f))

    Select Case (i)
        Case 0
            r = v
            g = t
            b = p
            Exit Select
        Case 1
            r = q
            g = v
            b = p
            Exit Select
        Case 2
            r = p
            g = v
            b = t
            Exit Select
        Case 3
            r = p
            g = q
            b = v
            Exit Select
        Case 4
            r = t
            g = p
            b = v
            Exit Select
        Case Else   'case 5:
            r = v
            g = p
            b = q
            Exit Select
    End Select
End Sub

【讨论】:

【参考方案7】:

这里有一个 C 实现:

http://www.cs.rit.edu/~ncs/color/t_convert.html

转换为 C# 应该非常简单,因为几乎不调用任何函数 - 只是计算。

通过Google找到

【讨论】:

这个实现不正确。它似乎是based on this example code,但它缺少一个部分(规范化部分)。让我绊倒了一段时间!

以上是关于如何将 RGB 颜色转换为 HSV?的主要内容,如果未能解决你的问题,请参考以下文章

python使用openCV加载图像并将BGR格式转换成HSV格式定义HSV格式中需要分离颜色的掩码(掩模)区间(mask)并使用mask信息进行颜色分离BGR格式的图像转化为RGB并可视化

python使用openCV加载图像并将BGR格式转换成HSV格式定义HSV格式中需要分离颜色的掩码(掩模)区间(mask)并使用mask信息进行颜色分离BGR格式的图像转化为RGB并可视化

HSV转换

这个RGB到HSV颜色转换方程我做错了什么?

图像RGB到HSV色彩空间转换及其逆变换

javascript中的RGB到HSV颜色? [关闭]