在VTK中,专门用于测量距离的类为vtkDistanceWidget和vtkDistanceRepresentation3D,具体的使用方法在VTK源码提供的实例 QtVTKRenderWindows 中说明。
void vtkDistanceRepresentation3D::GetPoint1WorldPosition(double pos[3])
void vtkDistanceRepresentation3D::GetPoint2WorldPosition(double pos[3])
这两个函数获得 pos1 和 pos2 两个端点处的世界坐标,从而可以测量两点之间的世界坐标距离。我们还可以过下面的函数来获取端点 pos1 和 pos2 的屏幕坐标:
void vtkDistanceRepresentation3D::GetPoint1DisplayPosition(double pos[3])
void vtkDistanceRepresentation3D::GetPoint2DisplayPosition(double pos[3])
在实际应用中,我们通常需要测量 3D 实体模型的空间物理尺寸,经过实验发现,我们不需要对vtkDistanceWidget做任何设置,只需要在使用图像读取类(例如vtkDICOMImageReader)读取 dicom 图像的时候,调用 SetDataSpacing() 将像素间距设置为实际距离即可,如果不设置就是读取的 dicom 的像素间距 tag 即(0028,0030) PixelSpacing表示的像素间距,这样测量得到的就是3D模型的空间实际物理尺寸。代码如下:
import vtk
import os
def ShowDicomVtk3D(dicompath):
render = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
renWin.AddRenderer(render)
renWin.SetSize(512,512)
style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)
reader = vtk.vtkDICOMImageReader()
reader.SetDataByteOrderToLittleEndian()
reader.SetDirectoryName(dicompath)
reader.SetDataSpacing(3.2, 3.2, 1.5);
reader.Update()
contourfilter = vtk.vtkContourFilter()
contourfilter.SetInputConnection(reader.GetOutputPort())
contourfilter.SetValue(0, 500)
normal = vtk.vtkPolyDataNormals()
normal.SetInputConnection(contourfilter.GetOutputPort())
normal.SetFeatureAngle(60)
conMapper = vtk.vtkPolyDataMapper()
conMapper.SetInputConnection(normal.GetOutputPort())
conMapper.ScalarVisibilityOff()
conActor = vtk.vtkActor()
conActor.SetMapper(conMapper)
render.AddActor(conActor)
# 测量3D实体大小
distanceWidget = vtk.vtkDistanceWidget();
distanceWidget.SetInteractor(iren);
representation = vtk.vtkDistanceRepresentation3D();
distanceWidget.SetRepresentation(representation);
distanceWidget.SetPriority(0.9);
representation.GetLineProperty().SetColor(0, 1, 0); # 绿色
representation.GetLabelProperty().SetColor(1, 0, 0); # 红色
distanceWidget.GetRepresentation().SetLabelFormat("%-#6.2f mm");
distanceWidget.ManagesCursorOn();
distanceWidget.On();
# 相机设置
camera = vtk.vtkCamera()
camera.SetViewUp(0, 0, -1)
camera.SetPosition(0, 1, 0)
camera.SetFocalPoint(0, 0, 0)
camera.ComputeViewPlaneNormal()
camera.Dolly(1.5)
render.SetActiveCamera(camera)
render.ResetCamera()
iren.Initialize()
iren.Start()
if __name__ == '__main__':
ShowDicomVtk3D("E://data//01//CT1.25mm")
结果示例: