2013-06-11 22 views
5

Czy jest jakiś dobry sposób, jak wykreślić tablicę 2D liczb złożonych jako obraz w mathplotlib?mathplotlib imshow złożona tablica 2D

Wielkie znaczenie ma odwzorowanie wielkości liczby zespolonej jako "jasności" lub "nasycenia" i fazy jako "barwy" (w każdym razie odcień jest niczym innym jak fazą w przestrzeni kolorów RBG). http://en.wikipedia.org/wiki/HSL_and_HSV

Ale o ile mi wiadomo, przyjmuje tylko wartości skalarne, które są następnie mapowane za pomocą niektórych kolorów skali. Nie ma nic lepszego niż kreślenie prawdziwych zdjęć RGB?

Rzeczą, że byłoby łatwo po prostu zaimplementować wersję, która akceptuje tablicę 2D krotek (wektorów) z 3 liczb zmiennoprzecinkowych lub ndarray pływaków o kształcie [:,:, 3]. Myślę, że byłaby to funkcja usefful. Byłoby to również użyteczne w wykreślaniu rzeczywistych obrazów colord RGB, takich jak tekstury wygenerowane z OpenCL

+0

Zobacz tę odpowiedź r dla innego pytania: http://stackoverflow.com/a/17113417/907575 –

Odpowiedz

4

ten ma prawie taki sam kod @Hooked ale bardzo dużo szybciej.

import numpy as np 
from numpy import pi 
import pylab as plt 
from colorsys import hls_to_rgb 

def colorize(z): 
    r = np.abs(z) 
    arg = np.angle(z) 

    h = (arg + pi)/(2 * pi) + 0.5 
    l = 1.0 - 1.0/(1.0 + r**0.3) 
    s = 0.8 

    c = np.vectorize(hls_to_rgb) (h,l,s) # --> tuple 
    c = np.array(c) # --> array of (3,n,m) shape, but need (n,m,3) 
    c = c.swapaxes(0,2) 
    return c 

N=1000 
x,y = np.ogrid[-5:5:N*1j, -5:5:N*1j] 
z = x + 1j*y 

w = 1/(z+1j)**2 + 1/(z-2)**2 
img = colorize(w) 
plt.imshow(img) 
plt.show() 
7

Biblioteka, aby uzyskać piękne obrazy złożonej płaszczyzny. Na złożonej płaszczyźnie zazwyczaj dbasz o bieguny, więc argument funkcji nadaje kolor (stąd bieguny zrobią spiralę). Regiony o bardzo dużych lub małych wartościach są kontrolowane przez nasycenie. Z dokumentów:

domyślnie kompleks argument (fazy) jest pokazany jako kolor (Hue) i wielkość jest pokazanie jak jasność. Możesz także dostarczyć niestandardową funkcję koloru (kolor). Ta funkcja powinna przyjmować liczbę zespoloną jako wejście i zwracać 3-krotny krąg RGB zawierający pływów w zakresie 0.0-1.0.

przykład:

import mpmath 
mpmath.cplot(mpmath.gamma, points=100000) 

enter image description here

Innym przykładem przedstawiającym zeta function, trywialne zera i critical strip:

import mpmath 
mpmath.cplot(mpmath.zeta, [-45,5],[-25,25], points=100000) 

enter image description here

+0

To wygląda ładnie, jednak jest to tylko do kreślenia funkcji, w których znam receptę analytinc. To nie jest moja sprawa. Potrzebuję czegoś do wykreślenia złożonych danych przy pomocy próbkowania dicrete, które czytam z pliku tekstowego i zapisuję w 2D. Nie mam wyraźnej recepty funkcjonalnej dla tych danych, które mogłyby być próbkowane w dowolnym punkcie. –

5

Dostosowując kod kreślenia z mpmath możesz wykreślić tablicę numpy , nawet jeśli nie znasz oryginalnej funkcji z numpy i matplotlib. Jeśli znasz tę funkcję, see my original answer używającużywając.

