Numpy的frompyfunc()可以返回图像吗?

时间:2016-03-29 22:45:52

标签: python numpy matplotlib

我想在复杂平面中构建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()显示这个图像?

2 个答案:

答案 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问题中,我发现frompyfuncvectorize快,并且比直接迭代略有改进。

这更快 - 但它不能完成工作

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)

enter image description here