Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python VTK, how to record a video?

I am trying to record a video of VTK 3D animation using ffmpeg. The example I found http://www.itk.org/Wiki/VTK/Examples/Cxx/Video/FFMPEG is a bit strange for me, because it does not create a render, so it is not clear how to attach actors in this case. So, my question is how to connect vtkRenderer to vtkFFMPEGWriter? I wrote a simplified example

import vtk

# draw a plane
plane_source = vtk.vtkPlaneSource()
plane_source.SetCenter(0, 0, 0)
plane_source.SetNormal(0, 0, 1)
plane_mapper = vtk.vtkPolyDataMapper()
plane_mapper.SetInput(plane_source.GetOutput())
plane_actor = vtk.vtkActor()
plane_actor.SetMapper(plane_mapper)

# create render
render = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(render)
renWin.SetSize(800, 600)
renInter = vtk.vtkRenderWindowInteractor()
renInter.SetRenderWindow(renWin)
render.AddActor(plane_actor)
renWin.Render()
renInter.Initialize()

# set callback
def cb(interactor, event):
    global plane_actor
    plane_actor.RotateZ(0.1)
    interactor.GetRenderWindow().Render()

renInter.AddObserver('TimerEvent', cb)
timerId = renInter.CreateRepeatingTimer(100);

# put something here?
writer = vtk.vtkFFMPEGWriter()
# ??? writer.SetInputConnection(...)
writer.SetFileName("test.avi")
writer.Start()

# run
renInter.Start()
like image 485
Maksim Surov Avatar asked Jun 15 '15 21:06

Maksim Surov


Video Answer


2 Answers

The problem can be easily solved by using vtkWindowToImageFilter (description here):

windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renWin)
windowToImageFilter.SetInputBufferTypeToRGBA()
windowToImageFilter.ReadFrontBufferOff()
windowToImageFilter.Update()

writer = vtk.vtkAVIWriter()
writer.SetInputConnection(windowToImageFilter.GetOutputPort())
writer.SetFileName("test.avi")
...
like image 76
Maksim Surov Avatar answered Oct 27 '22 06:10

Maksim Surov


Use the vtkWindowToImageFilter. You have to tell both the movie writer and the image filter when a new frame is ready. Also, some movie writers need an explicit call to end to finish the file properly. The example below shows the full life-cycle.

#Setup filter
renWin = vtk.vtkRenderWindow()
imageFilter = vtk.vtkWindowToImageFilter()
imageFilter.SetInput(renWin)
imageFilter.SetInputBufferTypeToRGB()
imageFilter.ReadFrontBufferOff()
imageFilter.Update()

#Setup movie writer
moviewriter = vtk.vtkOggTheoraWriter() 
moviewriter.SetInputConnection(windowToImageFilter.GetOutputPort())
moviewriter.SetFileName("movie.ogv")
moviewriter.Start()
renWin.start()
...

#Export a single frame
imageFilter.Modified()
moviewriter.Write()
...

#Finish movie
moviewriter.End()

The couplet that exports a frame may be called as many times as needed to complete the movie.

Using SetInputBufferTypeToRGB fixed problems that only appeared on one of my installations. With SetInputBufferTypeToRGBA, I saw banding and multiple partial copies. With SetInputBufferTypeToRGB it worked on every machine I tried.

The example uses the OggTheora encoder because it is available on many platforms by default.

like image 32
Joseph Cottam Avatar answered Oct 27 '22 06:10

Joseph Cottam