2012-06-05 513 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