如何在matplotlib中暂停视频并保持animfunc运行?

时间:2018-02-21 21:51:47

标签: matplotlib video pause

a)在下面的脚本中,只有1个FuncAnimation循环存储为视频。如何使视频存储永无止境的Funcanimation? (当我摧毁主窗口时它会停止)

b)如何从例如用PyGTK制作的GUI中的信号控制这样的视频(开始/停止)?控制将发生在从不FuncAnimation的平行(没有停止的funcanimation) 欢迎提出任何建议。

更新1: 通过在“FuncAnimation”调用的“animate”中添加以下代码,我创建了稍后将在一个视频中放在一起的图片。通过从GUI控制图片计数,我可以限制视频的大小,停止它,暂停它..主题关闭。通过阅读以下内容,我们解决了How can I make a video from array of images in matplotlib?

video_page_iter = video_page_iter+1 # if video is on
plt.savefig("/home/family/Bilder" + "/file%03d.png" % video_page_iter)  # if video is on
#
if video_page_iter==100:   # or if command store video
    os.chdir("/home/family/Bilder")
    subprocess.call([
        'ffmpeg', '-framerate', '8', '-i', 'file%03d.png', '-r', '30', '-pix_fmt', 'yuv420p',
        'video_name.mp4'
    ])
    for file_name in glob.glob("*.png"):
        os.remove(file_name)
    video_page_iter = 0


import math
import sys
import gi
#import csv
#import pandas as pd
#
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk, Gdk as gdk, GLib, GObject as gobject
import string
import os
import subprocess
import glob
from datetime import datetime, timedelta
import time
import numpy as np
import matplotlib; matplotlib.use('Gtk3Agg')
    #('GTKCairo' dont work)
import matplotlib.animation as animation
from mpl_toolkits.mplot3d.proj3d import proj_transform
from matplotlib.text import Annotation
#from cairocffi import *
#from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCanvas  # this work a bit
#from matplotlib.backends.backend_gtk3 import NavigationToolbar2GTK3 as NavigationToolbar
from matplotlib.backends.backend_gtk3cairo import FigureCanvasGTK3Cairo as FigureCanvas # this work full?
import matplotlib.pyplot as plt
#from multiprocessing import Process,Queue,Value
import multiprocessing as mp
#
#based on https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot#34139293
class Annotation3D(Annotation):
    '''Annotate the point xyz with text s'''
    def __init__(self, s, xyz, *args, **kwargs):
        Annotation.__init__(self,s, xy=(0,0), *args, **kwargs)
        self._verts3d = xyz

    def draw(self, renderer):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj_transform(xs3d, ys3d, zs3d, renderer.M)
        self.xy=(xs,ys)
        Annotation.draw(self, renderer)
#
def annotate3D(ax, s, *args, **kwargs):
    '''add anotation text s to to Axes3d ax'''
    tag = Annotation3D(s, *args, **kwargs)
    ax.add_artist(tag)
#
def draw_basket(ax1, x, y, z, h, color='black'):
    '''add basket to the ax1 figure'''
    # define the basket
    t = np.linspace(0, np.pi * 2, 16)
    #bottom
    ax1.plot(x+0.24*np.cos(t), y+0.24*np.sin(t), z,  linewidth=1, color=color)
    ax1.plot(x+0.16*np.cos(t), y+0.16*np.sin(t), z,  linewidth=1, color=color)
    #top
    ax1.plot(x+0.24*np.cos(t), y+0.24*np.sin(t), z+h,  linewidth=1, color=color)
    # side bars
    A=0
    while A < 16:
        xBar = [x+ 0.16 * math.sin(A*22.5*np.pi/180),x+ 0.24 * math.sin(A*22.5*np.pi/180)]
        yBar = [y+ 0.16 * math.cos(A*22.5*np.pi/180),y+ 0.24 * math.cos(A*22.5*np.pi/180)]
        zBar = [0,h]
        ax1.plot(xBar, yBar, zBar, color=color)
        A = A+1

