新手求助:如何在切面上实现区域选定
vtk吧
全部回复
仅看楼主
level 1
对dicom文件进行重建,并利用vtkimagereslice做了三视图(如图),目前针对重建模型写了个回调函数,当我在三维模型中点击时,能实时显示点的切面。但我想要点击冠状面的某个区域,让该区域放大、并且另外两个切面都变化到相应位置,这该怎么实现啊
2022年09月01日 01点09分 1
level 1
import vtkmodules as vtk
import vtk
import os
class MouseInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):
button_active = False
def __init__(self, parent=None):
self.parent = vtk.vtkRenderWindowInteractor()
if(parent is not None):
self.parent = parent
self.AddObserver("LeftButtonPressEvent", self.left_button_press_event)
self.AddObserver("LeftButtonReleaseEvent", self.left_button_release_event)
def left_button_press_event(self, obj, event):
print("press on")
self.button_active = True
self.OnLeftButtonDown()
def left_button_release_event(self, obj, event):
global point
point = widget.GetCurrentCursorPosition()
#print(point)
if point[2] != 0:
xresliceAxes.DeepCopy((1, 0, 0, point[0],
0, 1, 0, point[1],
0, 0, 1, point[2],
0, 0, 0, 1))
xreslice.Update()
yresliceAxes.DeepCopy((1, 0, 0, point[0],
0, 0, 1, point[1],
0, -1, 0, point[2],
0, 0, 0, 1))
yreslice.Update()
zresliceAxes.DeepCopy((1, 0, 0, point[0],
0, 0, 1, point[1],
0, -1, 0, point[2],
0, 0, 0, 1))
zreslice.Update()
renX.ResetCamera()
renY.ResetCamera()
renZ.ResetCamera()
self.button_active = False
self.OnLeftButtonUp()
# 创建渲染器、渲染窗口和交互器。渲染器绘制到渲染窗口,交互器实现基于鼠标和键盘的场景交互。
ren = vtk.vtkRenderer()
renX = vtk.vtkRenderer()
renY = vtk.vtkRenderer()
renZ = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.AddRenderer(renX)
renWin.AddRenderer(renY)
renWin.AddRenderer(renZ)
# 设置各切面窗口大小
ren.SetViewport(0.5, 0, 1, 0.5)
renX.SetViewport(0, 0.5, 0.5, 1)
renY.SetViewport(0.5, 0.5, 1, 1)
renZ.SetViewport(0, 0, 0.5, 0.5)
renX.SetBackground(.3, .3, .3)
renY.SetBackground(.3, .3, .3)
renZ.SetBackground(.3, .3, .3)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# 下面的阅读器用于读取组成volume的一系列2D切片(图像)。
# 设置切片尺寸和像素间距。还必须指定数据Endianness。
# 读取器结合使用FilePrefix和切片号来构造文件名,格式为FilePrefix.%d。
v16 = vtk.vtkDICOMImageReader()
v16.SetDirectoryName("C:/Users/zz/Desktop/4Dreconfiguration/reference/C-2502048429/4")
v16.Update()
# 获取灰度范围
range = [1,2]
v16.GetOutput().GetScalarRange(range)
m_pShift =vtk.vtkImageShiftScale() # 可以指定偏移和比例参数来对图像进行操作
m_pShift.SetShift(-1.0*range[0]) #设置偏移量
m_pShift.SetScale(255.0/(range[1] - range[0])) #设置放缩值
m_pShift.SetOutputScalarTypeToUnsignedChar() #将结果强制输出为unsignedchar格式
m_pShift.SetInputConnection(v16.GetOutputPort())
m_pShift.ReleaseDataFlagOff() #ReleaseDataFlag是对滤波器过程中的数据备份控制
m_pShift.Update()
# 该体积将显示光线投射阿尔法合成。需要一个光线投射贴图器来进行光线投射,需要一个合成函数来沿着光线进行合成。
volumeMapper = vtk.vtkGPUVolumeRayCastMapper()
volumeMapper.SetInputConnection(v16.GetOutputPort())
volumeMapper.SetBlendModeToComposite()
volumeMapper.SetSampleDistance(0.1)
# 颜色传递函数将体素强度映射到颜色。它是特定于形态的,通常也是特定于解剖结构的。
# 我们的目标是让肉(500到1000)有一种颜色,骨头(1150或以上)有另一种颜色。
volumeColor = vtk.vtkColorTransferFunction()
volumeColor.AddRGBPoint(0, 0.0, 0.0, 0.0)
volumeColor.AddRGBPoint(500, 1.0, 0.5, 0.3)
volumeColor.AddRGBPoint(1000, 1.0, 0.5, 0.3)
volumeColor.AddRGBPoint(1150, 1.0, 1.0, 0.9)
# 利用不透明度传递函数控制不同组织类型的不透明度。
volumeScalarOpacity = vtk.vtkPiecewiseFunction()
volumeScalarOpacity.AddPoint(0, 0.00)
volumeScalarOpacity.AddPoint(500, 0.55)
volumeScalarOpacity.AddPoint(1000, 0.95)
volumeScalarOpacity.AddPoint(1150, 0.85)
# 利用梯度不透明度函数降低体量“平坦”区域的不透明度,同时保持组织类型边界的不透明度。
# 梯度是用强度在单位距离上的变化量来测量的。对于大多数医疗数据,单位距离为1mm。
volumeGradientOpacity = vtk.vtkPiecewiseFunction()
volumeGradientOpacity.AddPoint(0, 0.0)
volumeGradientOpacity.AddPoint(90, 0.5)
volumeGradientOpacity.AddPoint(100, 1.0)
# VolumeProperty将颜色和不透明度功能附加到volume,并设置其他volume属性。
# 插值应该设置为线性,以实现高质量的渲染。
# ShadeOn选项打开定向照明,这通常会增强音量的外观,使它看起来更“3D”。
# 然而,阴影的质量取决于如何准确地计算出体积的梯度,对于有噪声的数据,梯度估计将是非常差的。
# 遮阳的影响可以通过增加环境系数来降低,同时降低漫反射系数和镜面系数。
# 为了增加阴影的影响,减少环境,增加漫反射和镜面。
volumePropertry = vtk.vtkVolumeProperty()
volumePropertry.SetColor(volumeColor)
volumePropertry.SetScalarOpacity(volumeScalarOpacity)
volumePropertry.SetInterpolationTypeToLinear()
volumePropertry.ShadeOn()
volumePropertry.SetAmbient(0.9)
volumePropertry.SetDiffuse(0.9)
volumePropertry.SetSpecular(0.9)
# vtkVolume是一个vtkProp3D(类似于vtkActor),它在世界坐标中控制volume的位置和方向。
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumePropertry)
# 最后,将volume添加到渲染器中
ren.AddViewProp(volume)
# 设置volume的初始视图。焦点将是体积的中心,摄像机的位置将在病人的正面 800mm 处。
camera = ren.GetActiveCamera()
c = volume.GetCenter()
camera.SetFocalPoint(c[0], c[1], c[2])
camera.SetPosition(c[0], c[1] + 800, c[2])
camera.SetViewUp(0, 0, -1)
point = v16.GetOutput().GetCenter()
# 添加横切面(X
xresliceAxes = vtk.vtkMatrix4x4()
xresliceAxes.DeepCopy((1, 0, 0, c[0],
0, 1, 0, c[1],
0, 0, 1, c[2],
0, 0, 0, 1)
xreslice = vtk.vtkImageReslice()
xreslice.SetInputConnection(m_pShift.GetOutputPort())
xreslice.SetOutputDimensionality(2)
xreslice.SetAutoCropOutput(True)
xreslice.SetResliceAxes(xresliceAxes)
xreslice.SetInterpolationModeToLinear()
xreslice.Update()
xActor = vtk.vtkImageActor()
xActor.SetInputData(xreslice.GetOutput())
renX.AddActor(xActor)
# 添加X的摄像头
xcamera = renX.GetActiveCamera()
xcamera.SetFocalPoint(c[0], c[1], c[2])
xcamera.SetPosition(c[0], c[1], c[2] + 800)
# 添加冠切面(Y
yresliceAxes = vtk.vtkMatrix4x4()
yresliceAxes.DeepCopy((1, 0, 0, c[0],
0, 0, 1, c[1],
0, -1, 0, c[2],
0, 0, 0, 1))
yreslice = vtk.vtkImageReslice()
yreslice.SetInputConnection(m_pShift.GetOutputPort())
yreslice.SetOutputDimensionality(2)
yreslice.SetAutoCropOutput(True)
yreslice.SetResliceAxes(yresliceAxes)
yreslice.SetInterpolationModeToLinear()
yreslice.Update()
yActor = vtk.vtkImageActor()
yActor.SetInputData(yreslice.GetOutput())
renY.AddActor(yActor)
#添加Y的摄像头
ycamera = renY.GetActiveCamera()
ycamera.SetFocalPoint(c[0], c[1], c[2])
ycamera.SetPosition(c[0], c[1], c[2] + 800)
#ycamera.SetViewUp(0, 0, -1)
# 添加矢切面(Z)
zresliceAxes = vtk.vtkMatrix4x4()
zresliceAxes.DeepCopy((0, 0, -1, c[0],
1, 0, 0, c[1],
0, -1, 0, c[2],
0, 0, 0, 1))
zreslice = vtk.vtkImageReslice()
zreslice.SetInputConnection(m_pShift.GetOutputPort())
zreslice.SetOutputDimensionality(2)
zreslice.SetAutoCropOutput(True)
zreslice.SetResliceAxes(zresliceAxes)
zreslice.SetInterpolationModeToLinear()
zreslice.Update()
zActor = vtk.vtkImageActor()
zActor.SetInputData(zreslice.GetOutput())
renZ.AddActor(zActor)
#添加Z的摄像头
zcamera = renZ.GetActiveCamera()
zcamera.SetFocalPoint(c[0], c[1], c[2])
zcamera.SetPosition(c[0], c[1], c[2] + 800)
#zcamera.SetViewUp(0, 0, -1)
# 设置截面
widget = vtk.vtkImagePlaneWidget()
widget.SetInteractor(iren)
widget.SetInputConnection(v16.GetOutputPort())
widget.RestrictPlaneToVolumeOn() # 将widget限制在volume中
widget.GetPlaneProperty().SetColor(0.9, 0.4, 0.4)
widget.TextureInterpolateOn()
widget.SetDefaultRenderer(ren)
widget.DisplayTextOn() # 显示鼠标选中的坐标、灰度值的文本信息
widget.SetResliceInterpolateToLinear() # 切面线性插值
widget.SetPlaneOrientationToZAxes() # 设置widget朝向z轴
widget.SetSliceIndex(10)
widget.On()
# 增加渲染窗口的大小
renWin.SetSize(640, 480)
ren.ResetCamera()
renX.ResetCamera()
renY.ResetCamera()
renZ.ResetCamera()
# 与数据交互
iren.SetInteractorStyle(MouseInteractorStyle(parent=iren))
iren.Initialize()
renWin.Render()
iren.Start()
2022年09月01日 01点09分 2
level 1
切面屏蔽鼠标交互也不是很会,有哥能讲讲吗[泪]
2022年09月01日 01点09分 3
屏蔽鼠标交互就是重写鼠交互器,把相应的重写成空函数题就行了
2022年09月02日 03点09分
@abjsa 屏蔽解决了 谢谢哥[泪]
2022年09月06日 02点09分
level 1
现在有个新问题,我想单独在我冠状面上选一个点,然后这个点反馈到三维模型上,能显示在三维模型上的坐标,这该怎么办啊[喷]
2022年09月06日 07点09分 4
level 1
楼主 求教 你右下角三维图中的切片是怎么显示出来的呀
2022年10月07日 16点10分 5
就是我代码中定义的widget
2022年10月08日 03点10分
1