在 pyvista 中保存屏幕截图,包括交互/旋转

Save screen capture in pyvista including interaction / rotation

我正在寻找一种在 pyvista 交互 期间有效捕获帧缓冲区的方法,以便我可以在模型移动之后制作视频屏幕。

我遇到的问题是,当我单击屏幕与 viewer/plotter 交互时,按下鼠标按钮时没有写入任何帧,模型正在移动到下一个位置。这导致视频中有 'jerky' 个动作。

有没有办法绕过这种行为,即使在被操纵时也能有效地执行绘图仪 window 的屏幕截图之类的操作?也许通过直接访问帧缓冲区或类似的东西?

#!/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()