def draw_halfsphere (ax1, x, y, z, sph_radius, color=(0,0,1,1)):
    ''' add free distance surface to Axes3d ax1 '''
#        https://stackoverflow.com/questions/40460960/how-to-plot-a-sphere-when-we-are-given-a-central-point-and-a-radius-size
    u, v = np.mgrid[0:2 * np.pi:20j, 0:np.pi/2:10j]
    xP1 = x + sph_radius * np.cos(u) * np.sin(v)
    yP1 = y + sph_radius * np.sin(u) * np.sin(v)
    zP1 = z - sph_radius * np.cos(v)
    # Plot the surface
    halffreesphere = ax1.plot_wireframe(xP1, yP1, zP1, color=color, alpha=0.3)
    return halffreesphere
#



def animate(i):

    global pos_pb_now, pos_pb_now_shared, pos_pb_target, p_b, pos_pb_deltamove
    global pos_pw_now, pos_pw_now_shared, pos_pw_target, p_w, pos_pw_deltamove
    global pos_ball_now, pos_ball_now_shared, pos_ball_target, p_ball, pos_ball_deltamove
    global Frame
    global count_iter
    global video_page_iter
    global azimut_shared
    global elevation_shared
    global EmitPosOneWin
    global EmitPosFourWin
    global ax1
    global free_sphere
    #
    azimut, elevation = ax1.azim, ax1.elev
#    print ("azimut from main",azimut)
    azimut_shared.value = azimut
#    print ("azimut_shared value from main",azimut_shared.value)
    elevation_shared.value = elevation

    pos_ball_now[0,0] += (1. / Frame) * pos_ball_deltamove[0,0]
    pos_ball_now[0,1] += (1. / Frame) * pos_ball_deltamove[0,1]
    pos_ball_now[0,2] += (1. / Frame) * pos_ball_deltamove[0,2]
    #
#    EmitPosOneWin.put(['bp', 0, pos_ball_now[0,0], pos_ball_now[0,1], pos_ball_now[0,2]])
#    EmitPosFourWin.put(['bp', 0, pos_ball_now[0,0], pos_ball_now[0,1], pos_ball_now[0,2]])
    pos_ball_now_shared[0] = pos_ball_now[0, 0]
    pos_ball_now_shared[1] = pos_ball_now[0, 1]
    pos_ball_now_shared[2] = pos_ball_now[0, 2]

    for j in range(6):
        pos_pb_now[j, 0] += (1. / Frame) * pos_pb_deltamove[j, 0]
        pos_pb_now[j, 1] += (1. / Frame) * pos_pb_deltamove[j, 1]
        pos_pb_now[j, 2] += (1. / Frame) * pos_pb_deltamove[j, 2]

        pos_pw_now[j, 0] += (1. / Frame) * pos_pw_deltamove[j, 0]
        pos_pw_now[j, 1] += (1. / Frame) * pos_pw_deltamove[j, 1]
        pos_pw_now[j, 2] += (1. / Frame) * pos_pw_deltamove[j, 2]

        #
        # feed the queue; queue because that animation could be paused
