2012-04-05 16 views
22

200x200 boyutlarında bir numpy dizisi oluşturmak ve içine 100, 100 koordinatlar, yarıçap 80 ve 3 piksellik strok genişliğine ortalanmış bir daire oluşturmak istiyorum. Dosya işlemleri dahil etmeden python 2.7'de bunu nasıl yapabilirim? Başka şekillerde genellemeye izin vermek için geometri veya görüntüleme kütüphaneleri kullanılabilir.Basit geometrik şekilleri numpy dizileri içine nasıl yazılır

cevap

17

Cairo modern, esnek ve hızlı 2D grafik kütüphanesi dahil varsayılan görüntü formatı

olarak numpy diziler oluşturmak. Bu Python bindings sahip NumPy dizilerine dayalı "yüzeyler" oluşturmasına olanak sağlar: çemberin rastgele fragmanını gösteren

import numpy 
import cairo 
import math 
data = numpy.zeros((200, 200, 4), dtype=numpy.uint8) 
surface = cairo.ImageSurface.create_for_data(
    data, cairo.FORMAT_ARGB32, 200, 200) 
cr = cairo.Context(surface) 

# fill with solid white 
cr.set_source_rgb(1.0, 1.0, 1.0) 
cr.paint() 

# draw red circle 
cr.arc(100, 100, 80, 0, 2*math.pi) 
cr.set_line_width(3) 
cr.set_source_rgb(1.0, 0.0, 0.0) 
cr.stroke() 

# write output 
print data[38:48, 38:48, 0] 
surface.write_to_png("circle.png") 

Bu kod yazdırılır

[[255 255 255 255 255 255 255 255 132 1] 
[255 255 255 255 255 255 252 101 0 0] 
[255 255 255 255 255 251 89 0 0 0] 
[255 255 255 255 249 80 0 0 0 97] 
[255 255 255 246 70 0 0 0 116 254] 
[255 255 249 75 0 0 0 126 255 255] 
[255 252 85 0 0 0 128 255 255 255] 
[255 103 0 0 0 118 255 255 255 255] 
[135 0 0 0 111 255 255 255 255 255] 
[ 1 0 0 97 254 255 255 255 255 255]] 

. Aynı zamanda bu PNG oluşturur:

Red circle

+0

güncellemesi için teşekkürler Ben gri tonlamalı (8bit) veri ile çalıştığım için Aşağıdakileri kullanıyorum: \ data = numpy.zeros ((200, 200), dtype = numpy.uint8) \ yüzey = cairo.ImageSurface.create_for_data (veri, cairo.FORMAT_A8, 200, 200) \ #to % 50 gri bir yüzeye boya (alfa değeri kullanılır) \ cr.set_source_rgba (0, 0, 0, 0,5) – a1an

+0

Bu örnek cairocffi kitaplığı ile herhangi birini kullanmaya çalışıyorsa, işe yaramaz. İşte cairocffi repo hakkında daha fazla ayrıntıya giren bir konu: https: // github.com/Kozea/cairocffi/issues/51 – neelshiv

6

opencv yeni piton bağlamaları import cv2 Onlar drawing functions

+0

çıktı diziler Ne biçim olurdu? Sadece bir koordinat listesi mi yoksa ikili bir kılavuz mu? –

+0

Bu bir resim = yani genellikle bir 2d numpy dizi, onlar üzerinde tüm normal numpy işlemleri yapabilirsiniz ve herhangi bir resim biçiminde kaydedebilirsiniz –

+0

Harika, @Martin –

31

zamanki gibi bir örgü koordine ve şeklin denklemlerini uygulamak tanımlamaktır. En kolay yolu numpy.mgrid kullanmak olduğunu yapmak için:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.mgrid.html

# xx and yy are 200x200 tables containing the x and y coordinates as values 
# mgrid is a mesh creation helper 
xx, yy = numpy.mgrid[:200, :200] 
# circles contains the squared distance to the (100, 100) point 
# we are just using the circle equation learnt at school 
circle = (xx - 100) ** 2 + (yy - 100) ** 2 
# donuts contains 1's and 0's organized in a donut shape 
# you apply 2 thresholds on circle to define the shape 
donut = numpy.logical_and(circle < (6400 + 60), circle > (6400 - 60)) 
+0

Numpy'nin bunu yapabileceğini asla bilemedim! –

+2

@MartinBeckett mgrid, bir dizi değer üzerindeki fonksiyonları değerlendirmenizi sağlar. 2 boyut ile sınırlı değilsiniz. Yan not – Simon

+2

I 'halka = (daire <(6400 + 60)) (daire> (6400-60)) bulmak 'biraz daha okunabilir açık' logical_and' arama daha. Yine de kişisel tercih meselesi. Tam olarak eşdeğer. (Ve' geçersiz kılınamaz 'ederken' & 'olsa, numpy.logical_and'' arayacak unutmayın.) Keyfi fonksiyonlar "çizilmiş" izin verir çünkü çok ince ve kullanışlı –

2

başka olasılık scikit-image kullanmaktır. Boşluk için circle_perimeter veya tam daire için circle kullanabilirsiniz.

Öyle gibi tek vuruş daire çizin edebilirsiniz:

import matplotlib.pyplot as plt 
from skimage import draw 
arr = np.zeros((200, 200)) 
rr, cc = draw.circle_perimeter(100, 100, radius=80, shape=arr.shape) 
arr[rr, cc] = 1 
plt.imshow(arr) 
plt.show() 

Ayrıca loop kullanarak inme taklit edebilir. Bu durumda eserler önlemek için yumuşatılmış sürümünü kullanmalıdır:

import matplotlib.pyplot as plt 
from skimage import draw 
arr = np.zeros((200, 200)) 
stroke = 3 
# Create an outer and inner circle. Then subtract the inner from the outer. 
radius = 80 
inner_radius = radius - (stroke // 2) + (stroke % 2) - 1 
outer_radius = radius + ((stroke + 1) // 2) 
ri, ci = draw.circle(100, 100, radius=inner_radius, shape=arr.shape) 
ro, co = draw.circle(100, 100, radius=outer_radius, shape=arr.shape) 
arr[ro, co] = 1 
arr[ri, ci] = 0 
plt.imshow(arr) 
plt.show() 
:

import matplotlib.pyplot as plt 
from skimage import draw 
arr = np.zeros((200, 200)) 
stroke = 3 
# Create stroke-many circles centered at radius. 
for delta in range(-(stroke // 2) + (stroke % 2), (stroke + 1) // 2): 
    rr, cc, _ = draw.circle_perimeter_aa(100, 100, radius=80+delta, shape=arr.shape) 
    arr[rr, cc] = 1 
plt.imshow(arr) 
plt.show() 

A muhtemelen daha etkili bir yol iki tam çevreleri oluşturmak ve dış itibaren iç "çıkarma" etmektir

İki yöntem aslında biraz farklı sonuçlar vermektedir.

Circle with <code>stroke=3</code>

İlgili konular