How to decode color mapping in matplotlib's Colormap?

前端 未结 1 1140
梦如初夏
梦如初夏 2020-11-30 14:55

I know how to map a number to a color from this post: Map values to colors in matplotlib

But I don\'t know how to decode the mapping to get my original color, assumi

相关标签:
1条回答
  • 2020-11-30 15:32

    Inverting the colormapping is possible, if
    (a) you know the data range it is mapping and
    (b) if you know the colormap that has been used, and
    (c) if the colormap is unambiguous.

    The following function would return the value given a color, a colormap and the range over which the colormap has been used.

    import numpy as np
    import matplotlib.colors
    import matplotlib.pyplot as plt
    
    def get_value_from_cm(color, cmap, colrange=[0.,1.]):
        color=matplotlib.colors.to_rgb(color)
        r = np.linspace(colrange[0],colrange[1], 256)
        norm = matplotlib.colors.Normalize(colrange[0],colrange[1])
        mapvals = cmap(norm(r))[:,:3]
        distance = np.sum((mapvals - color)**2, axis=1)
        return r[np.argmin(distance)]
    
    
    b = get_value_from_cm(plt.cm.coolwarm(0.5), plt.cm.coolwarm, [0.,1.])
    c = get_value_from_cm(np.array([1,0,0]), plt.cm.coolwarm)
    
    print b                   # 0.501960784314
    print plt.cm.coolwarm(b)
    # (0.86742763508627452, 0.86437659977254899, 0.86260246201960789, 1.0)
    print plt.cm.coolwarm(0.5)
    #(0.86742763508627452, 0.86437659977254899, 0.86260246201960789, 1.0)
    

    Note that this method involves an error, so you only get the closest value from the colormap and not the value that has initially been used to create the color from the map.

    In the updated code from the question, you have the color defined as integers between 0 and 255 for each channel. You therefore need to first map those to the range 0 to 1.

    from PIL import Image
    import numpy as np
    import matplotlib
    import matplotlib.cm as cm
    values = [670, 894, 582, 103, 786, 348, 972, 718, 356, 692]
    minima = 103
    maxima = 972
    norm = matplotlib.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
    mapper = cm.ScalarMappable(norm=norm, cmap=cm.gist_rainbow_r)
    c = []
    for i in range(10):
        c.append(mapper.to_rgba(values[i], bytes=True))
    print(c) # [(75, 255, 0, 255), (255, 77, 0, 255), (0, 255, 64, 255), (255, 0, 191, 255), (255, 250, 0, 255), (0, 72, 255, 255), (255, 0, 40, 255), (151, 255, 0, 255), (0, 83, 255, 255), (108, 255, 0, 255)]
    
    def get_value_from_cm(color, cmap, colrange):
        color = np.array(color)/255. 
        r = np.linspace(colrange[0], colrange[1], 256) 
        norm = matplotlib.colors.Normalize(colrange[0], colrange[1])
        mapvals = cmap(norm(r))[:, :4] # there are 4 channels: r,g,b,a
        distance = np.sum((mapvals - color) ** 2, axis=1)
        return r[np.argmin(distance)]
    
    decoded_colors = []
    for i in range(10):
        decoded_colors.append(get_value_from_cm(c[i], cm.gist_rainbow_r, colrange=[minima, maxima]))
    print(decoded_colors)
    
    0 讨论(0)
提交回复
热议问题