2012-06-05 517 views
11

我有一個浮點數(在Python中),可能範圍從0到100.我想創建一個僞彩色圖像,以便顏色從綠色(對應於0)到紅色( 100)。這與matplotlib中的pcolor類似。但是,我不想使用pcolor。範圍值pseudocolor

是否有像pseudocolorForValue(val,(minval,maxval))這樣的函數返回對應於'val'的僞色值的RGB三元組?另外,在此功能中是否有靈活性來選擇是以綠色到紅色還是從紅色到綠色顯示顏色?

謝謝, 的Nik

回答

15

你可以寫自己的函數轉換後的值在0 ... 100 => 0 ... 120度,然後使用該值作爲顏色的H(或角度)在HSV(或HLS)色彩空間中。然後可以將其轉換爲RGB顏色用於顯示。線性解釋顏色往往看起來更好,當他們在這個色彩空間正在計算:這裏是HSV色彩空間是什麼樣子:

hsv colorspace diagram

更新:

好消息,我驚喜地發現了Python在其內置的colorsys模塊中具有色彩空間轉換例程(它們的意思是「包含電池」)。關於什麼的,那該多好是,它使創建做什麼,我描述的相當容易的功能,如下圖所示:

from colorsys import hsv_to_rgb 

def pseudocolor(val, minval, maxval): 
    """ Convert val in range minval..maxval to the range 0..120 degrees which 
     correspond to the colors Red and Green in the HSV colorspace. 
    """ 
    h = (float(val-minval)/(maxval-minval)) * 120 

    # Convert hsv color (h,1,1) to its rgb equivalent. 
    # Note: hsv_to_rgb() function expects h to be in the range 0..1 not 0..360 
    r, g, b = hsv_to_rgb(h/360, 1., 1.) 
    return r, g, b 

if __name__ == '__main__': 
    steps = 10 

    print('val  R  G  B') 
    for val in range(0, 100+steps, steps): 
     print('{:3d} -> ({:.3f}, {:.3f}, {:.3f})'.format(
               val, *pseudocolor(val, 0, 100))) 

輸出:

val  R  G  B 
    0 -> (1.000, 0.000, 0.000) 
10 -> (1.000, 0.200, 0.000) 
20 -> (1.000, 0.400, 0.000) 
30 -> (1.000, 0.600, 0.000) 
40 -> (1.000, 0.800, 0.000) 
50 -> (1.000, 1.000, 0.000) 
60 -> (0.800, 1.000, 0.000) 
70 -> (0.600, 1.000, 0.000) 
80 -> (0.400, 1.000, 0.000) 
90 -> (0.200, 1.000, 0.000) 
100 -> (0.000, 1.000, 0.000) 

這裏是展示什麼它的輸出看起來像一個示例:

sample showing color interpolation in HSV colorspace

我想你可能會發現比我的其他答案更好的顏色。

泛化:

它可以修改此功能是一個小更一般的意義,它將與其他色彩則只是紅色和綠色當前硬編碼到它的工作。

這裏是如何做到這一點:

def pseudocolor(val, minval, maxval, start_hue, stop_hue): 
    """ Convert val in range minval..maxval to the range start_hue..stop_hue 
     degrees in the HSV colorspace. 
    """ 
    h = (float(val-minval)/(maxval-minval)) * (stop_hue-start_hue) + start_hue 

    # Convert hsv color (h,1,1) to its rgb equivalent. 
    # Note: hsv_to_rgb() function expects h to be in the range 0..1 not 0..360 
    r, g, b = hsv_to_rgb(h/360, 1., 1.) 
    return r, g, b 

if __name__ == '__main__': 
    # angles of common colors in hsv colorspace 
    RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA = range(0, 360, 60) 
    steps = 10 

    print('val  R  G  B') 
    for val in range(0, 100+steps, steps): 
     print('{:3d} -> ({:.3f}, {:.3f}, {:.3f})'.format(
       val, *pseudocolor(val, 0, 100, YEllOW, BLUE))) 

結果:

sample showing color interpolation in HSV colorspace between yellow and blue

+0

感謝。有趣的建議。雖然很難相信像我需要的那樣的函數還沒有在Python中構建。畢竟,matplotlib中的pcolor做同樣的事情。所以它必須以某種方式調用這樣的功能。你知道這樣的功能嗎? – Nik

+0

