13

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

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

谢谢,尼克

4

3 回答 3

18

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

hsv色彩空间图

更新:

好消息,我惊喜地发现 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)

这是一个显示其输出的示例:

在 HSV 颜色空间中显示颜色插值的示例

我认为您可能会发现生成的颜色比我的其他答案更好。

概括:

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

以下是如何做到这一点:

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)))

结果:

显示黄色和蓝色之间 HSV 颜色空间中颜色插值的示例

于 2012-06-05T18:03:59.473 回答
7

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

这就是我的意思:

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

这是一个显示其输出的示例:

显示 RGB 颜色空间中的插值的图像

如果您想从绿色变为红色,只需反转函数中rg的计算即可。无需太多额外的努力,您就可以概括该概念以允许在任何两种给定颜色之间进行线性插值。

这是如何做到的:

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)))

使用提供的颜色的示例输出:

显示不同颜色的 RGB 颜色空间中插值的图像

于 2012-06-06T03:36:51.080 回答
5

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

这将映射到下图中显示的颜色范围。

在此处输入图像描述

此方法的一个方便特性是,您可以通过更改为、、等 轻松切换到任何一个matplotlib 颜色图。cm.jetcm.rainbowcm.nipy_spectralcm.Accent

于 2016-09-07T12:31:00.997 回答