Java颜色检测
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22178978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java colour detection
提问by user2517280
Im looking to implement a feature in Java which reads an image and is able to detect where there are shades of red, blue, green, yellow, etc. as part of a satellite image analysis program. So for example in a standard satellite image, blue would be water so I would like the program to read how many pixels are blue and then it could say x% of the image is water.
我希望在 Java 中实现一项功能,该功能读取图像并能够检测红色、蓝色、绿色、黄色等阴影的位置,作为卫星图像分析程序的一部分。因此,例如在标准卫星图像中,蓝色将是水,所以我希望程序读取有多少像素是蓝色的,然后它可以说图像的 x% 是水。
I know it would be possible using a whole load of logic statements by reading the RGB value of each pixel but is there an easier way to do this? Otherwise there will be hundreds of if statements which is going to take a long time to write but also a long time to perform. Ideally id like something like this:
我知道可以通过读取每个像素的 RGB 值来使用一整套逻辑语句,但是有没有更简单的方法来做到这一点?否则将有数百个 if 语句,它们将需要很长时间来编写,但也需要很长时间来执行。理想情况下,id 像这样:
if (pixelValue = red) {
redCounter++;
}
Which is obviously very simple but it would save having to go through every single possible RGB combination for red, blue, green, yellow, purple, etc. which are all colours present in some of the coloured images.
这显然非常简单,但它可以省去必须通过红色、蓝色、绿色、黄色、紫色等所有可能的 RGB 组合,这些都是一些彩色图像中存在的颜色。
Thanks in advance.
提前致谢。
采纳答案by Marco13
You have to read every pixel anyhow. You can do this with
无论如何,您必须读取每个像素。你可以这样做
int rgb = bufferedImage.getRGB(x,y);
Alternatively, you can obtain the data buffer from the image and directly obtain the pixels as an int[]
array (as described in the comments), but note that this may have some impact on the performance when rendering this image afterwards.
或者,您可以从图像中获取数据缓冲区并直接以int[]
数组形式获取像素(如注释中所述),但请注意,这可能会对之后渲染此图像时的性能产生一些影响。
The next step would be to detect whether the pixel has a certain color. When it comes to photos, a comparison like
下一步是检测像素是否具有某种颜色。说到照片,比较像
if (rgb == Color.BLUE.getRGB()) { ... }
does not make sense: The pixels will not be perfectlyblue in most cases. Instead, you could analyze the hue of the RGB value, by converting it into the HSB color space. So you could do something like
没有意义:在大多数情况下,像素不会是完美的蓝色。相反,您可以通过将 RGB 值转换为 HSB 颜色空间来分析 RGB 值的色调。所以你可以做类似的事情
float hsb[] = new float[3];
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = (rgb ) & 0xFF;
Color.RGBtoHSB(r, g, b, hsb);
Then the hsb
array will contain the hue, saturation and brightness of the color. These will be values between 0 and 1. The hue multiplied with 360 will give you the "tone" of the color:
然后该hsb
数组将包含颜色的色调、饱和度和亮度。这些将是 0 到 1 之间的值。 色相乘以 360 将为您提供颜色的“色调”:
The saturation and brightness can be used to detect pixels that are "nearly black" or "nearly white". So your final analysis could roughly (!) look like this:
饱和度和亮度可用于检测“接近黑色”或“接近白色”的像素。所以你的最终分析大概是这样的(!):
if (hsb[1] < 0.1 && hsb[2] > 0.9) nearlyWhite();
else if (hsb[2] < 0.1) nearlyBlack();
else {
float deg = hsb[0]*360;
if (deg >= 0 && deg < 30) red();
else if (deg >= 30 && deg < 90) yellow();
else if (deg >= 90 && deg < 150) green();
else if (deg >= 150 && deg < 210) cyan();
else if (deg >= 210 && deg < 270) blue();
else if (deg >= 270 && deg < 330) magenta();
else red();
}
These nested if-statements could also be avoided by using a NavigableMap
and its floorEntry
and ceilingEntry
methods, but the if-statements are probably easier to understand here.
这些嵌套if语句也可以通过使用来避免NavigableMap
其floorEntry
和ceilingEntry
方法,但如果语句可能是更容易明白这里。