使用Emgu C#获取RGB的色相(HSV / HSB)值会产生错误的结果

时间:2018-09-21 22:23:51

标签: c# image-processing colors rgb emgucv

我正在使用EMGU.CV 3.4.1.2976(最新)库来分析图像,但没有得到预期的结果。我以ImageJ为基准,但是任何图像包都可以。

要测试功能,我正在分析一个简单的蓝色640x320 jpeg,如下所示。该图像的RGB值为0,0,255。

test image to get hue value from

ImageJ的色相直方图(值为170,计数为2048000)

Hue histogram of blue jpeg

使用下面的代码,我在120而不是170处出现尖峰-计数2048000是正确的。 我在做什么错了?

    public void AnalyzeEmgu(object image)
    {
        int[] arr = new int[256];

        using (Bitmap bmp = (Bitmap)image)
        {
            using (Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(bmp))
            {
                Image<Gray, byte>[] channels = hsvImage.Split();
                Image<Gray, byte> imgHue = channels[0];

                for (int x = 0; x < imgHue.Rows; x++)
                {
                    for (int y = 0; y < imgHue.Cols; y++)
                    {
                        var b = imgHue.Data[x, y, 0];
                        arr[b]++; // fill array with Hue data. Add 1 (++) to count amount.
                    }
                }
            }
        }

        GC.Collect();
        OnImageFinished(arr); // return array 
    }

  // call function.
  Bitmap bmp =new Bitmap(@"c:\test\blue.jpg");
  AnalyzeEmgu(bmp);

更新

轮到我需要转换为其他色彩空间,但仍然不是100%正确。 arr现在返回171而不是170。当然这只是一个微小的差异,但是对于更复杂的图像,这是值得注意的。

可能是什么问题?

    public void AnalyzeEmgu(object image)
    {
        int[] arr = new int[256];

        using (Mat orig = new Mat((string)image, ImreadModes.Color))
        {
            using (Mat hsv = new Mat())
            {
                // convert color to HSV here.
                CvInvoke.CvtColor(orig, hsv, ColorConversion.Bgr2HsvFull);
                Mat[] channels = hsv.Split();

                using (Image<Bgr, byte> img = channels[0].ToImage<Bgr, byte>())
                {
                    for (int x = 0; x < img.Rows; x++)
                    {
                        for (int y = 0; y < img.Cols; y++)
                        {
                            var b = img.Data[x, y, 0];
                            arr[b]++;
                        }
                    }
                }
                channels[1].Dispose();
                channels[2].Dispose();
            }
        }
        GC.Collect();
    }

    OnImageFinished(arr);

1 个答案:

答案 0 :(得分:1)

我不使用ImageJ或EMGU.CV,但我会分享一些要考虑的内容...

(1)

  

正确的色相值为240(不是170)度。

在色轮中,蓝色(0,0,255)的色相为 240 度。请注意,它也可以称为 -120
此逻辑可以解释为什么您要在AnalyzeEmgu函数中针对特定的色调“达到120的峰值”

通过添加360可以从负模式恢复。例如: myHue = (-120) + 360;,其结果为:240

(上)图片来源:http://www.graphic-design.com/Photoshop/color_cast/visible_color_spectrum.html

(2)

  

为什么ImageJ的色相直方图给出 170

如果您查看图像直方图,其最大值为 255 ,但滚轮/圆应为 360 。他们这样做为什么没有逻辑,但是可以解决:

IF: 360 / 255 = 1.4117647058823529411764705882353
THEN: 170 * 1.4117647058823529411764705882353 = 240 degrees.

(3)

  

“使用下面的代码,我的峰值是120而不是170”

尝试

myHue = 360 - 120; //gives 240

在下面用Photoshop制作的图像中,我显示了(从顶部开始)如果我们变蓝,它将正确列出为 240 度,并且在旅行时发现其距离为88像素向下。

相反的是从底部向上移动,我们看到相同的88像素距离现在给出 120 (绿色)。

您的代码色轮被翻转(上下颠倒)。将 A B 进行比较。
Photoshop使用系统 A ,但是您的值表明您的代码看起来像系统 B