2012-06-05 15 views
11

Mam pewną tablicę zmiennych (w języku Python), która może zawierać się w przedziale od 0 do 100. Chcę utworzyć obraz pseudokolorowy, aby kolory zmieniały się od zielonego (odpowiadającego 0) do czerwonego (100). Jest to podobne do pcolor z matplotlib. Jednak nie chcę używać pcolor.Zakres wartości do pseudokoloru

Czy istnieje funkcja taka jak pseudocolorForValue (val, (minval, maxval)), która zwraca potrójny RGB odpowiadający wartości pseudokoloru dla "val"? Czy istnieje także elastyczność w tej funkcji, aby wybrać wyświetlanie kolorów od zielonego do czerwonego lub od czerwonego do zielonego?

Dzięki, Nik

Odpowiedz

15

można napisać własną funkcję, która przekształca wartości 0 ... 100 => 0 ... 120 stopni, a następnie wykorzystywane tę wartość jako H (lub kąt) z kolorem w przestrzeni kolorów HSV (lub HLS). Następnie można go przekonwertować na kolor RGB w celu wyświetlania. Liniowo interpretować kolor często wyglądają lepiej, gdy są obliczane w tym kolorów: Oto co HSV colorspace wygląda następująco:

hsv colorspace diagram

Aktualizacja:

Dobre wieści, byłem mile zaskoczony, aby dowiedzieć się, że Python posiada procedury konwersji przestrzeni kolorów w swoim wbudowanym module colorsys (w rzeczywistości oznaczają one "baterie w zestawie"). Co znajduje się ładny o to, że to sprawia, że ​​tworzenie funkcji, która ma co opisałem dość łatwe, jak pokazano poniżej:

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

wyjściowa:

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) 

Oto przykład pokazujący co jego wyjście wygląda następująco:

sample showing color interpolation in HSV colorspace

Myślę, że możesz znaleźć kolory generowane ładniej niż w mojej drugiej odpowiedzi.

Uogólniając:

Jest możliwe, aby zmodyfikować tę funkcję, aby być trochę bardziej ogólny w tym sensie, że będzie pracować z kolorami innych potem po prostu czerwony i zielony obecnie sztywno do niego.

Oto jak to zrobić:

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

Wyniki:

sample showing color interpolation in HSV colorspace between yellow and blue

+0

Dzięki. Interesująca sugestia. Choć trudno jest uwierzyć, że funkcja taka jak ta, której potrzebuję, nie jest już wbudowana w Pythonie. After, pcolor w matplotlib robi to samo. A więc musi jakoś wywoływać taką funkcję. Czy wiesz o takiej funkcji? – Nik

+0

@Nik: Nie, nie jestem świadomy wbudowanego, i szczerze mówiąc, nie jestem zaskoczony, że nie ma takiego - jest to specyficzne dla danej domeny. Jedyną nie banalną częścią jest konwersja kolorów, którą powinieneś znaleźć w podstawowej książce komputerowej lub [online] (http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB). Prawdopodobnie jest dostępny pakiet graficzny o otwartym kodzie źródłowym z takim narzędziem, którego możesz użyć. – martineau

+0

@Nik: Python ma wbudowane funkcje konwersji przestrzeni kolorów - zobacz moją aktualizację tej odpowiedzi. – martineau

5

Choć zapewne nie tak ładna jak interpolację H w przestrzeni kolorów HLS lub HSV, o wiele prostsze do wdrożenia podejście byłoby należy napisać funkcję odwzorowującą pojedynczą wartość na trzy komponenty odpowiadające liniowo interpolowanym kolorom między całkowicie red (1,0,0) i całkowicie zielonym (0,1,0) w zakresie kolorów rgb ce.

Oto co mam na myśli:

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

wyjściowa:

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) 

można przekształcić zmiennoprzecinkowych R, G, B komponenty potrzebne, takie jak na liczby całkowite w zakresie od 0 ..255.

Oto przykład pokazujący co jego wyjście wygląda następująco:

image showing interpolation in RGB colorspace

Jeśli chcesz iść z zielonego na czerwony, po prostu odwrócić obliczenia dla r i g w funkcji. Bez zbytniego dodatkowego wysiłku można uogólnić koncepcję, aby umożliwić liniową interpolację między dowolnymi dwoma określonymi kolorami.

Oto w jaki sposób można zrobić:

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

Przykładowe wyjście przy użyciu dostarczonych kolory:

image showing interpolation in RGB colorspace with different colors

+0

Dzięki @martineau. To naprawdę pomogło! – Nik

2

można uzyskać dostęp matplolib's built-in colormaps bezpośrednio, które są dokładnie co pcolor używa do określenia jej colormapping . Każda mapa przyjmuje wartość zmiennoprzecinkową w zakresie [0, 1] i zwraca 4 elementową krotność wartości zmiennoprzecinkowych z zakresu [0, 1] z komponentami (R, G, B, A). Oto przykład funkcji, która zwraca krotki RGBA użyciu standardowego 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) 

Byłoby map do zakresu kolorów pokazane na obrazku poniżej.

enter image description here

Jednym z wygodnych funkcji dotyczących tej metody jest to, że można łatwo przełączać się do któregokolwiek z matplotlib colormaps zmieniając cm.jet do cm.rainbow, cm.nipy_spectral, cm.Accent itp

+0

To zasługuje na więcej awansów. Tak, korzysta z biblioteki matplotlib, ale jest to krótkie i elastyczne rozwiązanie. – medley56

Powiązane problemy