#        EmitPosOneWin.put(['pb', j, pos_pb_now[j, 0], pos_pb_now[j, 1], pos_pb_now[j, 2]])
#        EmitPosOneWin.put(['pw', j, pos_pw_now[j, 0], pos_pw_now[j, 1], pos_pw_now[j, 2]])
#        EmitPosFourWin.put(['pb', j, pos_pb_now[j, 0], pos_pb_now[j, 1], pos_pb_now[j, 2]])
#        EmitPosFourWin.put(['pw', j, pos_pw_now[j, 0], pos_pw_now[j, 1], pos_pw_now[j, 2]])
        pos_pb_now_shared[j*3] = pos_pb_now[j,0]
        pos_pb_now_shared[j*3+1] = pos_pb_now[j,1]
        pos_pb_now_shared[j*3+2] = pos_pb_now[j,2]
        pos_pw_now_shared[j*3] = pos_pw_now[j,0]
        pos_pw_now_shared[j*3+1] = pos_pw_now[j,1]
        pos_pw_now_shared[j*3+2] = pos_pw_now[j,2]
        #

    p_b._offsets3d = pos_pb_now[:, 0], pos_pb_now[:, 1], pos_pb_now[:, 2]
    p_w._offsets3d = pos_pw_now[:, 0], pos_pw_now[:, 1], pos_pw_now[:, 2]
    p_ball._offsets3d = pos_ball_now[:,0],pos_ball_now[:,1],pos_ball_now[:,2]

    #
    video_page_iter = video_page_iter+1 # if video is on
    plt.savefig("/home/family/Bilder" + "/file%03d.png" % video_page_iter)  # if video is on
    #
    if video_page_iter==100:   # or if command store video
        os.chdir("/home/family/Bilder")
        subprocess.call([
            'ffmpeg', '-framerate', '8', '-i', 'file%03d.png', '-r', '30', '-pix_fmt', 'yuv420p',
            'video_name.mp4'
        ])
        for file_name in glob.glob("*.png"):
            os.remove(file_name)
        video_page_iter = 0
        # simulate the deletion of the free domain. Will be activated later by a GUI
        free_sphere.remove()
#        fig.canvas.draw()

    if i == (Frame - 1):
        # reset the deltamove to a clean zero for last position in case of rounding elements
        # or set to next step of dynamic move
        count_iter = count_iter+1
        m, s = divmod(count_iter, 2)
        if s == 1:
            pos_ball_deltamove[0,0] = -1.
            pos_ball_deltamove[0,1] = -1.
            pos_ball_deltamove[0,2] = -1.
            for k in range(6):
                pos_pb_deltamove[k, 0] = -1.
                pos_pb_deltamove[k, 1] = -1.
                pos_pb_deltamove[k, 2] = -1.
                pos_pw_deltamove[k, 0] = -1.
                pos_pw_deltamove[k, 1] = -1.
                pos_pw_deltamove[k, 2] = -1.
        else:
            pos_ball_deltamove[0,0] = 1.
            pos_ball_deltamove[0,1] = 1.
            pos_ball_deltamove[0,2] = 1.
            for k in range(6):
                pos_pb_deltamove[k, 0] = 1.
                pos_pb_deltamove[k, 1] = 1.
                pos_pb_deltamove[k, 2] = 1.
                pos_pw_deltamove[k, 0] = 1.
                pos_pw_deltamove[k, 1] = 1.
                pos_pw_deltamove[k, 2] = 1.

        pos_ball_now[0,0] = pos_ball_target[0,0]
        pos_ball_now[0,1] = pos_ball_target[0,1]
        pos_ball_now[0,2] = pos_ball_target[0,2]
        pos_ball_now_shared[0] = pos_ball_now[0, 0]
        pos_ball_now_shared[1] = pos_ball_now[0, 1]
        pos_ball_now_shared[2] = pos_ball_now[0, 2]

        for k in range(6):
            pos_pb_now[k, 0] = pos_pb_target[k, 0]
            pos_pb_now[k, 1] = pos_pb_target[k, 1]
            pos_pb_now[k, 2] = pos_pb_target[k, 2]
            pos_pw_now[k, 0] = pos_pw_target[k, 0]
            pos_pw_now[k, 1] = pos_pw_target[k, 1]
            pos_pw_now[k, 2] = pos_pw_target[k, 2]
            pos_pb_now_shared[k * 3] = pos_pb_now[k, 0]
            pos_pb_now_shared[k * 3 + 1] = pos_pb_now[k, 1]
            pos_pb_now_shared[k * 3 + 2] = pos_pb_now[k, 2]
            pos_pw_now_shared[k * 3] = pos_pw_now[k, 0]
            pos_pw_now_shared[k * 3 + 1] = pos_pw_now[k, 1]
            pos_pw_now_shared[k * 3 + 2] = pos_pw_now[k, 2]

        #
if __name__=="__main__":
    #
    # Set up formatting for the movie files
#    Writer = animation.writers['ffmpeg']
#    writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)
#    writer = Writer(fps = 30, extra_args = ['-vcodec', 'libx264'])
    #
    ######## define the queues for the 2 detached plot processes
    mp.set_start_method('spawn')
    #
