问题描述
我正在寻找一种方法来在 pyvista
中交互期间有效地捕获帧缓冲区,以便之后我可以制作模型在屏幕上移动的视频。 >
我遇到的问题是,当我单击屏幕与查看器/绘图仪进行交互时,在按下鼠标按钮并且模型移动到下一个位置时没有写入任何帧。这会导致视频中出现“生涩”的动作。
有没有办法绕过这种行为来有效地执行诸如绘图仪窗口的屏幕截图之类的操作,即使在被操纵时也是如此?也许通过直接访问帧缓冲区或类似的东西?
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyvista as pv
import numpy as np
from pyvista import examples
import matplotlib as mpl
import matplotlib.pyplot as plt
px = int(round(1920*0.4))
py = int(round(1000*0.4))
mesh = examples.download_st_helens().warp_by_scalar()
p = pv.Plotter()
p.set_background(color='k')
cmap = mpl.cm.get_cmap('viridis')
p.add_mesh(mesh,lighting=True,texture=False,cmap=cmap,smooth_shading=True)
p.show_grid()
p.show(window_size=[px,py],auto_close=False,interactive_update=True)
p.render()
p.open_movie('anim.mp4',framerate=60)
i=0
while (i<100):
i+=1
p.write_frame()
print(i)
p.close()
解决方法
我在纯 VTK 中添加了一个示例,其中旋转立方体并通过旋转捕获平滑的视频。之后,启动交互器,之后用户可以与场景进行交互。
import os
import vtk
import numpy as np
def vtkRotationMovie(renderWindow,filename='c:/test.avi'):
global degrees
degrees = 0
windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renderWindow)
windowToImageFilter.SetInputBufferTypeToRGB()
windowToImageFilter.ReadFrontBufferOff()
windowToImageFilter.Update()
if os.name == 'nt':
writer = vtk.vtkAVIWriter()
else:
writer = vtk.vtkOggTheoraWriter()
writer.SetInputConnection(windowToImageFilter.GetOutputPort())
writer.SetRate(10) # Not needed for Ogg
try:
os.remove(filename)
except OSError:
pass
writer.SetFileName(filename)
writer.Start()
timerId = renderWindow.GetInteractor().CreateRepeatingTimer(50)
def cb(interactor,event):
global degrees
step = 5
if (degrees > 359):
interactor.DestroyTimer(timerId)
writer.End()
return
interactor.GetRenderWindow().Render()
cam = interactor.GetRenderWindow().GetRenderers().GetFirstRenderer().GetActiveCamera()
cam.Azimuth(step)
cam.OrthogonalizeViewUp()
windowToImageFilter.Modified()
writer.Write()
degrees = degrees + step
renderWindow.GetInteractor().AddObserver('TimerEvent',cb)
renderWindow.GetInteractor().Start()
# create a rendering window and renderer
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
# create a renderwindowinteractor
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# create cube
cube = vtk.vtkCubeSource()
# mapper
cubeMapper = vtk.vtkPolyDataMapper()
cubeMapper.SetInputConnection(cube.GetOutputPort())
# actor
cubeActor = vtk.vtkActor()
cubeActor.SetMapper(cubeMapper)
# assign actor to the renderer
ren.AddActor(cubeActor)
ren.SetBackground(.3,.2,.1)
# enable user interface interactor
iren.Initialize()
renWin.Render()
vtkRotationMovie(renWin,filename='./test.avi')
iren.Start()