Python 将值范围设置为伪彩色

Python 将值范围设置为伪彩色,python,colors,floating-point,gradient,Python,Colors,Floating Point,Gradient,我有一个特定的浮点数组(在Python中),其范围可能从0到100。我想创建一个伪彩色图像,使颜色从绿色(对应于0)到红色(100)不等。这类似于matplotlib中的pcolor。但是,我不想使用pcolor 是否有类似于pseudocolorForValue(val,(minval,maxval))的函数返回与val的伪彩色值对应的RGB三元组?此外,此功能是否具有灵活性,可以选择是显示从绿色到红色还是从红色到绿色的颜色 谢谢, Nik您可以编写自己的函数来转换值0…100→ 0…120度

我有一个特定的浮点数组(在Python中),其范围可能从0到100。我想创建一个伪彩色图像,使颜色从绿色(对应于0)到红色(100)不等。这类似于matplotlib中的pcolor。但是,我不想使用pcolor

是否有类似于
pseudocolorForValue(val,(minval,maxval))
的函数返回与
val
的伪彩色值对应的RGB三元组?此外,此功能是否具有灵活性,可以选择是显示从绿色到红色还是从红色到绿色的颜色

谢谢,
Nik

您可以编写自己的函数来转换值0…100→ 0…120度,然后将该值用作HSV(或HLS)颜色空间中颜色的H(或角度)。然后可以将其转换为RGB颜色以用于显示。在该颜色空间中计算线性解释的颜色时,其外观通常更好:以下是HSV颜色空间的外观:

更新:

好消息是,我惊喜地发现Python在其内置模块中有颜色空间转换例程(它们实际上是指“包括电池”)。这样做的好处在于,它使得创建一个实现我所描述的功能变得相当容易,如下所示:

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)
下面是一个显示其输出的示例:

我想你可能会发现生成的颜色比我的另一个答案更好

概括化:

可以将此函数修改为更通用的一点,因为它将处理除当前硬编码的红色和绿色之外的其他颜色

以下是如何做到这一点:

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)))
结果:


虽然可以说不如在HLS或HSV颜色空间中插值H漂亮,但一种更简单的实现方法是编写一个函数,将单个值映射为三个分量,对应于完全
红色(1,0,0)
和完全绿色
(0,1,0)之间的线性插值颜色
在RGB颜色空间中

我的意思是:

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范围内的整数

下面是一个显示其输出的示例:

如果要从绿色变为红色,只需在函数中反转r和g的计算。不需要太多额外的努力,您就可以将这个概念推广到允许在任意两种给定颜色之间进行线性插值

以下是如何做到这一点:

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)))
使用提供的颜色的示例输出:

您可以直接访问,这正是pcolor用来确定其颜色映射的内容。每个映射接受[0,1]范围内的一个浮点,并返回[0,1]范围内的一个4元素浮点元组,其中包含组件(R、G、B、a)。下面是一个使用标准
jet
colormap返回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)
这将映射到下图所示的颜色范围


此方法的一个方便功能是,通过将
cm.jet
更改为
cm.rainbow
cm.nipy\u spectrum
cm.Accent
等,您可以轻松切换到任何一种。谢谢。有趣的建议。虽然很难相信像我需要的那样的函数还没有在Python中构建。毕竟,matplotlib中的pcolor也做了同样的事情。所以它一定是以某种方式调用了这样一个函数。你知道这样一个功能吗?@Nik:不,我不知道有内置的,坦率地说,我并不奇怪没有内置的功能——它是特定于领域的。唯一不重要的部分是颜色转换,你应该可以在一本基本的计算机图形学书籍或其他书籍中找到。可能有一个开源的图形包,里面有这样一个实用程序,你可以使用。@Nik:Python有内置的颜色空间转换函数——请参阅我对这个答案的更新。谢谢你的解决方案——非常有吸引力。作为旁注:我在
val
可能超出minval,maxval限制的情况下使用代码,因此我添加了
val=max(val,minval)
val=min(val,maxval)
。此外,建议检查minval和maxval的平等性(尽管是成年人同意;-)@jake77:是的,现实往往是一个特例。顺便说一句,在这里表达感激之情的最好方式就是投票表决答案……谢谢@martineau。这真的很有帮助!这值得更多的投票。是的,它使用matplotlib库,但它是一个简短而灵活的解决方案。