How can I convert a color in RGB format into a color name?开发者_如何学Python
Examples:
- (0, 0, 255) -> "blue"
- (255, 0, 0) -> "red"
- (128, 128, 128) -> "grey"
Here is a working sample code that does that. It converts an rgb/hex value/awt color into the closest color name.
import java.awt.Color;
import java.util.ArrayList;
/**
* Java Code to get a color name from rgb/hex value/awt color
*
* The part of looking up a color name from the rgb values is edited from
* https://gist.github.com/nightlark/6482130#file-gistfile1-java (that has some errors) by Ryan Mast (nightlark)
*
* @author Xiaoxiao Li
*
*/
public class ColorUtils {
/**
* Initialize the color list that we have.
*/
private ArrayList<ColorName> initColorList() {
ArrayList<ColorName> colorList = new ArrayList<ColorName>();
colorList.add(new ColorName("AliceBlue", 0xF0, 0xF8, 0xFF));
colorList.add(new ColorName("AntiqueWhite", 0xFA, 0xEB, 0xD7));
colorList.add(new ColorName("Aqua", 0x00, 0xFF, 0xFF));
colorList.add(new ColorName("Aquamarine", 0x7F, 0xFF, 0xD4));
colorList.add(new ColorName("Azure", 0xF0, 0xFF, 0xFF));
colorList.add(new ColorName("Beige", 0xF5, 0xF5, 0xDC));
colorList.add(new ColorName("Bisque", 0xFF, 0xE4, 0xC4));
colorList.add(new ColorName("Black", 0x00, 0x00, 0x00));
colorList.add(new ColorName("BlanchedAlmond", 0xFF, 0xEB, 0xCD));
colorList.add(new ColorName("Blue", 0x00, 0x00, 0xFF));
colorList.add(new ColorName("BlueViolet", 0x8A, 0x2B, 0xE2));
colorList.add(new ColorName("Brown", 0xA5, 0x2A, 0x2A));
colorList.add(new ColorName("BurlyWood", 0xDE, 0xB8, 0x87));
colorList.add(new ColorName("CadetBlue", 0x5F, 0x9E, 0xA0));
colorList.add(new ColorName("Chartreuse", 0x7F, 0xFF, 0x00));
colorList.add(new ColorName("Chocolate", 0xD2, 0x69, 0x1E));
colorList.add(new ColorName("Coral", 0xFF, 0x7F, 0x50));
colorList.add(new ColorName("CornflowerBlue", 0x64, 0x95, 0xED));
colorList.add(new ColorName("Cornsilk", 0xFF, 0xF8, 0xDC));
colorList.add(new ColorName("Crimson", 0xDC, 0x14, 0x3C));
colorList.add(new ColorName("Cyan", 0x00, 0xFF, 0xFF));
colorList.add(new ColorName("DarkBlue", 0x00, 0x00, 0x8B));
colorList.add(new ColorName("DarkCyan", 0x00, 0x8B, 0x8B));
colorList.add(new ColorName("DarkGoldenRod", 0xB8, 0x86, 0x0B));
colorList.add(new ColorName("DarkGray", 0xA9, 0xA9, 0xA9));
colorList.add(new ColorName("DarkGreen", 0x00, 0x64, 0x00));
colorList.add(new ColorName("DarkKhaki", 0xBD, 0xB7, 0x6B));
colorList.add(new ColorName("DarkMagenta", 0x8B, 0x00, 0x8B));
colorList.add(new ColorName("DarkOliveGreen", 0x55, 0x6B, 0x2F));
colorList.add(new ColorName("DarkOrange", 0xFF, 0x8C, 0x00));
colorList.add(new ColorName("DarkOrchid", 0x99, 0x32, 0xCC));
colorList.add(new ColorName("DarkRed", 0x8B, 0x00, 0x00));
colorList.add(new ColorName("DarkSalmon", 0xE9, 0x96, 0x7A));
colorList.add(new ColorName("DarkSeaGreen", 0x8F, 0xBC, 0x8F));
colorList.add(new ColorName("DarkSlateBlue", 0x48, 0x3D, 0x8B));
colorList.add(new ColorName("DarkSlateGray", 0x2F, 0x4F, 0x4F));
colorList.add(new ColorName("DarkTurquoise", 0x00, 0xCE, 0xD1));
colorList.add(new ColorName("DarkViolet", 0x94, 0x00, 0xD3));
colorList.add(new ColorName("DeepPink", 0xFF, 0x14, 0x93));
colorList.add(new ColorName("DeepSkyBlue", 0x00, 0xBF, 0xFF));
colorList.add(new ColorName("DimGray", 0x69, 0x69, 0x69));
colorList.add(new ColorName("DodgerBlue", 0x1E, 0x90, 0xFF));
colorList.add(new ColorName("FireBrick", 0xB2, 0x22, 0x22));
colorList.add(new ColorName("FloralWhite", 0xFF, 0xFA, 0xF0));
colorList.add(new ColorName("ForestGreen", 0x22, 0x8B, 0x22));
colorList.add(new ColorName("Fuchsia", 0xFF, 0x00, 0xFF));
colorList.add(new ColorName("Gainsboro", 0xDC, 0xDC, 0xDC));
colorList.add(new ColorName("GhostWhite", 0xF8, 0xF8, 0xFF));
colorList.add(new ColorName("Gold", 0xFF, 0xD7, 0x00));
colorList.add(new ColorName("GoldenRod", 0xDA, 0xA5, 0x20));
colorList.add(new ColorName("Gray", 0x80, 0x80, 0x80));
colorList.add(new ColorName("Green", 0x00, 0x80, 0x00));
colorList.add(new ColorName("GreenYellow", 0xAD, 0xFF, 0x2F));
colorList.add(new ColorName("HoneyDew", 0xF0, 0xFF, 0xF0));
colorList.add(new ColorName("HotPink", 0xFF, 0x69, 0xB4));
colorList.add(new ColorName("IndianRed", 0xCD, 0x5C, 0x5C));
colorList.add(new ColorName("Indigo", 0x4B, 0x00, 0x82));
colorList.add(new ColorName("Ivory", 0xFF, 0xFF, 0xF0));
colorList.add(new ColorName("Khaki", 0xF0, 0xE6, 0x8C));
colorList.add(new ColorName("Lavender", 0xE6, 0xE6, 0xFA));
colorList.add(new ColorName("LavenderBlush", 0xFF, 0xF0, 0xF5));
colorList.add(new ColorName("LawnGreen", 0x7C, 0xFC, 0x00));
colorList.add(new ColorName("LemonChiffon", 0xFF, 0xFA, 0xCD));
colorList.add(new ColorName("LightBlue", 0xAD, 0xD8, 0xE6));
colorList.add(new ColorName("LightCoral", 0xF0, 0x80, 0x80));
colorList.add(new ColorName("LightCyan", 0xE0, 0xFF, 0xFF));
colorList.add(new ColorName("LightGoldenRodYellow", 0xFA, 0xFA, 0xD2));
colorList.add(new ColorName("LightGray", 0xD3, 0xD3, 0xD3));
colorList.add(new ColorName("LightGreen", 0x90, 0xEE, 0x90));
colorList.add(new ColorName("LightPink", 0xFF, 0xB6, 0xC1));
colorList.add(new ColorName("LightSalmon", 0xFF, 0xA0, 0x7A));
colorList.add(new ColorName("LightSeaGreen", 0x20, 0xB2, 0xAA));
colorList.add(new ColorName("LightSkyBlue", 0x87, 0xCE, 0xFA));
colorList.add(new ColorName("LightSlateGray", 0x77, 0x88, 0x99));
colorList.add(new ColorName("LightSteelBlue", 0xB0, 0xC4, 0xDE));
colorList.add(new ColorName("LightYellow", 0xFF, 0xFF, 0xE0));
colorList.add(new ColorName("Lime", 0x00, 0xFF, 0x00));
colorList.add(new ColorName("LimeGreen", 0x32, 0xCD, 0x32));
colorList.add(new ColorName("Linen", 0xFA, 0xF0, 0xE6));
colorList.add(new ColorName("Magenta", 0xFF, 0x00, 0xFF));
colorList.add(new ColorName("Maroon", 0x80, 0x00, 0x00));
colorList.add(new ColorName("MediumAquaMarine", 0x66, 0xCD, 0xAA));
colorList.add(new ColorName("MediumBlue", 0x00, 0x00, 0xCD));
colorList.add(new ColorName("MediumOrchid", 0xBA, 0x55, 0xD3));
colorList.add(new ColorName("MediumPurple", 0x93, 0x70, 0xDB));
colorList.add(new ColorName("MediumSeaGreen", 0x3C, 0xB3, 0x71));
colorList.add(new ColorName("MediumSlateBlue", 0x7B, 0x68, 0xEE));
colorList.add(new ColorName("MediumSpringGreen", 0x00, 0xFA, 0x9A));
colorList.add(new ColorName("MediumTurquoise", 0x48, 0xD1, 0xCC));
colorList.add(new ColorName("MediumVioletRed", 0xC7, 0x15, 0x85));
colorList.add(new ColorName("MidnightBlue", 0x19, 0x19, 0x70));
colorList.add(new ColorName("MintCream", 0xF5, 0xFF, 0xFA));
colorList.add(new ColorName("MistyRose", 0xFF, 0xE4, 0xE1));
colorList.add(new ColorName("Moccasin", 0xFF, 0xE4, 0xB5));
colorList.add(new ColorName("NavajoWhite", 0xFF, 0xDE, 0xAD));
colorList.add(new ColorName("Navy", 0x00, 0x00, 0x80));
colorList.add(new ColorName("OldLace", 0xFD, 0xF5, 0xE6));
colorList.add(new ColorName("Olive", 0x80, 0x80, 0x00));
colorList.add(new ColorName("OliveDrab", 0x6B, 0x8E, 0x23));
colorList.add(new ColorName("Orange", 0xFF, 0xA5, 0x00));
colorList.add(new ColorName("OrangeRed", 0xFF, 0x45, 0x00));
colorList.add(new ColorName("Orchid", 0xDA, 0x70, 0xD6));
colorList.add(new ColorName("PaleGoldenRod", 0xEE, 0xE8, 0xAA));
colorList.add(new ColorName("PaleGreen", 0x98, 0xFB, 0x98));
colorList.add(new ColorName("PaleTurquoise", 0xAF, 0xEE, 0xEE));
colorList.add(new ColorName("PaleVioletRed", 0xDB, 0x70, 0x93));
colorList.add(new ColorName("PapayaWhip", 0xFF, 0xEF, 0xD5));
colorList.add(new ColorName("PeachPuff", 0xFF, 0xDA, 0xB9));
colorList.add(new ColorName("Peru", 0xCD, 0x85, 0x3F));
colorList.add(new ColorName("Pink", 0xFF, 0xC0, 0xCB));
colorList.add(new ColorName("Plum", 0xDD, 0xA0, 0xDD));
colorList.add(new ColorName("PowderBlue", 0xB0, 0xE0, 0xE6));
colorList.add(new ColorName("Purple", 0x80, 0x00, 0x80));
colorList.add(new ColorName("Red", 0xFF, 0x00, 0x00));
colorList.add(new ColorName("RosyBrown", 0xBC, 0x8F, 0x8F));
colorList.add(new ColorName("RoyalBlue", 0x41, 0x69, 0xE1));
colorList.add(new ColorName("SaddleBrown", 0x8B, 0x45, 0x13));
colorList.add(new ColorName("Salmon", 0xFA, 0x80, 0x72));
colorList.add(new ColorName("SandyBrown", 0xF4, 0xA4, 0x60));
colorList.add(new ColorName("SeaGreen", 0x2E, 0x8B, 0x57));
colorList.add(new ColorName("SeaShell", 0xFF, 0xF5, 0xEE));
colorList.add(new ColorName("Sienna", 0xA0, 0x52, 0x2D));
colorList.add(new ColorName("Silver", 0xC0, 0xC0, 0xC0));
colorList.add(new ColorName("SkyBlue", 0x87, 0xCE, 0xEB));
colorList.add(new ColorName("SlateBlue", 0x6A, 0x5A, 0xCD));
colorList.add(new ColorName("SlateGray", 0x70, 0x80, 0x90));
colorList.add(new ColorName("Snow", 0xFF, 0xFA, 0xFA));
colorList.add(new ColorName("SpringGreen", 0x00, 0xFF, 0x7F));
colorList.add(new ColorName("SteelBlue", 0x46, 0x82, 0xB4));
colorList.add(new ColorName("Tan", 0xD2, 0xB4, 0x8C));
colorList.add(new ColorName("Teal", 0x00, 0x80, 0x80));
colorList.add(new ColorName("Thistle", 0xD8, 0xBF, 0xD8));
colorList.add(new ColorName("Tomato", 0xFF, 0x63, 0x47));
colorList.add(new ColorName("Turquoise", 0x40, 0xE0, 0xD0));
colorList.add(new ColorName("Violet", 0xEE, 0x82, 0xEE));
colorList.add(new ColorName("Wheat", 0xF5, 0xDE, 0xB3));
colorList.add(new ColorName("White", 0xFF, 0xFF, 0xFF));
colorList.add(new ColorName("WhiteSmoke", 0xF5, 0xF5, 0xF5));
colorList.add(new ColorName("Yellow", 0xFF, 0xFF, 0x00));
colorList.add(new ColorName("YellowGreen", 0x9A, 0xCD, 0x32));
return colorList;
}
/**
* Get the closest color name from our list
*
* @param r
* @param g
* @param b
* @return
*/
public String getColorNameFromRgb(int r, int g, int b) {
ArrayList<ColorName> colorList = initColorList();
ColorName closestMatch = null;
int minMSE = Integer.MAX_VALUE;
int mse;
for (ColorName c : colorList) {
mse = c.computeMSE(r, g, b);
if (mse < minMSE) {
minMSE = mse;
closestMatch = c;
}
}
if (closestMatch != null) {
return closestMatch.getName();
} else {
return "No matched color name.";
}
}
/**
* Convert hexColor to rgb, then call getColorNameFromRgb(r, g, b)
*
* @param hexColor
* @return
*/
public String getColorNameFromHex(int hexColor) {
int r = (hexColor & 0xFF0000) >> 16;
int g = (hexColor & 0xFF00) >> 8;
int b = (hexColor & 0xFF);
return getColorNameFromRgb(r, g, b);
}
public int colorToHex(Color c) {
return Integer.decode("0x"
+ Integer.toHexString(c.getRGB()).substring(2));
}
public String getColorNameFromColor(Color color) {
return getColorNameFromRgb(color.getRed(), color.getGreen(),
color.getBlue());
}
/**
* SubClass of ColorUtils. In order to lookup color name
*
* @author Xiaoxiao Li
*
*/
public class ColorName {
public int r, g, b;
public String name;
public ColorName(String name, int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
this.name = name;
}
public int computeMSE(int pixR, int pixG, int pixB) {
return (int) (((pixR - r) * (pixR - r) + (pixG - g) * (pixG - g) + (pixB - b)
* (pixB - b)) / 3);
}
public int getR() {
return r;
}
public int getG() {
return g;
}
public int getB() {
return b;
}
public String getName() {
return name;
}
}
}
- Populate a list of "known" colors.
For each known color compute:
rgbDistance = Math.abs(myColor.getRed() - colorI.getRed() + Math.abs(myColor.getGreen() - colorI.getGreen()) + Math.abs(myColor.getBlue() - colorI.getBlue())
Return the name of
colorI
for whichrgbDistance
was smallest.
Hmm, that's a kind of fun problem. I can think of a few solutions:
You could do a bit of guesswork depending on the relationships between the R-G-B values (for example, if one color is very dominant you guess that one, but if there's a bit of other color you get more and more likely to guess the combination of those two emitted colors, if all three are close to equal then guess white, grey, or black depending on how high the average of the three values is, if two are high and the other is low guess the combinatoin of the two, etc. etc.)
You could go for a more learning approach where you set some initial guesses (as above) and then improve on those based on feedback from users.
Unfortunately this problem is relatively subjective (although the question is not!) as people's perception of color varies widely between culture and even gender (see Randall Munroe's "study" on it ).
If you want a specific subset of RGB values (like the ones that are given constants in Java or C# you can iterate through each and compare, finally returning some default value if it's not equal to any of them).
[EDIT]
Ahh! Colorblind users eh? Have you considered creating a setting which lets the user specify which colors they have trouble differentiating? If you did that you could let them know that something is "20% Redder than Green" (if, for instance, they had red-green colorblindness, which is most common). That would be pretty simple. They select a pixel, and you follow this pseudocode:
if( userColorTrouble == RedGreen )
{
int redVal = colorInQuestion.GetRed();
int greenVal = colorInQuestion.GetGreen();
if( redVal > greenVal )
{
return "The color is " + (double)redVal / (redVal + greenVal) - .5d + "% redder than green";
}
else
{
return "The color is " + (double)greenVal / (redVal + greenVal) - .5d + "% greener than red";
}
}
That could be a simpler, and more useful solution.
You could simply build a lookup table, e.g. using the constants from Color class itself:
Map<Integer, String> map = new HashMap<Integer, String>();
for (Field f : Color.class.getFields()) {
if (f.getType() == Color.class) {
Color c = (Color) f.get(null);
map.put(c.getRGB(), f.getName());
}
}
If you want all HTML colors or all those form Wikipedia linked by @evan, you have still a little homework to do though.
EDIT resulting map:
0xff00ffff: CYAN
0xff0000ff: BLUE
0xffc0c0c0: LIGHT_GRAY
0xff808080: GRAY
0xffffff00: YELLOW
0xffff0000: RED
0xffffafaf: PINK
0xff000000: BLACK
0xff00ff00: GREEN
0xffffc800: ORANGE
0xff404040: DARK_GRAY
0xffff00ff: MAGENTA
0xffffffff: WHITE
Not all RGB values have aliases. You may need to create an array containing arrays of Red, Green, Blue, and Alias values. Then you would iterate over that array comparing the RGB values.
http://en.wikipedia.org/wiki/List_of_colors
Edit:
Sample:
//array of known aliases and rgb values
ArrayList colorList = new ArrayList();
colorList.add(new String[] {"255", "0", "0", "Red"});
//etc...
Color c = new Color(255, 0, 0); //test color
String name = "Unknown";
for (String[] color : colorList)
{
int r = Integer.parseInt(color[0]) //red value
int g = Integer.parseInt(color[1]) //green value
int b = Integer.parseInt(color[2]) //blue value
String alias = color[3];
if ((c.getRed() == r) && (c.getGreen() == g) && (c.getBlue() == b))
{
name = alias; //found it
break;
}
}
Frist of all convert pixels from RGB to HSV. It's much easier to define color ranges in HSV than in RGB.
/**
*
*@author Tomasz Drobiszewski
*/
public class Color {
/**
* Human color table.
*/
public static final int [] [] colors = {
{-1,-10,-360,-0,-100,-10,-80},
{1,0,360,0,100,0,50},
{2,0,360,0,15,50,130},
{3,0,360,0,15,130,210},
{4,-15,15,15,100,50,255},
{5,15,45,15,100,50,255},
{6,45,75,15,100,50,255},
{7,75,105,15,100,50,255},
{8,105,135,15,100,50,255},
{9,135,165,15,100,50,255},
{10,165,195,15,100,50,255},
{11,195,225,15,100,50,255},
{12,225,255,15,100,50,255},
{13,255,285,15,100,50,255},
{14,285,315,15,100,50,255},
{15,315,345,15,100,50,255},
{16,345,375,15,100,50,255},
{17,0,360,0,15,210,255}
};
/**
* Color names.
*/
public static final String [] humanColors = {
"unrecognized",
"black", //black colors[1]
"grey",
"light_grey",
"red",
"orange",
"yellow",
"jasny_zielony",
"zielony",
"zielony",
"turkusowy",
"jasny_niebieski",
"niebieski",
"fioletowy",
"fioletowy",
"rozowy",
"czerwony",
"bialy",
};
/**
* Convert from RGB do HSV
*
* @param r
* @param g
* @param b
* @param hsv
*/
public static void rgb2hsv(int r, int g, int b, int hsv[]) {
int min; // Min. value of RGB
int max; // Max. value of RGB
int delMax; // Delta RGB value
if (r > g) {
min = g;
max = r;
} else {
min = r;
max = g;
}
if (b > max)
max = b;
if (b < min)
min = b;
delMax = max - min;
float H = 0, S;
float V = max;
if (delMax == 0) {
H = 0;
S = 0;
} else {
S = delMax / (float) max;
if (r == max)
H = ((g - b) / (float) delMax) * 60;
else if (g == max)
H = (2 + (b - r) / (float) delMax) * 60;
else if (b == max)
H = (4 + (r - g) / (float) delMax) * 60;
}
hsv[0] = (int) (H);
hsv[1] = (int) (S * 100);
hsv[2] = (int) V;
}
/**
* Return human color index {@link Color#colors}
*
* @param r
* @param g
* @param b
* @return
*/
public static int [] getHumanColor(int r, int g, int b) {
int [] res = {0, 0, 0, 0};
int[] hsv = new int[3];
rgb2hsv(r, g, b, hsv);
for (int i = 1; i < colors.length; i++) {
if (hsv[0] <= colors[i][2] && hsv[0] >= colors[i][1]
&& hsv[1] <= colors[i][4] && hsv[1] >= colors[i][3]
&& hsv[2] <= colors[i][6] && hsv[2] >= colors[i][5]) {
res[3] = i;
res[0] = hsv[0];
res[1] = hsv[1];
res[2] = hsv[2];
return res;
}
}
return res;
}
}
public static String findColorNameByColor(Color c) throws IllegalArgumentException, IllegalAccessException {
String candidateColorName = null;
int rgbDistance = -1;
for(Field f : Color.class.getFields()) {
Color sys_c = (Color) f.get(null);
int dif_r = Math.abs(c.getRed() - sys_c.getRed());
int dif_g = Math.abs(c.getGreen() - sys_c.getGreen());
int dif_b = Math.abs(c.getBlue() - sys_c.getBlue());
int sum = dif_r+dif_g+dif_b;
if(sum == 0) {
return f.getName().trim().toLowerCase();
}else {
if (rgbDistance == -1) {
rgbDistance = sum;
candidateColorName = f.getName().trim().toLowerCase();
}
if(rgbDistance > sum) {
rgbDistance = sum;
candidateColorName = f.getName().trim().toLowerCase();
}
}
}
return candidateColorName;
}
In my case I was looking for a quick way to get the name of primary colours displayable on all on or all off LEDs so the following function works for me. Hope it's helpful to someone.
public static String getColourName(int c) {
String name = "UNKNOWN";
int colour = Color.BLACK;
if(Color.red(c) > 127) { colour |= Color.RED; }
if(Color.green(c) > 127) { colour |= Color.GREEN; }
if(Color.blue(c) > 127) { colour |= Color.BLUE; }
switch (colour) {
case Color.BLACK:
name = "BLACK";
break;
case Color.BLUE:
name = "BLUE";
break;
case Color.GREEN:
name = "GREEN";
break;
case Color.CYAN:
name = "CYAN";
break;
case Color.RED:
name = "RED";
break;
case Color.MAGENTA:
name = "MAGENTA";
break;
case Color.YELLOW:
name = "YELLOW";
break;
case Color.WHITE:
name = "WHITE";
break;
}
return name;
}
精彩评论