#    EmitPosOneWin = mp.Queue()
#    EmitPosFourWin = mp.Queue()
    #########################
    # swimmingpool size
    s_w = 10.0
#    s_w_shared = Value('d', 10.0)
    s_w_shared = mp.Value('f', 10.0)
    #
    s_d = 4.0
    s_d_shared = mp.Value('f', 4.0)
    #
    s_l = 18.0
    s_l_shared = mp.Value('f', 18.0)
    # exchange lane width
    el_w = 1.0  # normally 3
    el_w_shared = mp.Value('f', 1.0)  # just 1m in order to show the side
    # ball radius
#    b_r = 0.53 / (2 * math.pi)
#    b_r_shared = Value('d', 0.53 / (2 * math.pi))
    #
    elevation_shared = mp.Value('f', 10.)
    azimut_shared = mp.Value('f', 30.)
    #
    # define/initiate teams blue and white; array

    pos_pb_now = []
    pos_pb_now_shared = mp.Array('f',3*6)

    pos_pb_target = []

    pos_pw_now = []
    pos_pw_now_shared = mp.Array('f',3*6)

    pos_pw_target = []
    pos_pb_deltamove = []
    pos_pw_deltamove = []
    #
    pos_ball_now = []
    pos_ball_now_shared = mp.Array('f',3)

    pos_ball_target = []
    pos_ball_deltamove = []
    #
    numb_seq = 0
    video_page_iter = 0
    #
    pos_ball_now.append([5.,9.,0.2]) # ball in the middle
    pos_ball_target.append([5.,9.,0.2])
    pos_ball_deltamove.append([0., 0., 0.])
    #
    for i in range(6):
        # distribute the players at the side with the same distance
        # at game start
        pos_pb_now.append([((s_w/6)/2)+i*(s_w/6),1.0, s_d])
        pos_pb_target.append([((s_w/6)/2)+i*(s_w/6),1.0, s_d])
        pos_pw_now.append([s_w - ((s_w / 6) / 2) - i * (s_w / 6), s_l - 1.0, s_d])
        pos_pw_target.append([s_w - ((s_w / 6) / 2) - i * (s_w / 6), s_l - 1.0, s_d])
        pos_pb_deltamove.append([0., 0., 0.])
        pos_pw_deltamove.append([0., 0., 0.])
    #
    # Define numpy array which is faster to work with
    pos_pb_now = np.array(pos_pb_now, dtype='f')
    pos_pb_target = np.array(pos_pb_target, dtype='f')
    pos_pw_now = np.array(pos_pw_now, dtype='f')
    pos_pw_target = np.array(pos_pw_target, dtype='f')
    pos_pb_deltamove = np.array(pos_pb_deltamove, dtype='f')
    pos_pw_deltamove = np.array(pos_pw_deltamove, dtype='f')
    #
    pos_ball_now = np.array(pos_ball_now, dtype='f')
    pos_ball_target = np.array(pos_ball_target, dtype='f')
    pos_ball_deltamove = np.array(pos_ball_deltamove, dtype='f')
    #
    #
    fig = plt.figure()
    ax1 = fig.add_subplot(111,projection='3d')
    # field
    xG = [0,s_w,s_w,0,0, 0,s_w,s_w,s_w,s_w,s_w, 0, 0,0, 0,s_w]
    yG = [0, 0, 0,0,0,s_l,s_l, 0, 0,s_l,s_l,s_l,s_l,0,s_l,s_l]
    zG = [0, 0, s_d,s_d,0, 0, 0, 0, s_d, s_d, 0, 0, s_d,s_d, s_d, s_d]
    ax1.plot_wireframe (xG,yG,zG,colors= (0,0,1,1))  # blue line game area
    # exchange area
    xW = [s_w,s_w+el_w,s_w+el_w,s_w,s_w,s_w,s_w+el_w,s_w+el_w,s_w+el_w,s_w+el_w,s_w+el_w,s_w,s_w,s_w,s_w,s_w+el_w]
    yW = [0,  0, 0, 0, 0,s_l,s_l, 0, 0,s_l,s_l,s_l,s_l, 0,s_l,s_l]
    zW = [0,  0, s_d, s_d, 0, 0, 0, 0, s_d, s_d, 0, 0, s_d, s_d, s_d, s_d]
    ax1.plot_wireframe (xW,yW,zW,colors= (0,1,1,1))  # light blue line exchange area
    #
    ax1.set_xlabel('Wide')
    ax1.set_ylabel('Length')
    ax1.set_zlabel('Water')
    #
    # draw the 2 lines which show the depth
    xG1 = [0, s_w]
    yG1 = [s_d, s_d]
    zG1 = [0, 0]
    ax1.plot_wireframe(xG1, yG1, zG1, colors=(0, 0, 1, 1),linestyle=':')  # blue line
    xG2 = [0, s_w]
    yG2 = [s_l-s_d, s_l-s_d]
    zG2 = [0, 0]
    ax1.plot_wireframe(xG2, yG2, zG2, colors=(0, 0, 1, 1),linestyle=':')  # blue line
    #
    # put the axis fix
    ax1.set_xlim3d(0, s_w+el_w)
    ax1.set_ylim3d(0, s_l)
    ax1.set_zlim3d(0, s_d)
    #
    # use a factor for having y = x in factor
