Java colour detection

15,337

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.

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 perfectly blue 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

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:

HSV

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.

Share:
15,337
user2517280
Author by

user2517280

Updated on June 16, 2022

Comments

  • user2517280
    user2517280 almost 2 years

    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.

    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:

    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.

    Thanks in advance.

  • user2517280
    user2517280 about 10 years
    This is great, thank you. I was just looking into HSB as I wasn't sure how it was read in Java as it gives values between 0 and 1 where as its supposed to be between 0 and 360 but obviously you've explained that and more so thanks a lot.
  • Jay Dangar
    Jay Dangar about 6 years
    what's the degree for deciding orange value?
  • Marco13
    Marco13 about 6 years
    @JayDangar That solely depends on which color you want to consider as "orange". For example, would you consider this color as "orange" or as "yellow"? However, using something like (deg >= 30 && deg < 45) for orange() could be ok...
  • Jay Dangar
    Jay Dangar almost 6 years
    Well, your algorithm works really great, but in certain scenarios like outdoor coditions brightness is high, so there is high chances that we got wrong output, in most of the time the detected color would be white. Can you tell me any other methods by which I can solve this kind of more brightness issues??
  • Marco13
    Marco13 almost 6 years
    @JayDangar Similar to the question about "orange": You can adjust the limits as you wish. Right now, "white" is determined by hsb[2] > 0.9, and you can change this to hsb[2] > 0.95, but maybe I should emphasize: The answer here shows a very basic approach for a "pixel color classification". In a real-world application, one could consider more sophisticated approaches for computing the "color name" from the hue. You should also consider preprocessing the image, for example, in order to maximize the contrast (e.g. based on the histogram )
  • Jay Dangar
    Jay Dangar almost 6 years
    @Marco13, thanks man for the efforts... I will look through the histogram based approach, appreciated your help.