如何在Python动画函数中返回未知数量的对象

时间:2018-11-28 12:58:14

标签: python list animation ellipse

我目前正在尝试制作一系列图像的动画,其中为每个图像绘制一个最初未知的椭圆形。到目前为止,我已经尝试了很多事情,但是还没有找到解决方案,尽管我想我已经接近了。这是我的代码:

var today = Math.round((new Date()).getTime() / 1000);

console.log(today);

现在,当我尝试此代码时,出现以下错误消息:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse

def plot_images(img1, img2, objects, ax):

    im1 = ax.imshow(img1)
    im2 = ax.imshow(img2 with transparency as an overlay)

    # plotting an ellipse for each object
    e = [None]*len(objects)
    for j in range(len(objects)):
        e[j] = Ellipse(xy=(objects['x'][j], objects['y'][j]),
                            width=6 * objects['a'][j],
                            height=6 * objects['b'][j],
                            angle=objects['theta'][j] * 180. / np.pi)
        e[j].set_facecolor('none')
        e[j].set_edgecolor('red')
        ax.add_artist(e[j])

    return im1, im2, e


def animate(j):

    # extracting objects
    im1, im2, objects = object_finder_function()

    imm1, imm2, e = plot_images(im1, im2, objects, axs)


    return imm1, imm2, e

fig, axs = plt.subplots()
ani = animation.FuncAnimation(fig, animate, frames=image_number, interval=50, blit=True)
plt.show()

所以我尝试了不同的方法,但是最终我发现,当作为测试时,我放入plot_images函数

AttributeError: 'list' object has no attribute 'get_zorder'

并相应地更改动画功能,即

return im1, im2, e[0], e[1], e[2]

imm1, imm2, e0, e1, e2 = plot_images(im1, im2, objects, axs)

我没有收到错误消息,椭圆实际上按照我的意图绘制在各个帧中。现在的问题是,对于一个图像,我想绘制每幅图像有数百个椭圆,所以我必须手动将其全部写下(即e [0],e [1],e [2]- -e [k],和动画功能相同),这似乎不是正确的方法。另一件事是,正如我已经说过的,每张图像的椭圆数会发生变化,并且以前是未知的,因此我无法相应地调整功能。

如何返回此椭圆列表,以便动画读取它,就像我会像在工作示例中那样将它们全部写下来一样?

3 个答案:

答案 0 :(得分:1)

听起来您想压扁e

您可以使用已经平坦的变量创建列表,然后使用e:扩展它:

    return tuple([im1, im2] + e)

或者在您要使用的任何地方使用unpack e

答案 1 :(得分:1)

您的代码有点不合逻辑,因此为清晰起见,我对其进行了一些清理。您的AttributeErrorget_zorder函数有关,该函数在matplotlib中用于确定如何对图进行分层。使用您尝试过的方法,我可以告诉您只需要最后打开list_of_ellipses即可。

def plot_images(img1, img2, objects, ax):

    im1 = ax.imshow(img1)
    im2 = ax.imshow(img2 with transparency as an overlay)

    list_of_ellipses = []
    for j in range(len(objects)):
        my_ellipse = Ellipse(xy=(objects['x'][j], objects['y'][j]),
                        width=6 * objects['a'][j],
                        height=6 * objects['b'][j],
                        angle=objects['theta'][j] * 180. / np.pi)

        my_ellipse.set_facecolor('none')
        my_ellipse.set_edgecolor('red')
        ax.add_artist(e[j])
        list_of_ellipses.append(my_ellipse)
    return im1, im2, list_of_ellipses


def animate():
    im1, im2, objects = object_finder_function()
    imm1, imm2, list_of_ellipses = plot_images(im1, im2, objects, axs)
    return (imm1, imm2)+tuple(list_of_ellipses)

fig, axs = plt.subplots()
ani = animation.FuncAnimation(fig, animate, frames=image_number, interval=50, blit=True)
plt.show()

答案 2 :(得分:1)

假设您正在使用matplotlib.animation,则animate应该返回一个iterable,并且您返回的包含三个对象。 return imm1, imm2, e返回三个实例的tuple。最后一个是列表。通过将list函数更改为:

,您应该能够返回tuple而不是animate
def animate(j):
    im1, im2, objects = object_finder_function()
    imm1, imm2, e = plot_images(im1, im2, objects, axs)

    return [imm1, imm2] + e

但是,我将更改plot_images以返回list。也许像下面这样:

def create_ellipse(objects, object_idx, artists):
    ellipse = Ellipse(
        xy=(objects['x'][object_idx], objects['y'][object_idx]),
        width=(6 * objects['a'][object_idx]),
        height=(6 * objects['b'][object_idx]),
        angle=(objects['theta'][object_idx] * 180.0 / np.pi))
    ellipse.set_facecolor('none')
    ellipse.set_edgecolor('red')
    artists.add_artists(ellipse)
    return ellipse

def plot_images(img1, img2, objects, ax):
    renderables = [ax.imshow(img1),
                   ax.imshow(img2 with transparency as an overlay)]
    renderables.extend(create_ellipse(objects, idx, ax)
                       for idx in range(len(objects)))
    return renderables