Значения диапазона для псевдоколор
У меня есть определенный массив с плавающей точкой (в Python), который может варьироваться от 0 до 100. Я хочу создать псевдоцветное изображение, чтобы цвета варьировались от зеленого (соответствует 0) до красного (100). Это похоже на pcolor из matplotlib. Однако я не хочу использовать pcolor.
Есть ли такая функция, как pseudocolorForValue(val,(minval,maxval))
которая возвращает тройку RGB, соответствующую pseudocolorForValue(val,(minval,maxval))
для val
? Кроме того, есть ли гибкость в этой функции, чтобы выбрать, отображать ли цвета от зеленого к красному или от красного к зеленому?
Спасибо ник
Ответы
Ответ 1
Вы могли бы написать свою собственную функцию, которая преобразовывала бы значения 0… 100 → 0… 120 градусов, а затем использовала это значение как Н (или угол) цвета в цветовом пространстве HSV (или HLS). Затем его можно преобразовать в цвет RGB для отображения. Линейно интерпретируемый цвет часто выглядит лучше, когда он рассчитывается в этом цветовом пространстве. Вот как выглядит цветовое пространство HSV:
![hsv colorspace diagram]()
Обновить:
Хорошая новость, я был приятно удивлен, обнаружив, что в 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)
Вот пример, показывающий, как выглядит его вывод:
![sample showing color interpolation in HSV colorspace]()
Я думаю, что вы можете найти цвета получше, чем в моем другом ответе.
Обобщая:
Можно изменить эту функцию, чтобы она была немного более общей в том смысле, что она будет работать с цветами, отличными от только красного и зеленого, которые в настоящее время жестко закодированы в нее.
Вот как это сделать:
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)))
Результаты:
![sample showing color interpolation in HSV colorspace between yellow and blue]()
Ответ 2
Хотя это, возможно, и не так красиво, как интерполяция H в цветовом пространстве HLS или HSV, гораздо проще реализовать подход, заключающийся в том, чтобы написать функцию, отображающую одно значение в три компонента, соответствующих линейно-интерполированному цвету между полностью red (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.
Вот пример, показывающий, как выглядит его вывод:
![image showing interpolation in RGB colorspace]()
Если вы хотите перейти от зеленого к красному, просто измените вычисления для 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)))
Пример вывода с использованием предоставленных цветов:
![image showing interpolation in RGB colorspace with different colors]()
Ответ 3
Вы можете напрямую получить matplolib встроенные цветовые коды, которые именно они используют для определения своей цветокоррекции. Каждая карта принимает поплавок в диапазоне [0, 1] и возвращает 4-элементный набор поплавков в диапазоне [0, 1] с компонентами (R, G, B, A). Ниже приведен пример функции, которая возвращает кортеж RGBA с использованием стандартного jet
colormap:
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 colormaps, изменив cm.jet
на cm.rainbow
, cm.nipy_spectral
, cm.Accent
и т.д.