2016-04-22 204 views
2

我需要繪製半橢圓(或準確地說,半橢圓形磁盤,因此我不能用matplotlib繪製一個elliptical arc)。如何繪製Python中的半橢圓?

我發現OpenCV可以用這個語法來做到這一點:cv2.Ellipse(img, center, axes, angle, start_angle, end_angle, color, thickness=1, lineType=8, shift=0),但是有一件事情讓我很困擾。我想使用標準的x和y座標,而不是像素。此外,我將需要繪製非半徑的半橢圓,並且看起來OpenCV不能這樣做(出於與具有像素座標相同的原因)。

所以,我需要一個代碼,可以做什麼OpenCV(具有相同的angle + start_angle + end_angle結構),但不需要我的像素工作。

回答

2

您可以使用matplotlib arc是你不想讓他們填寫。對於一個充滿弧線,您可以使用接受的解決方案here哪裏定義一個通用的補丁,並與matplotlib橢圓example結合,

import matplotlib.patches as mpatches 
import matplotlib.pyplot as plt 
import numpy.random as rnd 
import numpy as np 

def arc_patch(xy, width, height, theta1=0., theta2=180., resolution=50, **kwargs): 

    # generate the points 
    theta = np.linspace(np.radians(theta1), np.radians(theta2), resolution) 
    points = np.vstack((width*np.cos(theta) + xy[0], 
         height*np.sin(theta) + xy[1])) 
    # build the polygon and add it to the axes 
    poly = mpatches.Polygon(points.T, closed=True, **kwargs) 

    return poly 

NUM = 10 
arcs = [] 
for i in range(NUM): 
    r = rnd.rand()*360. 
    arcs.append(arc_patch(xy=rnd.rand(2)*10, width=1., 
       height=1., theta1=r, theta2=r+180.)) 

# axis settings 
fig, ax = plt.subplots(1,1) 
for a in arcs: 
    ax.add_artist(a) 
    a.set_clip_box(ax.bbox) 
    a.set_alpha(0.5) 
    a.set_facecolor(rnd.rand(3)) 

ax.set_xlim(0, 10) 
ax.set_ylim(0, 10) 

plt.show() 

它看起來像, enter image description here

+0

僅供參考,'matplotlib.patches.Arc'可以填充半橢圓。 –

+0

你有這個@Syrtis Major的參考嗎?這裏是'matplotlib.patches.Arc'官方文檔:http://matplotlib.org/api/patches_api.html#module-matplotlib.patches明確地說:「因爲它執行各種優化,所以不能填充。」 –

+0

啊,我沒有注意到文檔,但只是試了一下(見下面的答案)。我不確定爲什麼,也許文檔有點過時? –

2

使用matplotlib.patches.Arc可以使半橢圓形,只需指定關鍵字theta1=0.0, theta2=180.0(或90至270)。 我寫了一個名爲arcs的包裝函數,用於製作Arc s的散點圖。 它使用PatchCollection,應該有更好的性能並啓用colorbar。 你可以在gist (link)找到它。

下面是一個例子:

a = np.arange(11) 
arcs(a, a, w=4, h=a, rot=a*30, theta1=0.0, theta2=180.0, 
    c=a, alpha=0.5, edgecolor='none') 
plt.colorbar() 

enter image description here


的簡要實施arcs張貼下面完整性埃德·史密斯建議。

def arcs(x, y, w, h, rot=0.0, theta1=0.0, theta2=360.0, 
     c='b', **kwargs): 
    import numpy as np 
    import matplotlib.pyplot as plt 
    from matplotlib.patches import Arc 
    from matplotlib.collections import PatchCollection 

    if np.isscalar(c): 
     kwargs.setdefault('color', c) 
     c = None 

    zipped = np.broadcast(x, y, w, h, rot, theta1, theta2) 
    patches = [Arc((x_, y_), w_, h_, rot_, t1_, t2_) 
       for x_, y_, w_, h_, rot_, t1_, t2_ in zipped] 
    collection = PatchCollection(patches, **kwargs) 

    if c is not None: 
     c = np.broadcast_to(c, zipped.shape).ravel() 
     collection.set_array(c) 

    ax = plt.gca() 
    ax.add_collection(collection) 
    return collection 

完整版可以在gist (link)找到。

+0

您的解決方案看起來不錯。是否可以提取出使用PatchCollections的示例的最小代碼,以便在此給出一個自包含的答案? –