有没有什么好的方法如何在Mathplotlib中将复数的二维数组绘制成图像?
将复数的大小映射为“亮度”或“饱和度”并将相位映射为“Hue”非常有意义(无论如何Hue只不过是RBG色彩空间中的相位)。 http://en.wikipedia.org/wiki/HSL_and_HSV
但据我所知,imshow只接受标量值,然后使用某些色阶进行映射。没有什么比投影真实的RGB图片更好的了吗?
我觉得很容易实现一个版本,它接受3个浮点数的元组(向量)的二维数组或形状浮点数的ndarray [:,:,3]。我想这通常是usefful功能。它也可用于绘制真实的RGB colord图像,例如从OpenCL输出的纹理
答案 0 :(得分:7)
图书馆mpmath
使用matplotlib
制作复杂平面的精美图像。在复杂的平面上,你通常关心极点,因此函数的参数给出了颜色(因此极点会产生螺旋)。极大或极小值的区域由饱和度控制。来自文档:
默认情况下,复杂参数(阶段)显示为颜色(色调)和 幅度显示为亮度。你也可以提供 自定义颜色功能(颜色)。这个功能应该采取 复数作为输入并返回包含的RGB 3元组 漂浮在0.0-1.0范围内。
示例:
import mpmath
mpmath.cplot(mpmath.gamma, points=100000)
另一个示例显示zeta function,琐碎的零和critical strip:
import mpmath
mpmath.cplot(mpmath.zeta, [-45,5],[-25,25], points=100000)
答案 1 :(得分:7)
调整mpmath
的绘图代码,即使您不知道原始函数,也可以使用numpy和matplotlib绘制一个numpy数组。如果您确实使用mpmath.cplot
知道该功能see my original answer。
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()
答案 2 :(得分:6)
这与@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()
答案 3 :(得分:3)
您可以使用matplotlib.colors.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
答案 4 :(得分:0)
您也可以使用 PIL.image 进行转换
import PIL.Image
def colorize(z):
z = Zxx
n,m = z.shape
A = (np.angle(z) + np.pi) / (2*np.pi)
A = (A + 0.5) % 1.0 * 255
B = 1.0 - 1.0/(1.0+abs(z)**0.3)
B = abs(z)/ z.max() * 255
H = np.ones_like(B)
image = PIL.Image.fromarray(np.stack((A, B, np.full_like(A, 255)), axis=-1).astype(np.uint8), "HSV") # HSV has range 0..255 for all channels
image = image.convert(mode="RGB")
return np.array(image)