更新 vtk 中的实时点云数据 python
update live pointcloud data in vtk python
我有一个基本问题,因为我是 VTK 的新手。我必须在 VTK 中绘制实时点云数据。我修改了How to display point cloud in vtk in different colors?中给出的代码。
点云应该更新迭代中给定的次数(这里是 30)。我已经使用 Initialize() 来避免某些解决方案中提到的阻塞控制流,在每次迭代中更新点云,并调用 render() 以便它可以用新数据更新 window。
我不明白为什么这会阻塞控制流,并且数据没有更新。只有在迭代结束后,调用 renderWindowInteractor.Start() 后,才会启用交互。
import vtk
from numpy import random
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
def func(pointCloud):
# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(pointCloud.vtkActor)
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Initialize()
return renderWindow,renderWindowInteractor
def main(iter):
while iter > 0:
pointCloud = VtkPointCloud()
for k in xrange(10000):
point = 20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
if iter == 30:
renderWindow,renderWindowInteractor = func(pointCloud)
else:
#pointCloud.vtkPolyData.Modified()
renderWindow.Render()
iter -= 1
renderWindowInteractor.Start()
main(30)
所以你想做一个动画。
更好的做法是遵循 this sample 说明如何使用 TimerEvent。
这是您的代码的样子:
</p>
<pre><code>import vtk
from numpy import random
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
class AddPointCloudTimerCallback():
def __init__(self, renderer, iterations):
self.iterations = iterations
self.renderer = renderer
def execute(self, iren, event):
if self.iterations == 0:
iren.DestroyTimer(self.timerId)
pointCloud = VtkPointCloud()
self.renderer.AddActor(pointCloud.vtkActor)
pointCloud.clearPoints()
for k in xrange(10000):
point = 20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
iren.GetRenderWindow().Render()
if self.iterations == 30:
self.renderer.ResetCamera()
self.iterations -= 1
if __name__ == "__main__":
# Renderer
renderer = vtk.vtkRenderer()
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderWindowInteractor.Initialize()
# Initialize a timer for the animation
addPointCloudTimerCallback = AddPointCloudTimerCallback(renderer, 30)
renderWindowInteractor.AddObserver('TimerEvent', addPointCloudTimerCallback.execute)
timerId = renderWindowInteractor.CreateRepeatingTimer(10)
addPointCloudTimerCallback.timerId = timerId
# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Start()
请注意,我将 iter 重命名为迭代,因为 iter 是 Python 中的保留名称。
我有一个基本问题,因为我是 VTK 的新手。我必须在 VTK 中绘制实时点云数据。我修改了How to display point cloud in vtk in different colors?中给出的代码。
点云应该更新迭代中给定的次数(这里是 30)。我已经使用 Initialize() 来避免某些解决方案中提到的阻塞控制流,在每次迭代中更新点云,并调用 render() 以便它可以用新数据更新 window。
我不明白为什么这会阻塞控制流,并且数据没有更新。只有在迭代结束后,调用 renderWindowInteractor.Start() 后,才会启用交互。
import vtk
from numpy import random
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
def func(pointCloud):
# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(pointCloud.vtkActor)
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Initialize()
return renderWindow,renderWindowInteractor
def main(iter):
while iter > 0:
pointCloud = VtkPointCloud()
for k in xrange(10000):
point = 20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
if iter == 30:
renderWindow,renderWindowInteractor = func(pointCloud)
else:
#pointCloud.vtkPolyData.Modified()
renderWindow.Render()
iter -= 1
renderWindowInteractor.Start()
main(30)
所以你想做一个动画。 更好的做法是遵循 this sample 说明如何使用 TimerEvent。
这是您的代码的样子:
</p>
<pre><code>import vtk
from numpy import random
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
class AddPointCloudTimerCallback():
def __init__(self, renderer, iterations):
self.iterations = iterations
self.renderer = renderer
def execute(self, iren, event):
if self.iterations == 0:
iren.DestroyTimer(self.timerId)
pointCloud = VtkPointCloud()
self.renderer.AddActor(pointCloud.vtkActor)
pointCloud.clearPoints()
for k in xrange(10000):
point = 20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
pointCloud.addPoint([0,0,0])
iren.GetRenderWindow().Render()
if self.iterations == 30:
self.renderer.ResetCamera()
self.iterations -= 1
if __name__ == "__main__":
# Renderer
renderer = vtk.vtkRenderer()
renderer.SetBackground(.2, .3, .4)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderWindowInteractor.Initialize()
# Initialize a timer for the animation
addPointCloudTimerCallback = AddPointCloudTimerCallback(renderer, 30)
renderWindowInteractor.AddObserver('TimerEvent', addPointCloudTimerCallback.execute)
timerId = renderWindowInteractor.CreateRepeatingTimer(10)
addPointCloudTimerCallback.timerId = timerId
# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Start()
请注意,我将 iter 重命名为迭代,因为 iter 是 Python 中的保留名称。