I only care about 12 colors:
red: RGB: 255, 0, 0
pink: RGB: 255, 192, 203
violet: RGB: 36, 10, 64
blue: RGB: 0, 0, 255
green: RGB: 0, 255, 0
yellow: RGB: 255, 255, 0
orange: RGB: 255, 104, 31
white: RGB: 255, 255, 255
black: RGB: 0, 0, 0
gray: RGB: 128, 128, 128
tea: RGB: 193, 186, 176
cream: RGB: 255, 253, 208
When i read the pixel of bitmap, i can get the Hue value:
int picw = mBitmap.getWidth();
int pich = mBitmap.getHeight();
int[] pix = new int[picw * pich];
float[] HSV = new float[3];
// get pixel array from source
mBitmap.getPixels(pix, 0, picw, 0, 0, picw, pich);
int index = 0;
// iteration through pixels
for(int y = 0; y < pich; ++y) {
for(int x = 0; x < picw; ++x) {
// get current index in 2D-matrix
index = y * picw + x;
// convert to HSV
Color.colorToHSV(pix[index], HSV);
// increase Saturation level
//HSV[0] = Hue
Log.i(getCallingPackage(), String.valueOf(HSV[0]));
}
}
Now i want to know what color of this pixel (only in 12 above colors)?
I use HSV to see the range of color. When i have a color which doesn't in this list, i want to name it as similarly color in my list How can i do it?
Thanks you so much
Based on your comments it seems you're basically trying to reduce the bitmap's full colour palette to only the 12 you specified. Obviously for every pixel in the bitmap the 'best match' from those 12 should be picked.
I still don't see why you would need the HSV values, as it's just a different representation of the RGB components - it doesn't actually change the problem, or its solution.
A straightforward approach to find the best match for any RGB colour would look something like as follows.
First build some sort of a list containing the colours you want to match against. I've used a Map, since you mentioned you (also) wanted to know the name of the colour, not just the RGB value.
Map<String, Integer> mColors = new HashMap<String, Integer>();
mColors.put("red", Color.rgb(255, 0, 0));
mColors.put("pink", Color.rgb(255, 192, 203));
mColors.put("voilet", Color.rgb(36, 10, 64));
mColors.put("blue", Color.rgb(0, 0, 255));
mColors.put("green", Color.rgb(0, 255, 0));
mColors.put("yellow", Color.rgb(255, 255, 0));
mColors.put("orange", Color.rgb(255, 104, 31));
mColors.put("white", Color.rgb(255, 255, 255));
mColors.put("black", Color.rgb(0, 0, 0));
mColors.put("gray", Color.rgb(128, 128, 128));
mColors.put("tea", Color.rgb(193, 186, 176));
mColors.put("cream", Color.rgb(255, 253, 208));
Then just make a method that will tell you the best match. You can call this from within your second for loop and pass it the current pixel colour. I've added some inline comments to explain the different steps, but it's really quite trivial.
private String getBestMatchingColorName(int pixelColor) {
// largest difference is 255 for every colour component
int currentDifference = 3 * 255;
// name of the best matching colour
String closestColorName = null;
// get int values for all three colour components of the pixel
int pixelColorR = Color.red(pixelColor);
int pixelColorG = Color.green(pixelColor);
int pixelColorB = Color.blue(pixelColor);
Iterator<String> colorNameIterator = mColors.keySet().iterator();
// continue iterating if the map contains a next colour and the difference is greater than zero.
// a difference of zero means we've found an exact match, so there's no point in iterating further.
while (colorNameIterator.hasNext() && currentDifference > 0) {
// this colour's name
String currentColorName = colorNameIterator.next();
// this colour's int value
int color = mColors.get(currentColorName);
// get int values for all three colour components of this colour
int colorR = Color.red(color);
int colorG = Color.green(color);
int colorB = Color.blue(color);
// calculate sum of absolute differences that indicates how good this match is
int difference = Math.abs(pixelColorR - colorR) + Math.abs(pixelColorG - colorG) + Math.abs(pixelColorB - colorB);
// a smaller difference means a better match, so keep track of it
if (currentDifference > difference) {
currentDifference = difference;
closestColorName = currentColorName;
}
}
return closestColorName;
}
The results for a quick test using some of the predefined Color constants:
Color.RED (-65536) -> red (-65536)
Color.GREEN (-16711936) -> green (-16711936)
Color.BLUE (-16776961) -> blue (-16776961)
Color.BLACK (-16777216) -> black (-16777216)
Color.WHITE (-1) -> white (-1)
Color.GRAY (-7829368) -> gray (-8355712)
Color.YELLOW (-256) -> yellow (-256)
Color.MAGENTA (-65281) -> pink (-16181)
The first number inbetween the brackets is the actual int value for the Color constant, the second is the int value for the best match found, with the name right in front of it.
The result for Color.MAGENTA
also illustrates why you should not just compare the colour's int value directly. The actual int value is -65281
, which is quite close to the value for Color.RED
(-65536). However, the best match based on the different components is 'pink', which has a -16181 value. Obviously this makes complete sense knowing that a colour is defined as 4 bytes:
Colors are represented as packed ints, made up of 4 bytes: alpha, red, green, blue. (...) The components are stored as follows (alpha << 24) | (red << 16) | (green << 8) | blue.
Source: android.graphics.Color reference.
// Edit: with HSV values it seems to work fine too. I did get a different result for 'magenta' as closest match though - violet, in stead of pink. You might want to double check the values and breakpoint some stuff. For instance, I can imagine it might be better to normalize the 'H' part. That's up to you...
private String getBestMatchingHsvColor(int pixelColor) {
// largest difference is 360(H), 1(S), 1(V)
float currentDifference = 360 + 1 + 1;
// name of the best matching colour
String closestColorName = null;
// get HSV values for the pixel's colour
float[] pixelColorHsv = new float[3];
Color.colorToHSV(pixelColor, pixelColorHsv);
Iterator<String> colorNameIterator = mColors.keySet().iterator();
// continue iterating if the map contains a next colour and the difference is greater than zero.
// a difference of zero means we've found an exact match, so there's not point in iterating further.
while (colorNameIterator.hasNext() && currentDifference > 0) {
// this colour's name
String currentColorName = colorNameIterator.next();
// this colour's int value
int color = mColors.get(currentColorName);
// get HSV values for this colour
float[] colorHsv = new float[3];
Color.colorToHSV(color, colorHsv);
// calculate sum of absolute differences that indicates how good this match is
float difference = Math.abs(pixelColorHsv[0] - colorHsv[0]) + Math.abs(pixelColorHsv[1] - colorHsv[1]) + Math.abs(pixelColorHsv[2] - colorHsv[2]);
// a smaller difference means a better match, so store it
if (currentDifference > difference) {
currentDifference = difference;
closestColorName = currentColorName;
}
}
return closestColorName;
}
Since you already have pixel color value in int. You can extract the RGB value using following methods
int green = Color.green(pix[i]);
int red = Color.red(pix[i]);
int blue = Color.blue(pix[i]);
And then compare with the RGB values you have
来源:https://stackoverflow.com/questions/8622104/find-color-name-when-have-hue-in-android