我只关心12种颜色:
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
当我读取位图的像素时,我可以得到Hue值:
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]));
}
}
现在我想知道这个像素的颜色(只有12种以上的颜色)?
我使用HSV来查看颜色范围。当我有一个不在此列表中的颜色时,我想在列表中将其命名为类似的颜色 我该怎么办?
非常感谢你
答案 0 :(得分:3)
根据您的评论,您似乎基本上尝试将位图的全色调色板减少到仅指定的12个。显然,对于位图中的每个像素,应该选择来自那些12的“最佳匹配”。
我仍然不明白为什么你需要HSV值,因为它只是RGB组件的不同表示 - 它实际上并没有改变问题或其解决方案。
找到任何RGB颜色的最佳匹配的简单方法如下所示。
首先构建某种包含要匹配的颜色的列表。我使用了Map,因为你提到你(也)想知道颜色的名称,而不仅仅是RGB值。
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));
然后制作一个能告诉你最佳匹配的方法。您可以在第二个for循环中调用它并将其传递给当前像素颜色。我添加了一些内联注释来解释不同的步骤,但它确实非常简单。
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;
}
使用一些预定义颜色常量进行快速测试的结果:
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)
括号中的第一个数字是Color常量的实际int值,第二个是找到的最佳匹配的int值,名称在它前面。
Color.MAGENTA
的结果也说明了为什么不应该直接比较颜色的int值。实际的int值为-65281
,非常接近Color.RED
( - 65536)的值。但是,基于不同组件的最佳匹配是“粉红色”,其值为-16181。显然,这完全意义上知道颜色被定义为4个字节:
颜色表示为压缩整数,由4个字节组成:alpha,red, 绿,蓝。 (...)组件存储如下(alpha <&lt; 24) | (红色&lt;&lt; 16)| (绿色&lt;&lt; 8)|蓝色。
Source: android.graphics.Color reference.
//编辑:使用HSV值似乎也能正常工作。我确实得到了与“洋红色”不同的结果作为最接近的匹配 - 紫罗兰色,而不是粉红色。您可能想要仔细检查值并断点一些东西。例如,我可以想象将“H”部分标准化可能会更好。这取决于你...
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;
}
答案 1 :(得分:1)
因为你已经在int中有像素颜色值。 您可以使用以下方法提取RGB值
int green = Color.green(pix[i]);
int red = Color.red(pix[i]);
int blue = Color.blue(pix[i]);
然后与您拥有的RGB值进行比较