Reputation: 13434
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?
Upvotes: 4
Views: 1118
Reputation: 9483
I saw a very related question some time ago, about getting color name from RGB value. The solution was easier when the color could be transformed from RGB to HSV, for example, since the hue
is the color. After doing that, you can define some ranges to the hue, and use them as color.
So, for example, a hue between 0 and 30 degrees (or any other measure) would be red, from 30 to 60 would be orange, then yellow....
Take a look at How do you get the hue of a #xxxxxx colour? or Map rainbow colors to RGB , for example
And to get color names from the hue, wikipedia can help...
Upvotes: 1
Reputation: 40871
You need to define reddish, bluish, and greenish. Obviously [254,0,0] should pass for red. What about [254,5,5]? What about [200, 10, 10]?
Your best bet is to check distance from the checked color (for exampl, with pure red: (255-r)^2 + (0-b)^2 (0-g)^2
) and compare it against a threshold value that you consider to be "effectively red".
And then do the same for the other colors.
This way will also let you very easily expand to additional colors (as you can just check the distance from your color vs the other color).
Edit: After finding this question: Is there an easy way to compare how close two colors are to each other, I would recommend converting to HSL (hue, saturation, lightness) and comparing he values in order based on some threshold. Check out that question, there's a lot of good information.
Upvotes: 3
Reputation: 20895
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:
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.
Upvotes: 4
Reputation: 242786
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).
Upvotes: 4
Reputation: 2924
Rather than check for a specific value for red, green or blue, check for a range
(you'll have to adjust this for syntax and calcuations - I'm not a Java coder)
private static void countColor(int red, int green, int blue) { if (red == 0 && green == 0 && blue == 0) blackCount++; else if (red !=0 && green == red && blue == red) whiteCount++; else if (red !=0 && green == 0 && blue == 0) redCount++; else if (red !=0 && green == (red/2) && blue == 0) orangeCount++; else if (red !=0 && green == red && blue == 0) yellowCount++; else if (red == 0 && green == !=0 && blue == 0) greenCount++; else if (red == 0 && green == 0 && blue == !=0) blueCount++; else if (red == (blue/3) && green == 0 && blue !=0) indigoCount++; else if (red == (blue/0.66) && green == 0 && blue == !=) violetCount++; else otherCount++; }
If this works, it will check for colours which match shades of red, green, blue, white, black etc.
Upvotes: 0