我想在复杂平面中构建NxN网格,并根据某些规则f(z)为此网格中的每个点z指定RGB颜色。
例如,网格z是
x,y = numpy.ogrid[-1:1:N*1j,-1:1:N*1j]
z = x+y*1j
,函数setcolor()是
def setcolor(z):
return (r,g,b) triple of z according to some rule
当我要用numpy的frompyfunc()显示f(z)的图像时,我的问题出现了:
img = numpy.frompyfunc(setcolor,1,1)(z).astype(np.float)
plt.imshow(img)
plt.show()
生成的图像全是蓝色(默认为colormap'jet'),没有错误也没有警告,所以显然imshow()已将所有(r,g,b)三元组转换为单个浮点数(或者0) )。我想这是因为astype(np.float)选项,但似乎这是唯一合理的选择。
当然可以使用两个for循环来显示img:
for i in range(N):
for j in range(N):
img[i,j] = f(z[i,j])
但这不是很有效(我自己的意见)。我想直接使用fromptfunc()。
那我怎么用frompyfunc()显示这个图像?
答案 0 :(得分:0)
In [588]: x,y=np.ogrid[-1:1:5*1j,-1:1:5*1j]
In [589]: z=x*y*1j
In [590]: def setcolor(z):
return (z.real,z.imag,np.abs(z))
.....:
In [591]: fn=np.frompyfunc(setcolor,1,1)
In [592]: fn(z)
Out[592]:
array([[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None]], dtype=object)
使用.astype(float)
变为0的数组。这里setcolor
只是从复杂输入中获取3个数字的简单方法。你可以选择更现实的东西。
但如果我们给它正确的out
计数,我们会得到一个数组元组。
In [593]: fn=np.frompyfunc(setcolor,1,3)
In [594]: fn(z)
Out[594]:
(array([[0.0, 0.0, -0.0, -0.0, -0.0],
[0.0, 0.0, -0.0, -0.0, -0.0],
[-0.0, -0.0, 0.0, 0.0, 0.0],
[-0.0, -0.0, 0.0, 0.0, 0.0],
[-0.0, -0.0, 0.0, 0.0, 0.0]], dtype=object),
array([[1.0, 0.5, 0.0, -0.5, -1.0],
[0.5, 0.25, 0.0, -0.25, -0.5],
[0.0, 0.0, 0.0, 0.0, 0.0],
[-0.5, -0.25, 0.0, 0.25, 0.5],
[-1.0, -0.5, 0.0, 0.5, 1.0]], dtype=object),
array([[1.0, 0.5, 0.0, 0.5, 1.0],
[0.5, 0.25, 0.0, 0.25, 0.5],
[0.0, 0.0, 0.0, 0.0, 0.0],
[0.5, 0.25, 0.0, 0.25, 0.5],
[1.0, 0.5, 0.0, 0.5, 1.0]], dtype=object))
可以使用:
将其转换为(3,N,N)数组np.array([A.astype(float) for A in fn(z)])
你必须进行转置以制作(N,N,3)阵列。
对于这个小样本,它不会更快
In [599]: timeit np.array([A.astype(float) for A in fn(z)]).transpose([1,2,0])
1000 loops, best of 3: 664 µs per loop
In [603]: %%timeit
.....: img=np.zeros((5,5,3),float)
.....: for i in range(5):
for j in range(5):
img[i,j]=setcolor(z[i,j])
.....:
1000 loops, best of 3: 316 µs per loop
在其他一些SO问题中,我发现frompyfunc
比vectorize
快,并且比直接迭代略有改进。
这更快 - 但它不能完成工作
In [606]: timeit np.frompyfunc(setcolor,1,1)(z).astype(float)
10000 loops, best of 3: 25.6 µs per loop
我选择的setcolor
可以直接获取数组z
,从而创建快速的3d数组。
In [608]: timeit np.array([A.astype(float) for A in setcolor(z)]).transpose([1,2,0])
10000 loops, best of 3: 47.1 µs per loop
来自https://stackoverflow.com/a/29703463/901925的早期回答涉及frompystack
,我发现vstack
是将元组组合成3d数组的更快方法:
In [616]: timeit np.vstack(fn(z)).astype(float).reshape(3,5,5).transpose([1,2,0])
10000 loops, best of 3: 178 µs per loop
如此正确,frompyfunc
可以在显式迭代上提供大约2倍的加速,但仍然不如直接处理数组的函数好。
答案 1 :(得分:0)
我遗漏了与主要问题分开的(rgb)元组,关于如何使用numpy
进行有效的分配。神奇的是使用meshgrid
:
import pylab as p
import numpy as np
f= lambda z : np.cos(z) # example
X = np.arange(-5, 5, 0.1)
Y = np.arange(-5, 5, 0.1)
X, Y = np.meshgrid(X, Y)
xn, yn = X.shape
W = np.zeros_like(X)
for x in range(xn):
for y in range(yn):
z = complex(X[x,y],Y[x,y])
w = float(f(z))
W[x,y] = w
p.imshow(W)