@Nik:不,我不知道內置的,並坦率地說我不驚訝沒有一個 - 它是如此特定領域。唯一不平凡的部分是您應該可以在基本計算機圖形書或[在線](http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB)中找到的顏色轉換。可能有一個開源圖形軟件包,可以使用這種實用程序。 – martineau

+0

@Nik:Python內置了色彩空間轉換功能 - 請參閱我對此答案的更新。 – martineau

5

雖然可以說是不一樣漂亮的HLS或HSV色彩空間插值H,一個更簡單的實現方式會是寫入一個函數,該函數將單個值映射爲對應於完全在red (1,0,0)和完全綠色(0,1,0)之間的線性內插顏色的RGB顏色CE。

這裏就是我的意思是:

def pseudocolor(val, minval, maxval): 
    """ Convert value in the range minval...maxval to a color between red 
     and green. 
    """ 
    f = float(val-minval)/(maxval-minval) 
    r, g, b = 1-f, f, 0. 
    return r, g, b 

if __name__ == '__main__': 
    steps = 10 
    print('val  R  G  B') 
    for val in xrange(0, 100+steps, steps): 
     print('{:3d} -> ({:.3f}, {:.3f}, {:.3f})'.format(
        val, *pseudocolor(val, 0, 100))) 

輸出:

val  R  G  B 
    0 -> (1.000, 0.000, 0.000) 
10 -> (0.900, 0.100, 0.000) 
20 -> (0.800, 0.200, 0.000) 
30 -> (0.700, 0.300, 0.000) 
40 -> (0.600, 0.400, 0.000) 
50 -> (0.500, 0.500, 0.000) 
60 -> (0.400, 0.600, 0.000) 
70 -> (0.300, 0.700, 0.000) 
80 -> (0.200, 0.800, 0.000) 
90 -> (0.100, 0.900, 0.000) 
100 -> (0.000, 1.000, 0.000) 

您可以將浮點R,G,需要B組分,如在0之間的整數..255。

這裏是展示什麼它的輸出看起來像一個示例:

image showing interpolation in RGB colorspace

如果你想從綠色變爲紅色去,正好反向計算爲[R的功能。沒有太多額外的努力,你可以推廣這個概念,以允許任何兩種給定顏色之間的線性插值。

這裏是如何可以做:使用提供的顏色

def pseudocolor(val, minval, maxval, startcolor, stopcolor): 
    """ Convert value in the range minval...maxval to a color in the range 
     startcolor to stopcolor. The colors passed and the the one returned are 
     composed of a sequence of N component values. 
    """ 
    f = float(val-minval)/(maxval-minval) 
    return tuple(f*(b-a)+a for (a, b) in zip(startcolor, stopcolor)) 

if __name__ == '__main__': 
    YEllOW, BLUE = (1, 1, 0), (0, 0, 1) 
    steps = 10 

    print('val  R  G  B') 
    for val in range(0, 100+steps, steps): 
     print('{:3d} -> ({:.3f}, {:.3f}, {:.3f})'.format(
        val, *pseudocolor(val, 0, 100, YEllOW, BLUE))) 

輸出示例:

image showing interpolation in RGB colorspace with different colors

+0

謝謝@馬蒂諾。這真的有幫助! – Nik

2

您可以直接訪問matplolib's built-in colormaps,這是什麼令pColor用來確定其colormapping 。每個映射在[0,1]範圍內都有一個浮點數,並返回一個元素(R,G,B,A)中的[0,1]範圍內的浮點數的4元組元素。這裏是返回使用標準顏色表jet的RGBA元組的函數的一個例子:

from matplotlib import cm 

def pseudocolor(val, minval, maxmal): 
    # Scale val to be in the range [0, 1] 
    val = (val - minval)/(maxval - minval) 
    # Return RGBA tuple from jet colormap 
    return cm.jet(val) 

pseudocolor(20, 0, 100) 
# Returns: (0.0, 0.3, 1.0, 1.0) 

pseudocolor(80, 0, 100) 
# Returns: (1.0, 0.4074, 0.0, 1.0) 

這將映射到下面的圖像中顯示的顏色範圍。

enter image description here

之一有關此方法的方便的特點是,可以很容易地通過改變cm.jet切換到matplotlib colormaps中任一項cm.rainbowcm.nipy_spectralcm.Accent

+0

這值得讚賞。是的,它使用matplotlib庫,但它是一個簡短而靈活的解決方案。 – medley56