Bisakah frompyfunc() Numpy mengembalikan gambar?

Saya ingin membuat kisi NxN di bidang kompleks, dan menetapkan setiap titik z di kisi ini warna RGB sesuai dengan beberapa aturan f(z).

Misalnya, grid z adalah

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

dan fungsinya setcolor() adalah

def setcolor(z):
    return (r,g,b) triple of z according to some rule

Masalah saya terjadi ketika saya akan menampilkan gambar f(z) dengan frompyfunc() numpy:

img = numpy.frompyfunc(setcolor,1,1)(z).astype(np.float)
plt.imshow(img)
plt.show()

Gambar yang dihasilkan semuanya berwarna biru (secara default peta warna 'jet'), tidak ada kesalahan atau peringatan, jadi jelas bahwa imshow() telah mengubah semua (r,g,b) rangkap tiga menjadi satu float mungkin 1 (atau 0). Saya kira ini karena opsi astype(np.float), tetapi tampaknya ini adalah satu-satunya pilihan yang masuk akal.

Tentu saja seseorang dapat menggunakan dua loop for untuk menampilkan img:

for i in range(N):
    for j in range(N):
        img[i,j] = f(z[i,j])

tapi ini tidak terlalu efisien (pendapat saya sendiri). Saya ingin menggunakan fromptfunc() secara langsung.

Jadi bagaimana saya bisa menampilkan gambar ini dengan frompyfunc()?


person zhaoL    schedule 29.03.2016    source sumber
comment
frompyfunc tidak akan mempercepat kode Anda ... asal tahu saja   -  person Joran Beasley    schedule 30.03.2016
comment
Seperti apa bentuk numpy.frompyfunc(setcolor,1,1)(z) (untuk N kecil)? frompyfunc, jika berfungsi, mungkin memberikan kecepatan sebanyak 2x, tetapi tidak seperti vektorisasi asli.   -  person hpaulj    schedule 30.03.2016
comment
numpy.frompyfunc tampaknya memiliki masalah dengan fungsi yang sudah mengembalikan urutan. Sepertinya itu mungkin bug NumPy. Anda mungkin sebaiknya tidak menggunakan frompyfunc.   -  person user2357112 supports Monica    schedule 30.03.2016
comment
@JoranBeasley: Saya membandingkan frompyfunc() dan for loop, yang pertama secara signifikan lebih cepat daripada yang terakhir. Mungkin ada cara lain untuk mempercepat kodenya?   -  person zhaoL    schedule 30.03.2016


Jawaban (2)


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)

yang berubah menjadi array 0 dengan .astype(float). Di sini setcolor hanyalah cara sederhana untuk mendapatkan 3 angka dari input kompleks. Anda dapat memilih sesuatu yang lebih realistis.

Namun jika kita memberikan hitungan out yang benar, kita mendapatkan serangkaian array.

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

Itu bisa diubah menjadi array (3,N,N) dengan:

np.array([A.astype(float) for A in fn(z)])

Anda harus melakukan transpose untuk membuat array (N,N,3).

Untuk sampel kecil ini, ini tidak lebih cepat

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

Dalam beberapa pertanyaan SO lainnya saya menemukan bahwa frompyfunc lebih cepat dari vectorize, dan sedikit peningkatan dibandingkan iterasi langsung.

Ini lebih cepat - tetapi tidak berhasil

In [606]: timeit np.frompyfunc(setcolor,1,1)(z).astype(float)
10000 loops, best of 3: 25.6 µs per loop

setcolor yang saya pilih dapat mengambil array z secara langsung, sehingga menghasilkan pembuatan array 3d yang cepat.

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

Dari https://stackoverflow.com/a/29703463/901925, jawaban sebelumnya yang melibatkan frompystack, saya menemukan bahwa vstack adalah cara yang lebih cepat untuk merakit Tuple menjadi array 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

Jika dilakukan dengan benar, frompyfunc dapat memberikan kecepatan sekitar 2x dibandingkan iterasi eksplisit, namun masih belum sebaik fungsi yang menangani array secara langsung.

person hpaulj    schedule 29.03.2016

Saya mengabaikan tupel (rgb) yang terpisah dari pertanyaan utama, tentang cara membuat tugas yang efisien dengan numpy. Keajaibannya ada pada penggunaan 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)

masukkan deskripsi gambar di sini

person roadrunner66    schedule 29.03.2016