Создать градиентную цветовую карту - matplotlib - PullRequest
0 голосов
/ 13 декабря 2018

Я пытаюсь создать colormap, градиент от dark red до очень light green/white.Я приведу пример вывода в виде скриншота ниже.

enter image description here

Я поиграл со следующим code:

from matplotlib import pyplot as plt
import matplotlib 
import numpy as np

plt.figure()
a=np.outer(np.arange(0,1,0.01),np.ones(100))
cdict2 = {'red':   [(0.0,  0.1, 0.2),
                   (0.3,  0.4, 0.5),
                   (0.5,  0.5, 0.5),
                   (1.0,  1.0, 1.0)],
         'green': [(0.0,  0.0, 0.0),
                  (0.5, 0.5, 0.5),
                  (0.75, 1.0, 1.0),
                  (1.0,  1.0, 1.0)],
         'blue':  [(0.0,  0.0, 0.0),
                  (0.0,  0.0, 0.0),
                  (1.0,  1.0, 1.0)]} 
my_cmap2 = matplotlib.colors.LinearSegmentedColormap('my_colormap2',cdict2,256)
plt.imshow(a,aspect='auto', cmap =my_cmap2)                   
plt.show()

Но я не могу заставить его повторить прикрепленный colormap.Я также не уверен, что может быть более эффективный способ добиться этого?

Текущий вывод: я манипулировал значениями, чтобы попытаться получить gradient для репликации прикрепленного colormap.Но я не могу получить red-orange-yellow-green gradient правильный

enter image description here

Ответы [ 3 ]

0 голосов
/ 13 декабря 2018

Вы можете загрузить изображение, которое у вас уже есть, и создать из него цветовую карту.К сожалению, изображение имеет белые рамки - их нужно сначала обрезать.

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np

cim = plt.imread("https://i.stack.imgur.com/4q2Ev.png")
cim = cim[cim.shape[0]//2, 8:740, :]

cmap = mcolors.ListedColormap(cim)


data = np.random.rand(10,10)
plt.imshow(data, cmap=cmap)
plt.colorbar()
plt.show()

enter image description here

0 голосов
/ 14 декабря 2018

Поскольку вы пытаетесь эмулировать существующий градиент, а не создаете его из произвольных цветов, просто становится вопросом поиска формулы, которая соответствует измеренным значениям градиента.

Начните с взятия среднего пикселя rзначения g, b в каждой точке градиента.Сначала вам нужно получить чистое изображение, у того, что вы разместили, есть белая рамка и некоторые звуки по краям;Я использовал редактор изображений, чтобы очистить это.

После того, как вы измерили значения, вы можете использовать numpy.polyfit, чтобы сделать подгонку кривой.Я предположил, что для хорошей подгонки достаточно 5 градусов, получив массив из 6 коэффициентов.Здесь вы можете увидеть график измеренных значений с наложенной кривой.Очень хорошее совпадение, я бы сказал.

R,G,B measured values and curve fit

А вот код для воссоздания градиента с использованием этих кривых.

rp = [-1029.86559098,  2344.5778132 , -1033.38786418,  -487.3693808 ,
         298.50245209,   167.25393272]
gp = [  551.32444915, -1098.30287507,   320.71732031,   258.50778539,
         193.11772901,    30.32958789]
bp = [  222.95535971, -1693.48546233,  2455.80348727,  -726.44075478,
         -69.61151887,    67.591787  ]

def clamp(n):
    return min(255, max(0, n))

def gradient(x, rfactors, gfactors, bfactors):
    '''
    Return the r,g,b values along the predefined gradient for
    x in the range [0.0, 1.0].
    '''
    n = len(rfactors)
    r = clamp(int(sum(rfactors[i] * (x**(n-1-i)) for i in range(n))))
    g = clamp(int(sum(gfactors[i] * (x**(n-1-i)) for i in range(n))))
    b = clamp(int(sum(bfactors[i] * (x**(n-1-i)) for i in range(n))))
    return r, g, b

from PIL import Image
im = Image.new('RGB', (742, 30))
ld = im.load()
for x in range(742):
    fx = x / (742 - 1)
    for y in range(30):
        ld[x,y] = gradient(fx, rp, gp, bp)

new gradient

0 голосов
/ 13 декабря 2018

С это другой ответ:

from matplotlib import pyplot as plt
import matplotlib 
import numpy as np
import matplotlib.colors as colors

def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=100):
    new_cmap = colors.LinearSegmentedColormap.from_list(
        'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval),
        cmap(np.linspace(minval, maxval, n)))
    return new_cmap

arr = np.linspace(0, 50, 100).reshape((10, 10))
fig, ax = plt.subplots(ncols = 2)

new_cmap1 = truncate_colormap(plt.get_cmap('jet'), 0.45, 1.0)
new_cmap2 = truncate_colormap(plt.get_cmap('brg'), 1.0, 0.45)

ax[0].imshow(a,aspect='auto', cmap = new_cmap1)
ax[1].imshow(a,aspect='auto', cmap = new_cmap2)
plt.show()

enter image description here

...