#    ax1.set_aspect(aspect=0.222)
#    ax1.set_aspect("equal")
    ax1.set_aspect(aspect=0.15)  # the best

    #
    # sphere red ball for playing
#    draw_ball(ax1, 5, 9, b_r, label="",color='r',ball_radius=b_r) # user scatter point instead
    #
    # define the basket1
    draw_basket(ax1, s_w / 2, 0.24, 0., 0.45)
    #
    # define the basket2
    draw_basket(ax1, s_w / 2, s_l - 0.24, 0., 0.45)
    #
    free_sphere = draw_halfsphere(ax1, 5., 9., 4., 2.)
    #
    p_b = ax1.scatter(pos_pb_now[:, 0], pos_pb_now[:, 1], pos_pb_now[:, 2],
                          s=400, alpha = 0.5, c=(0, 0, 1, 1))
    p_w = ax1.scatter(pos_pw_now[:, 0], pos_pw_now[:, 1],
                      pos_pw_now[:, 2], s=400, alpha = 0.5, c="darkgrey")

    p_ball = ax1.scatter(pos_ball_now[:,0], pos_ball_now[:,1],
                      pos_ball_now[:,2], s=100, alpha = 0.5, c="red")
    #
    #Add labels  ..  number and not the numbers defined in the player function (feature tbd)
    for j, xyz_ in enumerate(pos_pb_now):
        annotate3D(ax1, s=str(j+1), xyz=xyz_, fontsize=10, xytext=(-3,3),
                   textcoords='offset points', ha='right',va='bottom')
    for j, xyz_ in enumerate(pos_pw_now):
        annotate3D(ax1, s=str(j+1), xyz=xyz_, fontsize=10, xytext=(-3,3),
                   textcoords='offset points', ha='right', va='bottom')

    Frame = 10   # 2 for debugging else put it higher later for smooth movements

    for j in range(6):
        pos_pb_deltamove[j, 0] = 1.
        pos_pb_deltamove[j, 1] = 1.
        pos_pb_deltamove[j, 2] = 1.

        pos_pw_deltamove[j, 0] = 1.
        pos_pw_deltamove[j, 1] = 1.
        pos_pw_deltamove[j, 2] = 1.

    pos_ball_deltamove[0,0] = 1.
    pos_ball_deltamove[0,1] = 1.
    pos_ball_deltamove[0,2] = 1.

    count_iter = 0

    ani1 = animation.FuncAnimation(fig, animate, frames=Frame, interval=600, blit=False, repeat=True, repeat_delay=500)

    plt.pause(0.001)

#    ani1.save('uwr_game.mp4', writer=writer)

    plt.show()

0 个答案:

没有答案