Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting "redish/blueish/greenish..." colors in an image

Tags:

java

count

colors

I'm working on something that is able to count the number of blue/red/yellow/... pixels in an image. So far I've got this code as a test:

public class Main {

    /*
   Black: 0,0,0
   White: 255, 255, 255
   Red: 255, 0, 0
   Orange: 255, 127, 0
   Yellow: 255, 255, 0
   Green: 0, 255, 0
   Blue: 0, 0, 255
   Indigo: 111, 0, 255
   Violet: 143, 0, 255
    */

    static int blackCount = 0;
    static int whiteCount = 0;
    static int redCount = 0;
    static int orangeCount = 0;
    static int yellowCount = 0;
    static int greenCount = 0;
    static int blueCount = 0;
    static int indigoCount = 0;
    static int violetCount = 0;
    static int otherCount = 0;

    static int totalCount = 0;

    public static void main(String[] args) {
        try {

            String path = "src/colors.jpg";
            BufferedImage image = ImageIO.read(new File(path));
            int w = image.getWidth();
            int h = image.getHeight();
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    Color c = new Color(image.getRGB(x, y));
                    int red = c.getRed();
                    int green = c.getGreen();
                    int blue = c.getBlue();
                    countColor(red, green, blue);
                    totalCount++;
                }
            }

            printColors();

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    private static void countColor(int red, int green, int blue) {
        if (red == 0 && green == 0 && blue == 0) blackCount++;
        else if (red == 255 && green == 255 && blue == 255) whiteCount++;
        else if (red == 255 && green == 0 && blue == 0) redCount++;
        else if (red == 255 && green == 127 && blue == 0) orangeCount++;
        else if (red == 255 && green == 255 && blue == 0) yellowCount++;
        else if (red == 0 && green == 255 && blue == 0) greenCount++;
        else if (red == 0 && green == 0 && blue == 255) blueCount++;
        else if (red == 111 && green == 0 && blue == 255) indigoCount++;
        else if (red == 143 && green == 0 && blue == 255) violetCount++;
        else otherCount++;
    }

    private static void printColors() {
        System.out.println("Black: " + blackCount);
        System.out.println("White: " + whiteCount);
        System.out.println("Red: " + redCount);
        System.out.println("Orange: " + orangeCount);
        System.out.println("Yellow: " + yellowCount);
        System.out.println("Green: " + greenCount);
        System.out.println("Blue: " + blueCount);
        System.out.println("Indigo: " + indigoCount);
        System.out.println("Violet: " + violetCount);
        System.out.println("Other: " + otherCount);
        System.out.println("Total: " + totalCount);
    }

But you might notice the problem... In RGB, the color "Red" is defined as (255, 0, 0). Therefore, an image containing a lot of red may return "0" because the color used in the image is (254, 0, 0) and not (255, 0, 0).

So I actually want to count not only the pure red pixels, but all "redish" pixels. I assume there is an easier way to pull this off than writing an insane long if (red = 255), if (red = 254),... structure?

like image 295
Matthias Avatar asked Dec 16 '22 10:12

Matthias


2 Answers

You can convert pixels being processed into more convenient color model, namely HSL or HSV.

Then it could be simplier to define ranges of component values that belong to particular groups (reddish/blueish/etc).

like image 115
axtavt Avatar answered Dec 18 '22 22:12

axtavt


I would consider trying to determine which of the three constants is the greater in your color. If the amount of red is greater than the amount of blue and the amount of green, you might suppose that your color is "redish". The same goes with blue and green.

However, you might want to take into account some corner cases:

  • What do you do when the color is "grayish", ie, all three constants are the same
  • What should happen if you consider the color (155, 154, 154)? The red constant is the biggest, but the color is still gray. Maybe you should say the color is a certain color-ish if and only if the associated constant is bigger than all others plus a certain value?

xkcd conveyed a very interesting survey on the subject of colors. I recommend you check it out for more details about how colors works, and it might give you some hits as to which values make a color "redish", "greenish" and "blueish". The results are very interesting, but shows a lot of interesting cases where color detection is non trivial. Colors can be perceived differently by different people, influenced by sex, color-blindness and LOT of others factors.

Also, the survey includes lots of color names for lots of RGB constants that you could use. And it also comes with a map of color names!

I truly believe that colors are a very interesting topic, however it is really complicated and you should get as much information on the subject before actually deciding how to write your code.

like image 43
Vivien Barousse Avatar answered Dec 18 '22 22:12

Vivien Barousse