一、利用VTK渲染模型
1.1 VTK渲染模型流程:
① 模型数据导入
# 获取一个Cone(圆锥)模型
cone = vtkConeSource()
② 数据通过Mapper转换为几何图元
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
③ 几何图元通过vtkActor转换为实体
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
④ 通过vtkRenderer渲染这个实体
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
⑤ 渲染好的实体在vtkRenderWindow上显示
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
1.2 VTK渲染模型代码:
import sys
import vtk
from vtkmodules_vtkCommonColor import vtkNamedColors
from vtkmodules_vtkFiltersSources import vtkConeSource
from vtkmodules_vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow
def main(argv):
# 第一步,创建vtkNamedColors,为对象和背景选择颜色
colors = vtkNamedColors()
# 创建vtkConeSource实例
cone = vtkConeSource()
cone.SetHeight(5.0)
cone.SetRadius(1.0)
cone.SetResolution(10)
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
# 为这个Actor设置颜色
coneActor.GetProperty().SetColor(colors.GetColor3d("red"))
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
# 为这个渲染器设置背景颜色
ren1.SetBackground(colors.GetColor3d('pink'))
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
# 设置窗口大小
renWin.SetSize(300, 300)
# 设置窗口名称
renWin.SetWindowName('Hello_World')
for i in range(0, 360):
# 渲染图片
renWin.Render()
# 调用摄像机,一度一度旋转视角
ren1.GetActiveCamera().Azimuth(1)
if __name__ == '__main__':
main(sys.argv)
程序运行结果:渲染一个管道,旋转360度后,程序结束渲染。
二、监听VTK模型
VTK 使用命令/观察者设计模式。也就是说,观察者监视任何vtkObject(或子类)可能对其自身调用的特定事件。例如,vtkRenderer在开始渲染时调用“StartEvent”。这里我们添加一个观察者,当观察到这个事件时调用一个命令。
① 简单的来说,就是通过Renderer自带的AddObserver('StartEvent', mo1)函数,监测,一旦发生事件‘StartEvent’(Renderer开始渲染)就调用mo1。
# mo1绑定渲染器ren1
mo1 = vtkMyCallback(ren1)
# vtkRenderer在开始渲染时调用“StartEvent”。
# 这里我们添加一个观察者,当观察到这个事件时调用一个命令,打印当前摄影机位置。
ren1.AddObserver('StartEvent', mo1)
② 回调函数
# 设置回调函数
class vtkMyCallback(object):
# 实例化
def __init__(self, renderer):
self.renderer = renderer
# 调用时打印当前摄影机位置
def __call__(self, caller, ev):
position = self.renderer.GetActiveCamera().GetPosition()
print('({:5.2f}, {:5.2f}, {:5.2f})'.format(*position))
③ 整体代码
import sys
import vtk
from vtkmodules_vtkCommonColor import vtkNamedColors
from vtkmodules_vtkFiltersSources import vtkConeSource
from vtkmodules_vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow
def main(argv):
# 第一步,创建vtkNamedColors,为对象和背景选择颜色
colors = vtkNamedColors()
# 创建vtkConeSource实例
cone = vtkConeSource()
cone.SetHeight(5.0)
cone.SetRadius(1.0)
cone.SetResolution(10)
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
# 为这个Actor设置颜色
coneActor.GetProperty().SetColor(colors.GetColor3d("red"))
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
# 为这个渲染器设置背景颜色
ren1.SetBackground(colors.GetColor3d('pink'))
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
# 设置窗口大小
renWin.SetSize(300, 300)
# 设置窗口名称
renWin.SetWindowName('Hello_World')
# mo1绑定渲染器ren1
mo1 = vtkMyCallback(ren1)
# vtkRenderer在开始渲染时调用“StartEvent”。
# 这里我们添加一个观察者,当观察到这个事件时调用一个命令,打印当前摄影机位置。
ren1.AddObserver('StartEvent', mo1)
for i in range(0, 360):
# 渲染图片
renWin.Render()
# 调用摄像机,一度一度旋转视角
ren1.GetActiveCamera().Azimuth(1)
# 设置回调函数
class vtkMyCallback(object):
# 实例化
def __init__(self, renderer):
self.renderer = renderer
# 调用时打印当前摄影机位置
def __call__(self, caller, ev):
position = self.renderer.GetActiveCamera().GetPosition()
print('({:5.2f}, {:5.2f}, {:5.2f})'.format(*position))
if __name__ == '__main__':
main(sys.argv)
三、VTK多个渲染器对模型进行渲染
① VTK创建多个渲染器对模型进行渲染,其实就是通过vtkRenderer()创建多个Renderer再把这些Renderer注册到窗口里即可。
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
# 再创建一个渲染器,用来显示我们创建的Actor
ren2 = vtkRenderer()
ren2.AddActor(coneActor)
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
renWin.AddRenderer(ren2)
② 这里需要注意的是, 需要通过SetViewport()设置Renderer相对于窗口的大小和位置。
【以视窗左下角为原点构建坐标系,用两个点绘制出相应的视窗】
比如:SetViewport(0,0,0.5,1)代表如下图所示,左边的粉色部分。
前两个(0,0)代表着相对于左下角的坐标位置。后两个(0.5,1)代表相对于右上角的坐标位置。
SetViewport(0.2,0.6,0.5,1)
③ 整体代码:
import sys
import vtk
from vtkmodules_vtkCommonColor import vtkNamedColors
from vtkmodules_vtkFiltersSources import vtkConeSource
from vtkmodules_vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow
def main(argv):
# 第一步,创建vtkNamedColors,为对象和背景选择颜色
colors = vtkNamedColors()
# 创建vtkConeSource实例
cone = vtkConeSource()
cone.SetHeight(5.0)
cone.SetRadius(1.0)
cone.SetResolution(10)
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
# 为这个Actor设置颜色
coneActor.GetProperty().SetColor(colors.GetColor3d("red"))
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
# 为这个渲染器设置背景颜色
ren1.SetBackground(colors.GetColor3d('pink'))
# setViewport设定视窗大小在窗口的相对位置
# 前两个参数为视窗的左上角相对位置
# 后两个参数为视窗右下角的相对位置
ren1.SetViewport(0.0, 0.0, 0.5, 1.0)
# 再创建一个渲染器,用来显示我们创建的Actor
ren2 = vtkRenderer()
ren2.AddActor(coneActor)
ren2.SetBackground(colors.GetColor3d('yellow'))
ren2.SetViewport(0.5, 0.0, 1.0, 1.0)
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
renWin.AddRenderer(ren2)
# 设置窗口大小
renWin.SetSize(300, 300)
# 设置窗口名称
renWin.SetWindowName('Hello_World')
for i in range(0, 360):
# 渲染图片
renWin.Render()
# 调用摄像机,一度一度旋转视角
ren1.GetActiveCamera().Azimuth(1)
if __name__ == '__main__':
main(sys.argv)
四、VTK对多个模型进行渲染,并操作物体属性
① VTK创建多个模型,可以通过创建多个vtkActor实现。
# 创建一个vtkActor
coneActor = vtkActor()
# 创建第二个Actor
coneActor2 = vtkActor()
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将两个Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
ren1.AddActor(coneActor2)
② 对于vtkActor属性的赋值操作,可以通过vtkProperty()实现
# 创建一个vtkProperty(),通过property设置Actor参数
property = vtkProperty()
property.SetColor(colors.GetColor3d("red"))
property.SetDiffuse(0.7)
property.SetSpecular(0.4)
property.SetSpecularPower(20)
# property放入Actor
coneActor2.SetProperty(property)
③ 可以通个SetPosition()设置vtkActor位置。
# 控制位置
coneActor2.SetPosition(0, 0, 5)
④ 整体代码
import sys
import vtk
from vtkmodules_vtkCommonColor import vtkNamedColors
from vtkmodules_vtkFiltersSources import vtkConeSource
from vtkmodules_vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow, vtkProperty
def main(argv):
# 第一步,创建vtkNamedColors,为对象和背景选择颜色
colors = vtkNamedColors()
# 创建vtkConeSource实例
cone = vtkConeSource()
cone.SetHeight(5.0)
cone.SetRadius(1.0)
cone.SetResolution(10)
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
# 为这个Actor设置颜色
# https://www.fontke.com/tool/pickrgb/
# (45,224,167)为其RGB值,这里需要除以255归一化。
coneActor.GetProperty().SetColor(45/255, 224/255, 167/255)
# 设置漫反射,漫反射系数(Diffuse): 光线照射到物体材质上,经过漫反射后形成的光线强度, 越大时,物体偏亮
coneActor.GetProperty().SetDiffuse(1)
# 设定反射色,光线照射到物体材质上,经过镜面反射后形成的光线强度
coneActor.GetProperty().SetSpecular(0.4)
# 镜面指数(Specular Power): 取值范围是0---128,该值越小,表示材质越是粗糙,当点光源发射的光线照射到上面时,可以产生较大的亮点,
# 该值越大,表示材质越是类似于镜面,光源照射到上面后会产生较小的亮点;
coneActor.GetProperty().SetSpecularPower(20)
# 创建第二个Actor
coneActor2 = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor2.SetMapper(coneMapper)
# 创建一个vtkProperty(),通过property设置Actor参数
property = vtkProperty()
property.SetColor(colors.GetColor3d("red"))
property.SetDiffuse(0.7)
property.SetSpecular(0.4)
property.SetSpecularPower(20)
# property放入Actor
coneActor2.SetProperty(property)
# 控制位置
coneActor2.SetPosition(0, 0, 5)
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将两个Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
ren1.AddActor(coneActor2)
# 为这个渲染器设置背景颜色
ren1.SetBackground(colors.GetColor3d('pink'))
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
# 设置窗口大小
renWin.SetSize(300, 300)
# 设置窗口名称
renWin.SetWindowName('Hello_World')
for i in range(0, 360):
# 渲染图片
renWin.Render()
# 调用摄像机,一度一度旋转视角
ren1.GetActiveCamera().Azimuth(1)
if __name__ == '__main__':
main(sys.argv)
五、与渲染模型的交互
① 渲染模型的交互主要通过两种方式,移动摄像机的方式和移动模型的方式。
② 主要流程为:
(1)创建一个监听器,监听鼠标键盘事件,并设置要监听的窗口
iren = vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
(2)设置交互形式,通过SetInteractorStyle转换相应的鼠标键盘操作。
# 通过修改相机来改变观察角度和物体大小
# vtkInteractorStyleTrackballActor:通过改变actor来改变物体的位置和大小。
style = vtkInteractorStyleTrackballCamera()
# 选择监听方式
iren.SetInteractorStyle(style)
(3)初始化和启动
# 初始化和启动。
# 退出键盘e
# 鼠标滚轮调整大小、按住鼠标右键调整远近、按住鼠标左键调整角度。
iren.Initialize()
iren.Start()
④ 整体代码
import sys
import vtk
from vtkmodules_vtkCommonColor import vtkNamedColors
from vtkmodules_vtkFiltersSources import vtkConeSource
from vtkmodules_vtkInteractionStyle import vtkInteractorStyleTrackballCamera
from vtkmodules_vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow, vtkProperty, \
vtkRenderWindowInteractor
def main(argv):
# 第一步,创建vtkNamedColors,为对象和背景选择颜色
colors = vtkNamedColors()
# 创建vtkConeSource实例
cone = vtkConeSource()
cone.SetHeight(5.0)
cone.SetRadius(1.0)
cone.SetResolution(10)
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
# 为这个Actor设置颜色
# https://www.fontke.com/tool/pickrgb/
# (45,224,167)为其RGB值,这里需要除以255归一化。
coneActor.GetProperty().SetColor(45/255, 224/255, 167/255)
# 设置漫反射,漫反射系数(Diffuse): 光线照射到物体材质上,经过漫反射后形成的光线强度, 越大时,物体偏亮
coneActor.GetProperty().SetDiffuse(1)
# 设定反射色,光线照射到物体材质上,经过镜面反射后形成的光线强度
coneActor.GetProperty().SetSpecular(0.4)
# 镜面指数(Specular Power): 取值范围是0---128,该值越小,表示材质越是粗糙,当点光源发射的光线照射到上面时,可以产生较大的亮点,
# 该值越大,表示材质越是类似于镜面,光源照射到上面后会产生较小的亮点;
coneActor.GetProperty().SetSpecularPower(20)
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
# 为这个渲染器设置背景颜色
ren1.SetBackground(colors.GetColor3d('pink'))
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
# 设置窗口大小
renWin.SetSize(300, 300)
# 设置窗口名称
renWin.SetWindowName('Hello_World')
# vtkRenderWindowInteractor()监听键盘、鼠标等事件。
iren = vtkRenderWindowInteractor()
# 设置要监听的窗口
iren.SetRenderWindow(renWin)
# vtkInteractorStyleTrackballCamera
# 通过修改相机来改变观察角度和物体大小
# vtkInteractorStyleTrackballActor:通过改变actor来改变物体的位置和大小。
style = vtkInteractorStyleTrackballCamera()
# 选择监听方式
iren.SetInteractorStyle(style)
# 初始化
# 退出键盘e
# 鼠标滚轮调整大小、按住鼠标右键调整远近、按住鼠标左键调整角度。
# 按住鼠标中键,可以拖动模型
iren.Initialize()
# 事件循环
iren.Start()
if __name__ == '__main__':
main(sys.argv)
六、VTK模型的拉伸变换
① 3D组件设置
# vtkBoxWidget()是一个正交六面体3D控件。
# 这个3D小部件定义了一个区域,
# 该区域由一个内表面角度为90度(正交面)的任意定向六面体表示。
# 该对象创建了7个可在其上进行鼠标移动和操作的控制柄。
# 此外,还显示了一个边界框轮廓,可以选择其“面”进行对象旋转或缩放。
boxWidget = vtkBoxWidget()
boxWidget.SetInteractor(iren)
# 设置这个3D控件的大小,这里设置为模型的1.25倍
boxWidget.SetPlaceFactor(1.25)
# 设置边界框轮廓颜色
boxWidget.GetOutlineProperty().SetColor(colors.GetColor3d('Gold'))
② 监听相应Actor
# 3d模型Actor选择
boxWidget.SetProp3D(coneActor)
# 放置部件
boxWidget.PlaceWidget()
# 回调函数
callback = vtkMyCallback()
# 鼠标移动的时候调用,这个回调函数
boxWidget.AddObserver('InteractionEvent', callback)
# 可以通过按i选择是否显示这个组件。
boxWidget.On()
③ 回调函数
class vtkMyCallback(object):
def __call__(self, caller, ev):
t = vtkTransform()
widget = caller
widget.GetTransform(t)
widget.GetProp3D().SetUserTransform(t)
④ 整体代码
import sys
import vtk
from vtkmodules_vtkCommonColor import vtkNamedColors
from vtkmodules_vtkCommonTransforms import vtkTransform
from vtkmodules_vtkFiltersSources import vtkConeSource
from vtkmodules_vtkInteractionStyle import vtkInteractorStyleTrackballCamera
from vtkmodules_vtkInteractionWidgets import vtkBoxWidget
from vtkmodules_vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow, vtkProperty, \
vtkRenderWindowInteractor
def main(argv):
# 第一步,创建vtkNamedColors,为对象和背景选择颜色
colors = vtkNamedColors()
# 创建vtkConeSource实例
cone = vtkConeSource()
cone.SetHeight(5.0)
cone.SetRadius(1.0)
cone.SetResolution(10)
# 创建一个Mapper
coneMapper = vtkPolyDataMapper()
# 将vtkConeSource实例放入这个Mapper
coneMapper.SetInputConnection(cone.GetOutputPort())
# 创建一个vtkActor
coneActor = vtkActor()
# 将之前创建的Mapper放入这个Actor中
coneActor.SetMapper(coneMapper)
# 为这个Actor设置颜色
# https://www.fontke.com/tool/pickrgb/
# (45,224,167)为其RGB值,这里需要除以255归一化。
coneActor.GetProperty().SetColor(45/255, 224/255, 167/255)
# 设置漫反射,漫反射系数(Diffuse): 光线照射到物体材质上,经过漫反射后形成的光线强度, 越大时,物体偏亮
coneActor.GetProperty().SetDiffuse(1)
# 设定反射色,光线照射到物体材质上,经过镜面反射后形成的光线强度
coneActor.GetProperty().SetSpecular(0.4)
# 镜面指数(Specular Power): 取值范围是0---128,该值越小,表示材质越是粗糙,当点光源发射的光线照射到上面时,可以产生较大的亮点,
# 该值越大,表示材质越是类似于镜面,光源照射到上面后会产生较小的亮点;
coneActor.GetProperty().SetSpecularPower(20)
# 创建一个渲染器Renderer,用来显示我们创建的Actor
ren1 = vtkRenderer()
# 将Actor放进这个渲染器Renderer中
ren1.AddActor(coneActor)
# 为这个渲染器设置背景颜色
ren1.SetBackground(colors.GetColor3d('pink'))
# 通过vtkRenderWindow()创建一个窗口,用来接收Renderer渲染器。
renWin = vtkRenderWindow()
# 将创建的Renderer渲染器放进这个窗口里
renWin.AddRenderer(ren1)
# 设置窗口大小
renWin.SetSize(300, 300)
# 设置窗口名称
renWin.SetWindowName('Hello_World')
# vtkRenderWindowInteractor()监听键盘、鼠标等事件。
iren = vtkRenderWindowInteractor()
# 设置要监听的窗口
iren.SetRenderWindow(renWin)
# vtkInteractorStyleTrackballCamera
# 通过修改相机来改变观察角度和物体大小
# vtkInteractorStyleTrackballActor:通过改变actor来改变物体的位置和大小。
style = vtkInteractorStyleTrackballCamera()
# 选择监听方式
iren.SetInteractorStyle(style)
# vtkBoxWidget()是一个正交六面体3D控件。
# 这个3D小部件定义了一个区域,
# 该区域由一个内表面角度为90度(正交面)的任意定向六面体表示。
# 该对象创建了7个可在其上进行鼠标移动和操作的控制柄。
# 此外,还显示了一个边界框轮廓,可以选择其“面”进行对象旋转或缩放。
boxWidget = vtkBoxWidget()
boxWidget.SetInteractor(iren)
# 设置这个3D控件的大小,这里设置为模型的1.25倍
boxWidget.SetPlaceFactor(1.25)
# 设置边界框轮廓颜色
boxWidget.GetOutlineProperty().SetColor(colors.GetColor3d('Gold'))
# 小部件的典型用法是使用StartInteractionEvent、InteractionEvent和EndInteractionEvent事件。
# 在鼠标移动时调用InteractionEvent;
# 另外两个事件分别称为“按下按钮”和“按下按钮”(左键或右键)。
# 3d模型Actor选择
boxWidget.SetProp3D(coneActor)
# 放置部件
boxWidget.PlaceWidget()
# 回调函数
callback = vtkMyCallback()
# 鼠标移动的时候调用,这个回调函数
boxWidget.AddObserver('InteractionEvent', callback)
# 可以通过按i选择是否显示这个组件。
boxWidget.On()
# 初始化和启动。
# 退出键盘e
# 鼠标滚轮调整大小、按住鼠标右键调整远近、按住鼠标左键调整角度。
iren.Initialize()
iren.Start()
class vtkMyCallback(object):
def __call__(self, caller, ev):
t = vtkTransform()
widget = caller
widget.GetTransform(t)
widget.GetProp3D().SetUserTransform(t)
if __name__ == '__main__':
main(sys.argv)
七、总结
啊啊啊啊啊啊,最烦的就是这种没中文文档,然后资料又少的东西了🤡