mathplotlib imshow сложный 2D массив

есть ли хороший способ построить 2D-массив комплексных чисел как изображение в mathplotlib ?

имеет смысл отображать величину комплексного числа как "яркость" или "насыщенность" и фазу как "оттенок" (в любом случае оттенок-это не что иное, как фаза в цветовом пространстве RBG). http://en.wikipedia.org/wiki/HSL_and_HSV

но, насколько я знаю, imshow принимает только скалярные значения, которые затем отображаются с использованием некоторой цветовой шкалы. Нет ничего лучше ploting реальные фотографии RGB?

I вещь было бы легко просто реализовать версию, которая принимает 2D-массив кортежей (векторов) из 3 чисел с плавающей запятой или ndarray поплавков формы [:,:,3]. Я думаю, что это будет вообще usefful функция. Это было бы также полезно для построения реальных цветных изображений RGB, таких как текстуры, выводимые из OpenCL

4 ответов


это делает почти то же самое из @Hooked кода, но гораздо быстрее.

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

библиотека mpmath использует matplotlib для получения красивых изображений на комплексной плоскости. На комплексной плоскости вы обычно заботитесь о полюсах, поэтому аргумент функции дает цвет (следовательно, полюса сделают спираль). Области чрезвычайно больших или малых значений контролируются насыщением. Из документов:

по умолчанию сложный аргумент (фаза) отображается как цвет (оттенок) и величина показана как яркость. Вы также можете поставляем пользовательская функция цвета (цвета). Эта функция должна принимать комплексное число как входной сигнал и возвращает RGB 3-кортеж, содержащий плавает в диапазоне 0.0-1.0.

пример:

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

enter image description here

другой пример, показывающий дзета-функцией, тривиальные нули и критической полосе:

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

enter image description here


адаптация кода построения из mpmath вы можете построить массив numpy даже если вы не знаете исходную функцию С numpy и matplotlib. Если вы знаете функцию, см. мой оригинальный ответ используя mpmath.cplot.

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

отсюда вы можете построить произвольный сложный массив 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


вы можете использовать matplotlib.цвета.hsv_to_rgb вместо colorsys.hls_to_rgb, что примерно в 10 раз быстрее! смотрите результаты ниже:

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

вот метод выбранного ответа @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

тестирование результатов из двух методов с помощью 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"

этот результат на моем старом ноутбуке:

Complex2HSV method: 0.250999927521 s
colorize method: 2.03200006485 s