【问题标题】:How to select by color range?如何按颜色范围选择?
【发布时间】:2013-10-26 00:19:24
【问题描述】:

在我的应用程序中,我加载了一张图片,我希望能够检测到相似的颜色。因此,如果我选择一种颜色,我希望应用程序能够找到具有相同(或几乎相同)颜色的所有像素。这是我为检测系统编写的内容,该检测系统在鼠标单击点和位图末端之间的垂直方向上进行查看。

for (int y = mouseY; y < m_bitmap.Height; y++)
        {
            Color pixel = m_bitmap.GetPixel(mouseX, y);
            //check if there is another color
            if ((pixel.R > curcolor.R + treshold || pixel.R < curcolor.R - treshold) ||
                (pixel.G > curcolor.G + treshold || pixel.G < curcolor.G - treshold) ||
                (pixel.B > curcolor.B + treshold || pixel.B < curcolor.B - treshold))
            { //YESSSSS!
                if ((y - ytop > minheight)&&(curcolor != Color.White)) //no white, at least 15px height
                {
                    colorlayers.Add(new ColorLayer(curcolor, y - 1, ytop));
                }
                curcolor = pixel;
                ytop = y;
            } 
        }

这是最好的方法吗?不知何故,它看起来不太适合黄色。

【问题讨论】:

  • 请解释I want to be able to detect similair colors?你想要的输出是什么样的?您只是要求帮助您更正您的if statement logic 吗?您是否希望从鼠标单击位置向下看?你的意思是水平你的颜色不会改变?您可能已经回答了所有这些问题......但至少我无法在您的问题中清楚地看到这些事情。

标签: c# colors


【解决方案1】:

RGB 是一个 3D 空间。

远在阈值各个方向上的颜色与原来的颜色不太相似(根据数字相似的可能与人眼不太相似)。

我会使用 HSL(例如)进行检查,其中色调值作为有限的一维范围,例如:

for (int y = mouseY; y < m_bitmap.Height; y++)
{
    Color pixel = m_bitmap.GetPixel(mouseX, y);
    if (Math.Abs(color.GetHue() - curcolor.GetHue()) <= threshold)
    {
        // ...
    }
}

此外,请注意以这种方式使用位图(GetPixel() 非常慢,请查看this post 以了解更快的替代方案)。

【讨论】:

    【解决方案2】:

    黄色出现问题的原因可能是 RGB 不是感知上一致的色彩空间。这意味着,给定颜色空间中两个点/颜色之间的距离,该颜色距离/差异的感知通常不会相同。

    也就是说,您可能想要使用其他颜色空间,例如 Adriano 建议的 HSL,或者可能是 Lab。

    如果你想坚持RGB,我建议计算欧几里得距离,像这样(我认为它更简单):

    float distance = Math.sqrt((pixel.R-curcolor.R)^2 + (pixel.G-curcolor.G)^2 + (pixel.B-curcolor.B)^2);
    
    if(distance < threshold)
    {
        // Do what you have to. 
    }
    

    【讨论】:

      【解决方案3】:

      看看 Paint.NET 中的 magic wand tool 是如何工作的可能会很有趣。

      这是他们比较两种颜色的方式:

      private static bool CheckColor(ColorBgra a, ColorBgra b, int tolerance)
      {
        int sum = 0;
        int diff;
        diff = a.R - b.R;
        sum += (1 + diff * diff) * a.A / 256;
        diff = a.G - b.G;
        sum += (1 + diff * diff) * a.A / 256;
        diff = a.B - b.B;
        sum += (1 + diff * diff) * a.A / 256;
        diff = a.A - b.A;
        sum += diff * diff;
        return (sum <= tolerance * tolerance * 4);
      }
      

      Source

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-18
        • 1970-01-01
        • 1970-01-01
        • 2015-06-10
        • 1970-01-01
        • 2019-10-27
        • 1970-01-01
        相关资源
        最近更新 更多