2011-12-24 65 views
1

有色调时,我只关心12种颜色:查找颜色名称中的Android

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 

,当我读到位图的像素,我能得到的色调值:

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

要获得最接近你的12种颜色之一的颜色,你必须基本上限定一些RGB值与每个颜色相匹配的程度。最直接的方法可能是计算三个颜色分量中的每一个的绝对差值并将它们相加。具有最小差异的颜色将是您最好的搭配。尽管这样做可能会变得相当昂贵,因为尽管一些优化是绝对有可能的,但你必须做这个'width * height * 12'次。 – 2011-12-24 02:38:30

+0

我必须将RBG转换为HSV吗? – 2011-12-24 02:54:58

+0

我不确定你的意思。据我可以告诉你有12种颜色的RGB值,Rajdeep的答案显示了如何获得特定像素的三种颜色分量。你需要什么HSV值? – 2011-12-24 03:21:21

回答

3

根据您的意见,似乎你基本上试图将位图的全彩色调色板减少到只有比较提取RGB值你指定的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) 

第一个数字其间括号是用于颜色恒定的实际int值,第二个是int值找到最佳匹配,并在名称前面加上名称。

Color.MAGENTA的结果还说明了为什么不应该直接比较颜色的int值。实际的int值是-65281,这与Color.RED(-65536)的值非常接近。然而,基于不同组件的最佳匹配是“粉红色”,其具有-16181值。显然,这使得完整意义上知道一个颜色定义为4个字节:

颜色表示为包装整数,由4个字节:alpha,红色, 绿,蓝。 (...)组件存储如下(alpha < < 24) | (红色< < 16)| (绿色< < 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; 
} 
+0

嗨,感谢您的回答,但我必须使用HSV模式 – 2011-12-25 15:14:38

+0

您能否告诉我使用HSV的解决方案,我必须使用HSV。谢谢 – 2011-12-27 05:27:13

+0

你有没有试过HSV值的上述方法? – 2011-12-28 18:07:39

1

因为你已经有int像素颜色值。 您可以通过以下方法

int green = Color.green(pix[i]); 
int red = Color.red(pix[i]); 
int blue = Color.blue(pix[i]); 

然后用RGB值,你有

+0

当我有一种颜色不在我的列表中时,我想在列表中使用类似的颜色,以便将它转换为HSV。例如:红:0 - > 18,306-> 359 橙:19 - > 41 黄色:42 - > 69 绿色:70 - > 166 蓝:167 - > 251 紫:252 - > 305 – 2011-12-24 02:06:59

+0

问题不是很清楚,你能不能详细说一下 – 2011-12-24 02:09:10

+0

我的意思是,当我有一个像素时,我想知道颜色的名称。当我有一些类型的红色:http://en.wikipedia.org/wiki/List_of_colors#Red我想标记他们只有红色 – 2011-12-24 02:22:56