from colorsys import hls_to_rgb 

def colorize(z): 
    n,m = z.shape 
    c = np.zeros((n,m,3)) 
    c[np.isinf(z)] = (1.0, 1.0, 1.0) 
    c[np.isnan(z)] = (0.5, 0.5, 0.5) 

    idx = ~(np.isinf(z) + np.isnan(z)) 
    A = (np.angle(z[idx]) + np.pi)/(2*np.pi) 
    A = (A + 0.5) % 1.0 
    B = 1.0 - 1.0/(1.0+abs(z[idx])**0.3) 
    c[idx] = [hls_to_rgb(a, b, 0.8) for a,b in zip(A,B)] 
    return c 

Stąd można wykreślić dowolną tablicę złożoną numpy:

N = 1000 
A = np.zeros((N,N),dtype='complex') 
axis_x = np.linspace(-5,5,N) 
axis_y = np.linspace(-5,5,N) 
X,Y = np.meshgrid(axis_x,axis_y) 
Z = X + Y*1j 

A = 1/(Z+1j)**2 + 1/(Z-2)**2 

# Plot the array "A" using colorize 
import pylab as plt 
plt.imshow(colorize(A), interpolation='none',extent=(-5,5,-5,5)) 
plt.show() 

enter image description here

+0

dziękuję bardzo! Jest dość powolny, więc byłoby lepiej, gdyby istniała taka funkcja bezpośrednio zakodowana numpy (mam na myśli coś przyspieszonego w ten sam sposób, co inne operacje tablicowe w numpy - bez iteracji po tablicy przez pętlę Pythona). Ale ważne jest to, że działa. –

+0

@ProkopHapala Właściwie większość pracy wykonuje się z numpy, z wyjątkiem wywołania 'hls_to_rgb', które prawdopodobnie można wektoryzować. Możesz zrobić to o wiele szybciej dzięki zmianie liczby punktów "N", prędkość powinna być proporcjonalna do N^2. – Hooked

3

Można użyć matplotlib.colors.hsv_to_rgb zamiast colorsys.hls_to_rgb, który jest około 10 razy szybciej!patrz poniższe wyniki:

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

def Complex2HSV(z, rmin, rmax, hue_start=90): 
    # get amplidude of z and limit to [rmin, rmax] 
    amp = np.abs(z) 
    amp = np.where(amp < rmin, rmin, amp) 
    amp = np.where(amp > rmax, rmax, amp) 
    ph = np.angle(z, deg=1) + hue_start 
    # HSV are values in range [0,1] 
    h = (ph % 360)/360 
    s = 0.85 * np.ones_like(h) 
    v = (amp -rmin)/(rmax - rmin) 
    return hsv_to_rgb(np.dstack((h,s,l))) 

oto sposób odebrał odpowiedź przez @nadapez:

from colorsys import hls_to_rgb 
def colorize(z): 
    r = np.abs(z) 
    arg = np.angle(z) 

    h = (arg + np.pi)/(2 * np.pi) + 0.5 
    l = 1.0 - 1.0/(1.0 + r**0.3) 
    s = 0.8 

    c = np.vectorize(hls_to_rgb) (h,l,s) # --> tuple 
    c = np.array(c) # --> array of (3,n,m) shape, but need (n,m,3) 
    c = c.swapaxes(0,2) 
    return c 

Testowanie wyniki z dwóch metod z 1024 * 1024 2darray:

N=1024 
x, y = np.ogrid[-4:4:N*1j, -4:4:N*1j] 
z = x + 1j*y 

t0 = time.time() 
img = Complex2HSV(z, 0, 4) 
t1 = time.time() 
print "Complex2HSV method: "+ str (t1 - t0) +" s" 

t0 = time.time() 
img = colorize(z) 
t1 = time.time() 
print "colorize method: "+ str (t1 - t0) +" s" 

Ten wynik na moim starym laptopie:

Complex2HSV method: 0.250999927521 s 
colorize method: 2.03200006485 s