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



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

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

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

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

所以我尝试了不同的东西,但最终,我发现,作为测试,我输入了plot_images函数。

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

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

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

return imm1, imm2, e0, e1, e2

我没有收到错误消息,省略号实际上按照我的预期绘制在各自的帧中。现在的问题是,首先,我想绘制每个图像有数百个椭圆,所以我必须手动写下所有椭圆(即 e[0]、e[1]、e[2] - e[k],动画函数也是如此),这似乎不是正确的方法。另一件事是,正如我已经说过的那样,每个图像的省略号数量都会发生变化,并且以前不知道,因此我不可能相应地调整功能。

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

你的代码有点不python,所以我为了清楚起见清理了一下。您的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(my_ellipse)
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()

听起来你想扁平化e.

您可以使用已经平面化的变量创建一个列表,并使用 e 对其进行扩展:

return tuple([im1, im2] + e)

或者e任何您想使用它的地方打开包装。

假设您使用的是matplotlib.animation,animate应该返回一个iterable并且您返回一个包含三个对象的。return imm1, imm2, e返回三个实例的元组。 最后一个是列表。 您应该能够通过将animate函数更改为以下内容来返回list而不是tuple

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

最新更新