如何为像素颜色定义清晰的范围

15
我试图做的是测试像素是否为蓝色。
例如:蓝色在RGB中定义为rgb(0,0,255)。 典型的颜色深度为8位(256种颜色),16位(约65,000种颜色),24位(约16百万种颜色)和32位(超过4十亿种不同颜色)。 因此,显然有多种不同的蓝色。
如何定义蓝色范围并测试每个像素是否为蓝色? 针对不同的深度需要注意什么?
到目前为止我的代码是:
BufferedImage image = ImageIO.read(file);

// Getting pixel color by position x and y
for (int i = 0; i < image.getWidth(); i++) {
    for (int j = 0; j < image.getHeight(); j++) {
        int clr = image.getRGB(i, j);

注1:

http://www.workwithcolor.com/cyan-blue-color-hue-range-01.htm

这里的问题是,在颜色步骤之间有什么内容?

一个例子会很好。

注2:

我刚刚找到了一个关于我感兴趣的主题的演示文稿:

http://cstwiki.wtb.tue.nl/images/06-opencv.pdf

在第13页,我们可以看到红色的定义。但是其他颜色如何定义呢?


1
起初我以为可以为RGB颜色设置范围,但这样行不通。正如您在颜色表中所看到的:http://2.bp.blogspot.com/_DmvFk3aIxDI/S9Kbb5BOjEI/AAAAAAAAADk/MVrj60t6ec8/s1600/cc.png 蓝色从#000066开始,而#66FFFF仍然是蓝色。但是,在它们之间并非所有颜色都是蓝色。 - ju ho
我找到了这个链接:https://dev59.com/lYvda4cB1Zd3GeqPUxYs,应该会有所帮助。 - ju ho
不,它并不会!如果你选择HUE中的蓝色值,你仍然可以改变饱和度和亮度/明度的参数,这样你就看不到任何蓝色了。在这里试一试:http://colorizer.org/ - Jürgen K.
你如何定义哪些颜色是“蓝色”?#000001算蓝色吗?#7F7F80或#FEFEFF呢?你只想要蓝色分量大于其他分量的颜色,还是想要色调在一定范围内(什么范围?)且饱和度在HSV模型中超过某个阈值(什么阈值)的颜色? - Wyzard
我想获取晴朗蓝天的所有变化。天空中有许多不同的蓝色,但我对任何云都不感兴趣。现在回答你的问题,所提出的颜色对我来说并不是蓝色。因此,蓝色成分高于其他成分并不是足够的要求。如何设置范围、饱和度和阈值是我的问题! - Jürgen K.
3个回答

8

我认为最简单的方法是将颜色格式转换为HSV / HSB,然后选择Hue的蓝色范围。确切的范围可能会有问题,但我通常使用从165(下面是绿色)到240(上面是紫色/紫罗兰色)。饱和度和值/亮度仅控制阴影,但请注意,饱和度接近0时会呈现灰色,并带有一些蓝色调,而价值接近0时几乎是黑色的。因此,您还可以检查饱和度是否大于10,价值是否大于15,但当然您可以选择适合自己需求的值。

示例代码(未经测试):

boolean isBlue(int rgb){
    Color color = new Color(rgb);
    float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
    // now [0] is hue, [1] saturation and [2] value/brightness
    // all values are between 0 and 1 so you must divide hue by 360 and others by 100
    if(hsb[0] > 165/360 && hsb[0] < 240/360 && hsb[1] > 0.1 && hsb[2] > 0.15)
        return true;
    return false;
}

HSV的维基百科

RGBtoHSB javadoc

颜色选择器,可用于检查不同系统中的颜色


是的,这可能是一种普通的近似方法。但我正在寻找一种绕过“选择适合自己需求的值”的方法。 - Jürgen K.
1
好的,这里的难点在于你需要什么。如果你想要遵循暗色和“多云”的色调,只需将饱和度和值都设置为大于50(或代码中的0.5)。在之前的评论中,你提到你正在寻找“晴空”,它可能是从海军蓝到低饱和青色的任何地方,所以我建议尝试饱和度>25(低于此会太“多云”),并且值>50(低于此会更像夜空色调)。在我的回答中,我提供了从深色到浅色的相当通用的蓝色定义,从青绿色到靛蓝色。 - xnor
1
@JürgenK。如果您对蓝色有自己的定义,请将其添加到您的问题中。如果您要求别人为您定义颜色,那么您会得到他们自己的近似定义。在某些情况下,人们会将一件蓝色连衣裙看作是白色 - gre_gor
@gre_gor。嗯,我没有自己对蓝色的定义。即使我有一个,它也不会有用。这就是为什么我正在寻找一种通用解决方案。 - Jürgen K.

4
在RGB色彩空间中,这并不容易实现。首先,颜色的显示方式是设备相关的,也就是说,无论您选择什么RGB值来显示,可能在不同的屏幕上看起来完全不同。但即使可以控制这一点,英语中被指定特定名称的颜色在RGB颜色立方体内不一定占据相同的体积,无论是在大小还是形状上都是如此。因此,有一些颜色模型试图近似于人类对颜色的感知。
其中一个竞争者是CIELab色彩空间。 "Lab"指的是在此模型中表示颜色的方式:通过颜色的亮度L,颜色在红/洋红和绿轴上的位置(a),以及其在黄和蓝轴上的位置(b)。不幸的是,RGB或CMYK值与L*a*b*之间没有简单的转换公式,因为RGB和CMYK颜色模型是设备相关的。必须首先将RGB或CMYK值转换为特定的绝对颜色空间,例如sRGB或Adobe RGB。这种调整将依赖于设备,但从变换得到的数据将是设备无关的。

0

从技术上讲,以下应该是蓝色阴影的实现方式。

boolean isBlueShade(int r, int g, int b)
{
    return (r == g) && (r != b);
}

我们可以争论青色也是蓝色。但从技术上讲,它并不是蓝色。如果您的应用程序需要一些相关颜色为蓝色,则可以使用上述方法实现来包括该范围检查。
我只是编辑上述方法,以便清楚地传达我的想法,即使这不是预期的解决方案。

如何定义蓝色的范围检查。 - Jürgen K.
1
基于这个定义,白色和黑色甚至灰度也是蓝色。RGB不是直观的模型,不能轻易地用来区分颜色。 - xnor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接