写在前面:
我是一个2020年入学的农学学生,读硕后开启了跨学科方向的课题研究:CT。所以一切要开始从头自学:Python、C++、VTK、ITK等。整个过程既富有挑战性,又极其痛苦,为勉励自己不忘初心,追求卓越,不失前进的动力与方向,特开通此博客,记录自己的每一次收获与成长,同时也做一些知识分享,与大家共同进步。
本文目的:
为在三维使用区域生长分割算法,需要设置种子点,但种子点的寻找需要在二维进行交互寻找,所以这个时候需要先将Dicom序列文件进行体绘制(Volume Rendering),随后通过VTK的交互类 vtkImagePlaneWidget 进行交互找点,同时在交互过程中显示横截面。
代码如下:
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkImagePlaneWidget.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageActor.h>
#include <vtkOutlineFilter.h>
#include <vtkPiecewiseFunction.h>
#include <vtkColorTransferFunction.h>
#include <vtkVolumeProperty.h>
#include <vtkVolume.h>
#include <vtkProperty.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkTexture.h>
int main()
{
//====================读取dicom序列文件===============================
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName("C:\\Users\\liuya\\Desktop\\CT\\151490");
reader->Update();
//===========================体绘制====================================
//实例化GPU加速体绘制
vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper =
vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
volumeMapper->SetInputConnection(reader->GetOutputPort());
//设置透明度传输函数
vtkSmartPointer<vtkPiecewiseFunction> opacity =
vtkSmartPointer<vtkPiecewiseFunction>::New();
opacity->AddSegment(0, 0, 180, 1);
//设置颜色传输函数
vtkSmartPointer<vtkColorTransferFunction> color =
vtkSmartPointer<vtkColorTransferFunction>::New();
color->AddRGBSegment(0, 0.5, 0.1, 0.1, 180, 1, 1, 1);
//配置传输函数
vtkSmartPointer<vtkVolumeProperty> volumeProperty =
vtkSmartPointer<vtkVolumeProperty>::New();
volumeProperty->SetScalarOpacity(opacity);
volumeProperty->SetColor(color);
volumeProperty->SetInterpolationTypeToLinear();
volumeProperty->ShadeOn();
volumeProperty->SetAmbient(0.4);//环境光系数
volumeProperty->SetDiffuse(0.6);//散射光系数
volumeProperty->SetSpecular(0.2);//高光强度:控制体绘制外观平滑程度
//volumeMapper->SetBlendModeToMaximumIntensity();//最大密度投影
//实例化体绘制Actor
vtkSmartPointer<vtkVolume> volume =
vtkSmartPointer<vtkVolume>::New();
volume->SetMapper(volumeMapper);
volume->SetProperty(volumeProperty);
//实例化Renderer,renderer1用于渲染体绘制与imagePlaneWidget的交互,
//renderer2用于渲染切面图
vtkSmartPointer<vtkRenderer> renderer1 =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderer> renderer2 =
vtkSmartPointer<vtkRenderer>::New();
renderer1->AddVolume(volume);
vtkSmartPointer<vtkRenderWindow> window =
vtkSmartPointer<vtkRenderWindow>::New();
window->AddRenderer(renderer1);
window->AddRenderer(renderer2);
window->SetSize(600, 300);
window->SetWindowName("pig CT 3D Viewer");
renderer1->SetViewport(0, 0, 0.5, 1);//设置渲染窗口位置
renderer2->SetViewport(0.5, 0, 1, 1);
renderer1->SetBackground(0, 0, 0);
renderer2->SetBackground(0.3, 0.3, 0.3);
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(window);
//=====================ImagePlaneWidget==========================
//实例化ImagePlaneWidget
vtkSmartPointer<vtkImagePlaneWidget> widget =
vtkSmartPointer<vtkImagePlaneWidget>::New();
widget->SetInteractor(interactor);
widget->SetInputConnection(reader->GetOutputPort());
widget->RestrictPlaneToVolumeOn();//将widget限制在volume中
widget->GetPlaneProperty()->SetColor(0.9, 0.4, 0.4);
widget->TextureInterpolateOn();
widget->SetDefaultRenderer(renderer1);
widget->DisplayTextOn();//显示鼠标选中的坐标、灰度值的文本信息
widget->SetResliceInterpolateToLinear();//切面线性插值
widget->SetPlaneOrientationToZAxes();//设置widget朝向为Z轴
widget->SetSliceIndex(10);
//============================切面渲染==============================
vtkSmartPointer<vtkPlaneSource> slicePlane =
vtkSmartPointer<vtkPlaneSource>::New();
vtkSmartPointer<vtkPolyDataMapper> planeMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> planeActor =
vtkSmartPointer<vtkActor>::New();
planeMapper->SetInputConnection(slicePlane->GetOutputPort());
planeActor->SetMapper(planeMapper);
planeActor->SetTexture(widget->GetTexture());
renderer2->AddActor(planeActor);
//=============================启动项目===============================
widget->On();
window->Render();
interactor->Initialize();
interactor->Start();
return 0;
}
效果图如下:
可使用鼠标中间滚轮来调整切片位置,使用鼠标左键寻找合适点,点坐标与灰度值在左下角限制。
参考博客:
https://blog.csdn.net/weixin_42834523/article/details/88855142