VTK 多平面重建(MPR)及三维切片显示
2017-12-14 21:11
316 查看
在此之前翻阅很多资料,爬过很多的坑,花费不少时间,终于还是完成了!虽然实现地很简单,但是大体功能是实现了。后面需要完善功能的话,可以用qt与vtk结合开发。
MPR 的优点
能任意产生新的断层图像,而无需重复扫描。
曲面重组能在一幅图像里展开显示弯曲物体的生长。
MPR的缺点
难以表达复杂的空间结构。
曲面重组易造成假阳性。
MPR
MPR(multi-planner reformation)也称多平面重建,多重面重建是将扫描范围内所有的轴位图像叠加起来再对某些标线标定的重组线所指定的组织进行冠状、矢状位、任意角度斜位图像重组。MPR 的优点
能任意产生新的断层图像,而无需重复扫描。
曲面重组能在一幅图像里展开显示弯曲物体的生长。
MPR的缺点
难以表达复杂的空间结构。
曲面重组易造成假阳性。
#include "vtkSmartPointer.h" #include "vtkActor.h" #include "vtkCamera.h" #include "vtkCellPicker.h" #include "vtkCommand.h" #include "vtkImageActor.h" #include "vtkImageReslice.h" #include "vtkInteractorStyleImage.h" #include "vtkImageMapToColors.h" #include "vtkImagePlaneWidget.h" #include "vtkImageReader.h" #include "vtkInteractorEventRecorder.h" #include "vtkLookupTable.h" #include "vtkOutlineFilter.h" #include "vtkDICOMImageReader.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkImageData.h" #include "vtkPointData.h" #include "vtkPlaneSource.h" #include "vtkPlane.h" #include "vtkResliceCursorActor.h" #include "vtkResliceCursorPolyDataAlgorithm.h" #include "vtkResliceCursor.h" #include "vtkResliceCursorWidget.h" #include "vtkResliceCursorLineRepresentation.h" #include "vtkBiDimensionalWidget.h" #include"vtkAutoInit.h" #include"vtkAxesActor.h" #include"vtkTransform.h" #include"vtkTextActor.h" #include"vtkProperty2D.h" VTK_MODULE_INIT(vtkRenderingOpenGL); VTK_MODULE_INIT(vtkInteractionStyle); VTK_MODULE_INIT(vtkRenderingFreeType); VTK_MODULE_INIT(vtkRenderingVolumeOpenGL); class vtkResliceCursorCallback : public vtkCommand { public: static vtkResliceCursorCallback *New() { return new vtkResliceCursorCallback; } void Execute(vtkObject *caller, unsigned long, void *callData) override { vtkImagePlaneWidget* ipw = dynamic_cast< vtkImagePlaneWidget* >(caller); if (ipw) { double* wl = static_cast<double*>(callData); if (ipw == this->IPW[0]) { this->IPW[1]->SetWindowLevel(wl[0], wl[1], 1); this->IPW[2]->SetWindowLevel(wl[0], wl[1], 1); } else if (ipw == this->IPW[1]) { this->IPW[0]->SetWindowLevel(wl[0], wl[1], 1); this->IPW[2]->SetWindowLevel(wl[0], wl[1], 1); } else if (ipw == this->IPW[2]) { this->IPW[0]->SetWindowLevel(wl[0], wl[1], 1); this->IPW[1]->SetWindowLevel(wl[0], wl[1], 1); } } vtkResliceCursorWidget *rcw = dynamic_cast<vtkResliceCursorWidget * >(caller); if (rcw) { vtkResliceCursorLineRepresentation *rep = dynamic_cast<vtkResliceCursorLineRepresentation * >(rcw->GetRepresentation()); vtkResliceCursor *rc = rep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor(); for (int i = 0; i < 3; i++) { vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(this->IPW[i]->GetPolyDataAlgorithm()); ps->SetNormal(rc->GetPlane(i)->GetNormal()); ps->SetCenter(rc->GetPlane(i)->GetOrigin()); this->IPW[i]->UpdatePlacement(); } } this->RCW[0]->Render(); } vtkResliceCursorCallback() {} vtkImagePlaneWidget* IPW[3]; vtkResliceCursorWidget *RCW[3]; }; int main() { vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New(); reader->SetDirectoryName("F://CT3"); reader->Update(); /*vtkSmartPointer<vtkOutlineFilter> outline = vtkSmartPointer<vtkOutlineFilter>::New(); outline->SetInputConnection(reader->GetOutputPort());*/ vtkSmartPointer<vtkPolyDataMapper> outlineMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); outlineMapper->SetInputConnection(reader->GetOutputPort()); vtkSmartPointer<vtkActor> outlineActor = vtkSmartPointer<vtkActor>::New(); outlineActor->SetMapper(outlineMapper); vtkSmartPointer<vtkRenderer> ren[4]; vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->SetMultiSamples(0); for (int i = 0; i < 4; i++) { ren[i] = vtkSmartPointer<vtkRenderer>::New(); renWin->AddRenderer(ren[i]); } vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New(); iren->SetRenderWindow(renWin); vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New(); picker->SetTolerance(0.005); vtkSmartPointer<vtkProperty> ipwProp = vtkSmartPointer<vtkProperty>::New(); vtkSmartPointer<vtkImagePlaneWidget> planeWidget[3]; int imageDims[3]; reader->GetOutput()->GetDimensions(imageDims); for (int i = 0; i < 3; i++) { planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New(); planeWidget[i]->SetInteractor(iren); planeWidget[i]->SetPicker(picker); planeWidget[i]->RestrictPlaneToVolumeOn(); double color[3] = { 0, 0, 0 }; color[i] = 1; planeWidget[i]->GetPlaneProperty()->SetColor(color); planeWidget[i]->SetTexturePlaneProperty(ipwProp); planeWidget[i]->TextureInterpolateOff(); planeWidget[i]->SetResliceInterpolateToLinear(); planeWidget[i]->SetInputConnection(reader->GetOutputPort()); planeWidget[i]->SetPlaneOrientation(i); planeWidget[i]->SetSliceIndex(imageDims[i] / 2); planeWidget[i]->DisplayTextOn(); planeWidget[i]->SetDefaultRenderer(ren[3]); planeWidget[i]->SetWindowLevel(1358, -27); planeWidget[i]->On(); planeWidget[i]->InteractionOn(); } planeWidget[1]->SetLookupTable(planeWidget[0]->GetLookupTable()); planeWidget[2]->SetLookupTable(planeWidget[0]->GetLookupTable()); vtkSmartPointer<vtkResliceCursorCallback> cbk = vtkSmartPointer<vtkResliceCursorCallback>::New(); vtkSmartPointer< vtkResliceCursor > resliceCursor = vtkSmartPointer< vtkResliceCursor >::New(); resliceCursor->SetCenter(reader->GetOutput()->GetCenter()); resliceCursor->SetThickMode(0); resliceCursor->SetThickness(10, 10, 10); resliceCursor->SetImage(reader->GetOutput()); vtkSmartPointer< vtkResliceCursorWidget > resliceCursorWidget[3]; vtkSmartPointer< vtkResliceCursorLineRepresentation > resliceCursorRep[3]; double viewUp[3][3] = { { 0, 0, -1 }, { 0, 0, 1 }, { 0, 1, 0 } }; for (int i = 0; i < 3; i++) { resliceCursorWidget[i] = vtkSmartPointer< vtkResliceCursorWidget >::New(); resliceCursorWidget[i]->SetInteractor(iren); resliceCursorRep[i] = vtkSmartPointer< vtkResliceCursorLineRepresentation >::New(); resliceCursorWidget[i]->SetRepresentation(resliceCursorRep[i]); resliceCursorRep[i]->GetResliceCursorActor()->GetCursorAlgorithm()->SetResliceCursor(resliceCursor); resliceCursorRep[i]->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i); const double minVal = reader->GetOutput()->GetScalarRange()[0]; if (vtkImageReslice *reslice = vtkImageReslice::SafeDownCast(resliceCursorRep[i]->GetReslice())) { reslice->SetBackgroundColor(minVal, minVal, minVal, minVal); } resliceCursorWidget[i]->SetDefaultRenderer(ren[i]); resliceCursorWidget[i]->SetEnabled(1); ren[i]->GetActiveCamera()->SetFocalPoint(0, 0, 0); double camPos[3] = { 0, 0, 0 }; camPos[i] = 1; ren[i]->GetActiveCamera()->SetPosition(camPos); ren[i]->GetActiveCamera()->ParallelProjectionOn(); ren[i]->GetActiveCamera()->SetViewUp(viewUp[i][0], viewUp[i][1], viewUp[i][2]); ren[i]->ResetCamera(); cbk->IPW[i] = planeWidget[i]; cbk->RCW[i] = resliceCursorWidget[i]; resliceCursorWidget[i]->AddObserver(vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk); double range[2]; reader->GetOutput()->GetScalarRange(range); resliceCursorRep[i]->SetWindowLevel(range[1] - range[0], (range[0] + range[1]) / 2.0); planeWidget[i]->SetWindowLevel(range[1] - range[0], (range[0] + range[1]) / 2.0); resliceCursorRep[i]->SetLookupTable(resliceCursorRep[0]->GetLookupTable()); planeWidget[i]->GetColorMap()->SetLookupTable(resliceCursorRep[0]->GetLookupTable()); } /*vtkSmartPointer<vtkTextActor> textActor = vtkSmartPointer<vtkTextActor>::New(); textActor->SetInput("横断面"); textActor->GetProperty()->SetColor(0.0,1.0,0.0);*/ ren[0]->SetBackground(0.3, 0.1, 0.1); ren[1]->SetBackground(0.1, 0.3, 0.1); ren[2]->SetBackground(0.1, 0.1, 0.3); ren[3]->AddActor(outlineActor); ren[3]->SetBackground(0.1, 0.1, 0.1); renWin->SetSize(600, 600); ren[0]->SetViewport(0, 0, 0.5, 0.5); ren[1]->SetViewport(0.5, 0, 1, 0.5); ren[2]->SetViewport(0, 0.5, 0.5, 1); ren[3]->SetViewport(0.5, 0.5, 1, 1); renWin->Render(); ren[3]->GetActiveCamera()->Elevation(110); ren[3]->GetActiveCamera()->SetViewUp(0, 0, -1); ren[3]->GetActiveCamera()->Azimuth(45); ren[3]->GetActiveCamera()->Dolly(1.15); ren[3]->ResetCameraClippingRange(); vtkSmartPointer< vtkInteractorStyleImage > style = vtkSmartPointer< vtkInteractorStyleImage >::New(); iren->SetInteractorStyle(style); iren->Initialize(); iren->Start(); return EXIT_SUCCESS; }
相关文章推荐
- VTK 点云重建和读取.txt文档显示三维点云
- VTK的三维切片和三视图显示
- VS2008、QT及VTK实现DICOM图像三维重建之三:Win32工程配置
- OpenCV学习笔记(19)双目测距与三维重建的OpenCV实现问题集锦(四)三维重建与OpenGL显示
- VTK修炼之道26:图像基本操作_三维图像切片提取
- 【VTK】VTK中设置默认的三维切片方向
- 转kidwei 最简单但是却最有用的vtk三维重建代码
- VTK读取一个TXT文档中的三维点坐标显示三维点云
- 双目测距(六)--三维重建及UI显示
- VC++ VTK 读取序列CT图片三维重建
- VTK读取一个TXT文档中的三维点坐标显示三维点云
- VTK修炼之道27:图像基本操作_三维图像切片交互提取(回调函数、观察者-命令模式)
- vs2008和QT及VTK实现三维重建之VS2008下QT的安装使用
- VTK读取序列JPG图片MC算法进行三维重建
- vtk二维图像三维显示,Z轴表示灰度
- VTK三维重建(1)-使用VTK读取DICOM,并动态输出
- VS2008、QT及VTK实现DICOM图像三维重建之二:VS2008下VTK的安装使用
- VTK三维重建(2)-根据脚部骨骼CT的三维重建和显示
- 用VTK实现CT图片的三维重建过程
- VTK三维重建(1)-使用VTK读取DICOM,并动态输出