将HSV数据从255转换为359

时间:2019-05-22 16:29:23

标签: c# image-processing colors emgucv

我正在使用emgucv。

我希望进行hsl过滤。

颜色范围是0到359。

我正在过滤黄色,所以我正在寻找30到60之间的色调。

我加载一个现有的位图并将其作为hsv图像加载:

var img = new Image<Hsv, int>(@"D:\yellow.jpg");

当我运行它时,我得到:

System.NotSupportedException: 'There is an error converting Emgu.CV.Structure.Bgr to Emgu.CV.Structure.Hsv: Requested value 'Bgr2Bgr' was not found.'

我可以这样做:

var img = new Image<Hsv, byte>(@"D:\yellow.jpg");

这样可以很好地加载,但是字节值最多只能达到255。

我还能尝试什么?我是否必须将每个“像素”数据乘以值* 255/359?

2 个答案:

答案 0 :(得分:0)

将每个像素值乘以255/359会给我带来错误的提示,因为HSL中的三个通道(色调[范围从0度到360度的分量],饱和度,亮度)不对应于这三个通道以RGB(红色,绿色,蓝色)。我对C#并不十分熟悉,但是the following snippets对于您进行颜色转换可能会很有用。

为了您的利益而在此处转贴:

// Convert an HLS value into an RGB value.
public static void HlsToRgb(double h, double l, double s,
    out int r, out int g, out int b)
{
    double p2;
    if (l <= 0.5) p2 = l * (1 + s);
    else p2 = l + s - l * s;

    double p1 = 2 * l - p2;
    double double_r, double_g, double_b;
    if (s == 0)
    {
        double_r = l;
        double_g = l;
        double_b = l;
    }
    else
    {
        double_r = QqhToRgb(p1, p2, h + 120);
        double_g = QqhToRgb(p1, p2, h);
        double_b = QqhToRgb(p1, p2, h - 120);
    }

    // Convert RGB to the 0 to 255 range.
    r = (int)(double_r * 255.0);
    g = (int)(double_g * 255.0);
    b = (int)(double_b * 255.0);
}

// Convert an RGB value into an HLS value.
public static void RgbToHls(int r, int g, int b,
    out double h, out double l, out double s)
{
    // Convert RGB to a 0.0 to 1.0 range.
    double double_r = r / 255.0;
    double double_g = g / 255.0;
    double double_b = b / 255.0;

    // Get the maximum and minimum RGB components.
    double max = double_r;
    if (max < double_g) max = double_g;
    if (max < double_b) max = double_b;

    double min = double_r;
    if (min > double_g) min = double_g;
    if (min > double_b) min = double_b;

    double diff = max - min;
    l = (max + min) / 2;
    if (Math.Abs(diff) < 0.00001)
    {
        s = 0;
        h = 0;  // H is really undefined.
    }
    else
    {
        if (l <= 0.5) s = diff / (max + min);
        else s = diff / (2 - max - min);

        double r_dist = (max - double_r) / diff;
        double g_dist = (max - double_g) / diff;
        double b_dist = (max - double_b) / diff;

        if (double_r == max) h = b_dist - g_dist;
        else if (double_g == max) h = 2 + r_dist - b_dist;
        else h = 4 + g_dist - r_dist;

        h = h * 60;
        if (h < 0) h += 360;
    }
}

答案 1 :(得分:0)

最简单的方法是读取文件。那应该给你一个RGBA图像。将RGBA转换为BGR,然后从BGR转换为HLS。

我这样使用Mats:

Mat src = new Mat(@"D:\yellow.jpg");
Mat Bgr = new Mat();
Mat Hls = new Mat();
CvInvoke.CvtColor(src, Bgr, ColorConversion.Rgba2Bgr);
CvInvoke.CvtColor(Bgr, Hls, ColorConversion.Bgr2Hls);

我认为是的。您想要进行HSL过滤,这告诉我您需要HSL格式的图像。在OpenCV中,在所有情况下,HSV,HSL等只能达到255,因此它们非常适合8位图像的字节。如果您使用的是32位深度,则值将保持不变。不支持16位图像。对于HSV,色相的值是0-180(我将BGR与8位无符号值一起使用),我只是乘以或除以2,但这仅在需要向用户显示此值或获取色相值时才需要来自用户。最终,它对我内部如何使用Hue值没有影响。

HSL的处理方式完全相同,8位的Hue值为0-180,不支持16位,而32位则保持不变。

道格