【无标题】

文章讨论了使用VTK在Python中录制3D动画的两种方法,一是通过vtkAVIWriter,但受限于编码器的压缩能力;二是利用cv2的VideoWriter,虽需额外处理数据转换,但能支持更好的压缩格式如X265。作者遇到的问题是vtkAVIWriter的输出质量和效率,以及cv2录制时需要不断重建windowToImageFilter以获取更新图像。
摘要由CSDN通过智能技术生成

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()只能获取一次,后面需要重新创建。

希望有经验的大侠能分享一下。虽然上面的做法有效,但是道理上不通。谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值