如何按颜色范围选择?

时间:2013-10-17 13:21:24

标签: c# colors

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

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;
            } 
        }

这会是最好的方法吗?不知怎的,看起来它的黄色颜色效果不太好。

3 个答案:

答案 0 :(得分:2)

RGB是 3D 空间。

所有方向上远离阈值的颜色与原始颜色不太相似(根据数字的相似之处可能与人类的眼睛不太相似)。

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

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以查看 - 更快更快的替代方案。)

答案 1 :(得分:0)

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

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

如果你想坚持使用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. 
}

答案 2 :(得分:0)

查看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