vtk将渲染的3D动画进行录制保存起来的方式
我尝试了两种方式:
(1)使用tvkAVIWriter,这种方式的问题是VTK在python中持支的编码器很少,压缩能力有限,压缩后速率有14M
(2)果断考虑使用cv2来进行视频录制,但是需要进行数据的变换,好在有工具。
下面的方式采用的回调函数可以实现AVI的录制
writer = vtk.vtkAVIWriter()
writer.SetInputConnection(windowToImageFilter.GetOutputPort())
writer.SetFileName("test.avi")
writer.SetRate(30)
writer.SetQuality(0)
writer.PromptCompressionOptionsOn()
#writer.SetCompressorFourCC('DIVX')
writer.Start()
windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renWin)
windowToImageFilter.SetInputBufferTypeToRGB()#不能转成rgba否则就出问题
windowToImageFilter.ReadFrontBufferOff()
windowToImageFilter.Update()
def cb(interactor, event):
global plane_actor,writer,num_frame,windowToImageFilter
plane_actor.RotateZ(0.5)
interactor.GetRenderWindow().Render()
if num_frame<300:
windowToImageFilter.Modified()
writer.Write()
print("writing",num_frame)
num_frame+=1
#time.sleep(1)
else:
writer.End()
print("end")
exit(0)
使用opencv
def writeX265():
global plane_actor, windowToImageFilter
fourcc = cv2.VideoWriter_fourcc(*'X265')
# (640,480)表示分辨率
# 30表示帧率
lz = cv2.VideoWriter('output.mp4', fourcc, 30, (640, 480))
while True:
plane_actor.RotateZ(0.5)
# renInter.GetRenderWindow().Render()
renWin.Render()
#如果不每次都重新创建,就无法获得更新的图像,不清楚是我没有找到法门,还是本身是个问题
windowToImageFilter = vtk.vtkWindowToImageFilter()
windowToImageFilter.SetInput(renWin)
windowToImageFilter.SetInputBufferTypeToRGB() # 不能转成rgba否则就出问题
windowToImageFilter.ReadFrontBufferOff()
windowToImageFilter.Update()
image = windowToImageFilter.GetOutput()
rows, cols, _ = image.GetDimensions()
scalars = image.GetPointData().GetScalars()
arr = vtk_to_numpy(scalars).reshape(cols, rows, -1)[..., ::-1]
img = cv2.flip(arr, 0)
lz.write(img)
cv2.imshow("win", img)
if cv2.waitKey(1) == ord('q'):
break
lz.release()
cv2.destroyAllWindows()
使用系统的writer是没有问题,因为是它通过windowToImageFilter.GetOutputPort()获得数据。
而直接冲windowToImageFilter.GetOutput()只能获取一次,后面需要重新创建。
希望有经验的大侠能分享一下。虽然上面的做法有效,但是道理上不通。谢谢!