欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图像色彩空间转换——RGB与HSL/HSV

程序员文章站 2022-07-07 11:37:04
...

色彩空间

RGB色彩空间

RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。

图像色彩空间转换——RGB与HSL/HSV

HSL/HSV色彩空间

HSL色彩模式是工业界的一种颜色标准,是通过对色相(H)、饱和度(S)、明度(L)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,HSL即是代表色相,饱和度,明度三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。

HSL的H(hue)分量,代表的是人眼所能感知的颜色范围,这些颜色分布在一个平面的色相环上,取值范围是0°到360°的圆心角,每个角度可以代表一种颜色。色相值的意义在于,我们可以在不改变光感的情况下,通过旋转色相环来改变颜色。在实际应用中,我们需要记住色相环上的六大主色,用作基本参照:360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红,它们在色相环上按照60°圆心角的间隔排列。

图像色彩空间转换——RGB与HSL/HSV

HSL的S(saturation)分量,指的是色彩的饱和度,它用0%至100%的值描述了相同色相、明度下色彩纯度的变化。数值越大,颜色中的灰色越少,颜色越鲜艳,呈现一种从理性(灰度)到感性(纯色)的变化。

图像色彩空间转换——RGB与HSL/HSV

HSL的L(lightness)分量,指的是色彩的明度,作用是控制色彩的明暗变化。它同样使用了0%至100%的取值范围。数值越小,色彩越暗,越接近于黑色;数值越大,色彩越亮,越接近于白色。

图像色彩空间转换——RGB与HSL/HSV


转换算法

RGB→HSL的算法

  • 步骤1:找出R,G和B中的最大值。
  • 步骤2:计算明度:L=(maxcolor + mincolor)/2
  • 步骤3:如果最大和最小的颜色值相同,即表示灰色,那么S定义为0,而H未定义并在程序中通常写成0。
  • 步骤4:否则,根据明度L计算饱和度S:
    If L<127.5, S=255×(maxcolor-mincolor)/(maxcolor + mincolor)
    If L>=127.5, S=255×(maxcolor-mincolor)/(510.0-maxcolor-mincolor)
  • 步骤5:计算色调H:
    If R=maxcolor, H=(G-B)/(maxcolor-mincolor)
    If G=maxcolor, H=120.0+(B-R)/(maxcolor-mincolor)
    If B=maxcolor, H=240.0+(R-G)/(maxcolor-mincolor)
    如果H为负值,则加360;如果H大于360,则减360。

说明:
1,由步骤4的式子可以看出明度仅与图像的最多颜色成分和最少的颜色成分的总量有关。明度越小,图像越趋于黑色。亮度越高图像越趋于明亮的白色。
2,由步骤5的式子可以看出饱和度与图像的最多颜色成分和最少的颜色成分的差量有关。饱和度越小,图像越趋于灰度图像。饱和度越大,图像越鲜艳,给人的感觉是彩色的,而不是黑白灰的图像。
3,色调决定了人对图像的不同的颜色感受。
4,从第5步的计算看,H分成0~6区域。RGB颜,色空间是一个立方体而HSL颜色空间是两个六角形锥体,其中的L是RGB立方体的主对角线。因此,RGB立方体的顶点:红、黄、绿、青、蓝和品红就成为HSL六角形的顶点,而数值0~6就告诉我们H在哪个部分。
  

HSL→RGB的算法

  • 步骤1:If S=0,表示灰色,定义R,G和B都为L.
  • 步骤2:否则,测试L:
    If L<127.5,temp2=L×(255.0+S)/255
    If L>=127.5,temp2=L+S-L×S/255
  • 步骤3:temp1=2.0×L-temp2
  • 步骤4:对于R,G,B,计算另外的临时值temp3。方法如下:
    for R, temp3=H+120.0
    for G, temp3=H
    for B, temp3=H-120.0
  • 步骤5:根据temp3的范围计算相应的R,G,B值。

算法实现

RGB→HSL

    public double[] rgb2Hsl(int[] rgb)
    {
        double min, max, dif, sum;
        double f1, f2;
        double h, s, l;
        min = rgb[0];
        if (rgb[1] < min)
            min = rgb[1];
        if (rgb[2] < min)
            min = rgb[2];
        max = rgb[0];
        f1 = 0.0;
        f2 = rgb[1] - rgb[2];
        if (rgb[1] > max) {
            max = rgb[1];
            f1 = 120.0;
            f2 = rgb[2] - rgb[0];
        }
        if (rgb[2] > max) {
            max = rgb[2];
            f1 = 240.0;
            f2 = rgb[0] - rgb[1];
        }
        dif = max - min;
        sum = max + min;
        l = 0.5 * sum;
        if (dif == 0) {
            h = 0.0;
            s = 0.0;
        }
        else if(l < 127.5) {
            s = 255.0 * dif / sum;
        }
        else {
            s = 255.0 * dif / (510.0 - sum);
        }

        h = (f1 + 60.0 * f2 / dif);
        if (h < 0.0) {
            h += 360.0;
        }
        if (h >= 360.0) {
            h -= 360.0;
        }

        return new double[]{h, s, l};
    }

HSL→RGB

    public int[] hsl2RGB(double[] hsl)
    {
        double c1o60  = 1.0 / 60.0;
        double c1o255 = 1.0 / 255.0;
        int tr = 0, tg = 0, tb = 0;
        double v1, v2, v3, h1;
        double s = hsl[1], l = hsl[2];
        double h = hsl[0];
        if (s == 0) {
            tr = (int)l;
            tg = (int)l;
            tb = (int)l;
        } else {

            if (l < 127.5) {
                v2 = c1o255 * l * (255 + s);
            } else {
                v2 = l + s - c1o255 * s * l;
            }

            v1 = 2 * l - v2;
            v3 = v2 - v1;
            h1 = h + 120.0;
            if (h1 >= 360.0)
                h1 -= 360.0;

            if (h1 < 60.0) {
                tr = (int)(v1 + v3 * h1 * c1o60);
            }
            else if (h1 < 180.0) {
                tr = (int)v2;
            }
            else if (h1 < 240.0) {
                tr = (int)(v1 + v3 * (4 - h1 * c1o60));
            }
            else {
                tr = (int)v1;
            }

            h1 = h;
            if (h1 < 60.0) {
                tg = (int)(v1 + v3 * h1 * c1o60);
            }
            else if (h1 < 180.0) {
                tg = (int)v2;
            }
            else if (h1 < 240.0) {
                tg = (int)(v1 + v3 * (4 - h1 * c1o60));
            }
            else {
                tg = (int)v1;
            }

            h1 = h - 120.0;
            if (h1 < 0.0) {
                h1 += 360.0;
            }
            if (h1 < 60.0) {
                tb = (int)(v1 + v3 * h1 * c1o60);
            }
            else if (h1 < 180.0) {
                tb = (int)v2;
            }
            else if (h1 < 240.0) {
                tb = (int)(v1 + v3 * (4 - h1 * c1o60));
            }
            else {
                tb = (int)v1;
            }
        }
        return new int[]{tr, tg, tb};
    }

想了解更多关于数字图像处理:数字图像处理专栏