2013-06-11 38 views
5

Có cách nào tốt để vẽ mảng 2D của các số phức như hình ảnh trong mathplotlib? Nó làm cho rất nhiều ý nghĩa để bản đồ độ lớn của số phức là "độ sáng" hoặc "bão hòa" và giai đoạn là "Huế" (anyway Huế là không có gì khác hơn là giai đoạn trong không gian màu RBG). http://en.wikipedia.org/wiki/HSL_and_HSVmathplotlib imshow mảng 2D phức tạp

Nhưng theo như tôi biết imshow chỉ chấp nhận các giá trị vô hướng sau đó được ánh xạ bằng cách sử dụng một số màu sắc. Không có gì giống như vẽ hình ảnh RGB thực sự? Tôi có thể dễ dàng thực hiện một phiên bản chấp nhận mảng 2D của các bộ dữ liệu (vectơ) của 3 số dấu phẩy động hoặc các biến dạng float của hình dạng [:,:, 3]. Tôi đoán đây sẽ là tính năng thường sử dụng. Nó cũng hữu ích cho việc vẽ sơ đồ hình ảnh màu RGB thực, chẳng hạn như kết cấu được xuất từ ​​OpenCL

+0

Xem câu trả lời này r cho một câu hỏi khác: http://stackoverflow.com/a/17113417/907575 –

Trả lời

4

này không gần như giống nhau của mã @Hooked nhưng nhanh hơn rất nhiều.

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

Thư viện mpmath sử dụng matplotlib để tạo ra hình ảnh đẹp của mặt phẳng phức tạp. Trên mặt phẳng phức tạp, bạn thường quan tâm đến các cực, do đó, đối số của hàm cho màu sắc (do đó các cực sẽ tạo ra một hình xoắn ốc). Các vùng có giá trị cực lớn hoặc nhỏ được điều khiển bởi độ bão hòa. Từ tài liệu:

Theo mặc định, đối số phức (giai đoạn) được hiển thị dưới dạng màu (màu) và độ lớn được hiển thị là độ sáng. Bạn cũng có thể cung cấp chức năng màu tùy chỉnh (màu). Hàm này cần có một số phức là làm đầu vào và trả về một bộ ba RGB chứa nổi trong phạm vi 0.0-1.0.

Ví dụ:

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

enter image description here

Một ví dụ khác cho thấy zeta function, các số không tầm thường và critical strip:

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

enter image description here

+0

Điều này có vẻ tốt đẹp, tuy nhiên nó chỉ cho âm mưu chức năng mà tôi biết toa thuốc analytinc. Nó không phải là trường hợp của tôi. Tôi cần một cái gì đó để vẽ dữ liệu phức tạp với lấy mẫu dicrete mà tôi đọc từ tập tin văn bản và lưu trữ trong tường thuật 2D. Tôi không có đơn thuốc chức năng rõ ràng cho dữ liệu này có thể được lấy mẫu ở bất kỳ thời điểm nào. –

5

Điều chỉnh mã vạch từ mpmath, bạn có thể vẽ một mảng có khối u ngay cả khi bạn không biết hàm gốc với numpy và matplotlib. Nếu bạn biết chức năng, see my original answer sử dụng 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 

Từ đây, bạn có thể vẽ một phức tạp mảng NumPy tùy ý:

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

+0

cảm ơn bạn rất nhiều! Nó là khá chậm, vì vậy nó sẽ là tốt hơn nếu có sẽ được như vậy chức năng trực tiếp hardcoded numpy (tôi có nghĩa là một cái gì đó tăng tốc trong cùng một cách như các hoạt động mảng trong numpy - mà không iterating qua mảng bởi python loop). Nhưng điều quan trọng là nó hoạt động. –

+0

@ProkopHapala Trên thực tế hầu hết các công việc _is_ thực hiện với numpy, ngoại trừ các cuộc gọi đến 'hls_to_rgb' mà bạn có thể có thể vectorize. Bạn có thể làm cho nó _much much_ nhanh hơn bằng cách thay đổi số điểm 'N', tốc độ phải tỷ lệ thuận với N^2. – Hooked

3

Bạn có thể sử dụng matplotlib.colors.hsv_to_rgb thay vì colorsys.hls_to_rgb, đó là nhanh hơn khoảng 10 lần!xem kết quả dưới đây:

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

đây là phương pháp của câu trả lời chọn bởi @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 

kiểm tra các kết quả từ hai phương pháp với 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" 

Kết quả này trên máy tính xách tay cũ của tôi:

Complex2HSV method: 0.250999927521 s 
colorize method: 2.03200006485 s 
Các vấn đề liên quan