Нелинейное масштабирование цветовой карты для усиления контраста - PullRequest
8 голосов
/ 27 июня 2011

Следующий код Python создает тепловую карту матрицы, которая содержит нормально распределенные значения

import numpy as np
from matplotlib import pylab as plt


np.random.seed(123) #make sure we all have same data
m = np.random.randn(200).reshape(10, 20)
plt.imshow(m, cmap='RdYlGn', interpolation='nearest')
plt.colorbar()

Это вывод этого кода

example 1

Я бы хотел повысить контрастность этого изображения, «затухая» значениями, близкими к нулю. Я могу легко сделать это, используя дисгмоидальное масштабирование исходных данных следующим образом:

def disigmoidScaling(values, steepnessFactor=1, ref=None):
    ''' Sigmoid scaling in which values around a reference point are flattened
    arround a reference point

    Scaled value y is calculated as 
        y = sign(v - d)(1 - exp(-((x - d)/s)**2)))
    where v is the original value,  d is the referenc point and s is the 
    steepness factor
    '''
    if ref is None:
        mn = np.min(values)
        mx = np.max(values)
        ref = mn + (mx - mn) / 2.0

    sgn = np.sign(values - ref)
    term1 = ((values - ref)/steepnessFactor) ** 2
    term2 = np.exp(- term1) 
    term3 = 1.0 - term2 
    return sgn * term3


plt.imshow(disigmoidScaling(m, 4), cmap='RdYlGn', interpolation='nearest')
plt.colorbar()

Вот вывод.

example 2

Результатом доволен, кроме того, что в этой версии оригинал значения были обменены на масштабированные.

Есть ли способ выполнить нелинейное отображение значений в цветовую карту?

1 Ответ

4 голосов
/ 27 июня 2011

Цветовая карта содержит словарь значений красного, зеленого и синего, отображенных на интервале [0,1]. Документы класса Linear Segmented Colormap дают пример

cdict = {'red':   [(0.0,  0.0, 0.0),
               (0.5,  1.0, 1.0),
               (1.0,  1.0, 1.0)],

     'green': [(0.0,  0.0, 0.0),
               (0.25, 0.0, 0.0),
               (0.75, 1.0, 1.0),
               (1.0,  1.0, 1.0)],

     'blue':  [(0.0,  0.0, 0.0),
               (0.5,  0.0, 0.0),
               (1.0,  1.0, 1.0)]}

"Каждая строка в таблице для данного цвета представляет собой последовательность кортежей x, y0, y1. В каждой последовательности x должно монотонно увеличиваться от 0 до 1. Для любого входного значения z, попадающего между x [i] и x [i + 1], выходное значение данного цвета будет линейно интерполировано между y1 [i] и y0 [i + 1]: "

Цветовая карта RdYlGn имеет 11 значений x для каждого цвета с шагом от 0 до 1,0 с шагом 0,1. Вы можете получить значения cdict, вызвав

plt.cm.RdYlGn._segmentdata

Затем вы можете изменить значения x на любые нужные вам шаги (при условии, что они монотонно растут и находятся в диапазоне от 0 до 1), и получить новую цветовую карту, вызвав matplotlib.colors.LinearSegmentedColormap на вашем новом cdict. Есть несколько замечательных примеров этого в Matplotlib Cookbook .

...