2011-12-24 35 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