【问题标题】:Generate point cloud from depth map image using vtk使用 vtk 从深度图图像生成点云
【发布时间】:2018-10-17 17:02:30
【问题描述】:

我用python写了一个代码来生成一个3D模型的深度图并保存 使用VTK作为图像。
但是当我编写代码从图像生成点云时,只有一部分 点云的生成。我找不到原因。我在两个代码中使用相同的相机参数。 code and 3d model

从网格生成深度图图像

import vtk
import os
import numpy as np
from vtk.util import numpy_support


reader = vtk.vtkXMLPolyDataReader()
data_path = 'C:/Users/jiang/Repository/ModelNet10/chair_train_scaled'
path = os.path.join(data_path, "chair_0001.vtp") #Archive path
reader.SetFileName(path)
reader.Update()

ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

bounds = reader.GetOutput().GetBounds()

voxelModeller = vtk.vtkVoxelModeller ()
voxelModeller.SetSampleDimensions(128,128,128)
voxelModeller.SetModelBounds(bounds)
voxelModeller.SetMaximumDistance(0.1)
voxelModeller.SetScalarTypeToFloat()

voxelModeller.SetInputConnection(reader.GetOutputPort())
voxelModeller.Update()

# Create transfer mapping scalar value to opacity
opacityTransferFunction = vtk.vtkPiecewiseFunction()
opacityTransferFunction.AddPoint(0, 0.0)
opacityTransferFunction.AddPoint(1, 1)

# Create transfer mapping scalar value to color
colorTransferFunction = vtk.vtkColorTransferFunction()
colorTransferFunction.AddRGBPoint(0.0, 1.0, 1.0, 1.0)
colorTransferFunction.AddRGBPoint(1.0, 1.0, 0.0, 0.0)

# The property describes how the data will look
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorTransferFunction)
volumeProperty.SetScalarOpacity(opacityTransferFunction)
volumeProperty.ShadeOn()
volumeProperty.SetInterpolationTypeToLinear()

# The mapper / ray cast function know how to render the data
volumeMapper = vtk.vtkGPUVolumeRayCastMapper()
volumeMapper.SetBlendModeToComposite()
volumeMapper.SetInputConnection(voxelModeller.GetOutputPort())
volumeMapper.RenderToImageOn()
# The volume holds the mapper and the property and
# can be used to position/orient the volume
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)


ren.AddVolume(volume)
ren.SetBackground(1, 1, 1)
renWin.SetSize(128, 128)


ren.GetActiveCamera().SetPosition(32, 0,0)
ren.GetActiveCamera().SetFocalPoint(0, 0, 0)
ren.GetActiveCamera().SetViewUp(0, 0, 1)
ren.GetActiveCamera().SetClippingRange(20,50)
renWin.Render()

dpimg = vtk.vtkImageData()
volumeMapper.GetDepthImage(dpimg)

scale = vtk.vtkImageShiftScale()
scale.SetOutputScalarTypeToUnsignedChar()

scale.SetInputData(dpimg)
scale.SetShift(0)
scale.SetScale(255)


imageWriter = vtk.vtkBMPWriter()
imageWriter.SetFileName("depthmap1.bmp")
imageWriter.SetInputConnection(scale.GetOutputPort())
imageWriter.Write()

从深度图图像生成云点

import vtk
import os
import numpy as np
from vtk.util import numpy_support

reader = vtk.vtkBMPReader()
reader.SetFileName('depthmap3.bmp')
reader.Update()
dpscalar = reader.GetOutput().GetPointData().GetScalars()
dpnp1d = numpy_support.vtk_to_numpy(dpscalar)
print(np.max(dpnp1d),np.min(dpnp1d))

scale = vtk.vtkImageShiftScale()
scale.SetOutputScalarTypeToFloat()
#scale.SetInputConnection(filter.GetOutputPort())
scale.SetInputConnection(reader.GetOutputPort())
scale.SetShift(0)
#scale.SetScale(-1/255.0)
scale.SetScale(1/255.0)
scale.Update()

dpscalar = scale.GetOutput().GetPointData().GetScalars()
dpnp1d = numpy_support.vtk_to_numpy(dpscalar)
print(np.max(dpnp1d),np.min(dpnp1d))


ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
ren.SetBackground(1, 1, 1)
renWin.SetSize(300,300)
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)


camera =ren.GetActiveCamera()
camera.SetPosition(-32, 0,0)
camera.SetFocalPoint(0, 0, 0)
camera.SetViewUp(0, 0, 1)
camera.SetClippingRange(20,50)
axial = vtk.vtkMatrix4x4()
axial.DeepCopy((3.73205, 0, 0, 0,
                 0, 3.73205, 0, 0,
                 0, 0, -2.33333, -66.6667,
                 0, 0, -1, 0)) 
#camera.SetUseExplicitProjectionTransformMatrix(True)
#camera.SetExplicitProjectionTransformMatrix(axial)
print(camera)

print(camera.GetWindowCenter ())

pc = vtk.vtkDepthImageToPointCloud()
pc.SetInputConnection(scale.GetOutputPort())
pc.SetCamera(camera)
pc.CullNearPointsOn()
pc.CullFarPointsOn()
#pc.ProduceVertexCellArrayOff()
pc.Update()
print(pc)
#print(ren.GetActiveCamera())

pcMapper = vtk.vtkPolyDataMapper()
pcMapper.SetInputConnection(pc.GetOutputPort())

# pcMapper = vtk.vtkPointGaussianMapper()
# pcMapper.SetInputConnection(pc.GetOutputPort())
# pcMapper.EmissiveOff()
# pcMapper.SetScaleFactor(0.0)

pcActor = vtk.vtkActor()
pcActor.SetMapper(pcMapper)
iren.Initialize()
ren.AddActor(pcActor)
ren.SetBackground(0,0,0)
# ren.GetActiveCamera().SetPosition(32, 0,0)
# ren.GetActiveCamera().SetFocalPoint(0, 0, 0)
# ren.GetActiveCamera().SetViewUp(0, 0, 1)
ren.ResetCamera()
renWin.Render()
iren.Start()

【问题讨论】:

    标签: python opengl vtk


    【解决方案1】:

    我找出问题所在。当我使用 vtkBMPReader 时,这个输出 类是 3 通道 vtkImageData,但只有 vtkDepthImageToPointCloud 接收 1 通道深度图像。所以我们需要使用 vtkImageExtractComponents 获取 vtkBMPReader 输出的第一个通道。

    但我还是不明白 vtk 是如何计算投影变换矩阵的。

    【讨论】:

      【解决方案2】:

      要获得正确的投影矩阵,您可以在 C++ 中使用它,假设是 vtkRenderer* 渲染器。 python中的代码应该是类似的:

      vtkCamera* camera = renderer->GetActiveCamera();
      vtkSmartPointer<vtkMatrix4x4> projection  = vtkSmartPointer<vtkMatrix4x4>::New();
      projection->DeepCopy( camera->GetCompositeProjectionTransformMatrix( renderer->GetTiledAspectRation(), 0.0, 1.0) ); // This maps the z-buffer from 0.0 to 1.0.
      

      我在vtkRenderervtkVolume 源代码等类中发现了这种用法。希望对您有所帮助。

      顺便说一句,由于某种原因,深度缓冲区默认填充为 1.0 秒,而不是预期的 0.0 秒。

      【讨论】:

        猜你喜欢
        • 2020-04-22
        • 1970-01-01
        • 1970-01-01
        • 2021-01-13
        • 2016-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        相关资源
        最近更新 更多