赞
踩
前段时间对VTK9.3.0进行了编译,开发了MPR+VR实现的demo,显示效果不是很理想,正好趁着周末有时间,再度对之前的程序进行优化和完善,先展示下效果:
VTK实现MPR+VR四视图
再次讲解下基于VTK的MPR+VR实现的简单项目创建过程:
1、在vtk官网https://vtk.org/download/下载vtk库,我下载的是9.3.0版本,如下:
2、下载后解压,用Cmake进行编译,具体编译过程我就不详细说明了.
3、我选择的是Visual Studio 2022 64位开发工具,Cmake编译完成后就生成了VTK.sln解决方案:
编译生成即可,编译过程遇到的问题在我其他几篇博客里已经做了记录,需要可以查看。
4、右键VTK中的“INSTALL”生成VTK的库目录和包含目录,如下:
5、右键VTK项目解决方案,选择 添加新项目,再选择 c++控制台项目即可
6、在新添加的MPR demo项目中添加包含目录、库目录和依赖项,如下:
到此我们已经创建了一个基于VTK9.3.0+Visual Studio的C++控制台项目,在生成的cpp源文件中就可以编写具体的DICOM影像MPR多平面重建+V R体绘制的代码了。
- class vtkImageInteractionCallback : public vtkCommand
- {
- public:
- static vtkImageInteractionCallback* New()
- {
- return new vtkImageInteractionCallback();
- }
-
- vtkImageInteractionCallback()
- : ImageReslice(nullptr), Slicing(0) {}
-
- void SetImageReslice(vtkImageReslice* reslice) { this->ImageReslice = reslice; }
-
- virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) override
- {
- vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);
- if (!interactor) return;
-
- int x, y;
- interactor->GetEventPosition(x, y);
-
- if (eventId == vtkCommand::MouseMoveEvent)
- {
- if (this->Slicing)
- {
- this->ProcessSlicing(interactor, x, y);
- }
- }
- else if (eventId == vtkCommand::LeftButtonPressEvent)
- {
- this->Slicing = 1;
- }
- else if (eventId == vtkCommand::LeftButtonReleaseEvent)
- {
- this->Slicing = 0;
- }
- }
-
- protected:
- void ProcessSlicing(vtkRenderWindowInteractor* interactor, int x, int y)
- {
- // 获取当前切片的中心位置
- double sliceCenter[3];
- this->ImageReslice->GetOutput()->GetCenter(sliceCenter);
-
- // 获取鼠标移动的增量
- int lastX = interactor->GetLastEventPosition()[0];
- int lastY = interactor->GetLastEventPosition()[1];
- int deltaY = y - lastY;
-
- // 根据移动的方向和增量调整切片位置
- double newSlicePosition = sliceCenter[2] + deltaY * 0.1; // 比例因子可以调整
- sliceCenter[2] = newSlicePosition;
-
- // 设置新的切片位置
- this->ImageReslice->SetResliceAxesOrigin(sliceCenter);
- interactor->Render(); // 渲染更新后的图像
- }
-
- vtkImageReslice* ImageReslice;
- int Slicing;
- };
-
- void initImageActor(double* Matrix, double* center, vtkSmartPointer<vtkImageCast> pImageCast,
- vtkSmartPointer<vtkImageReslice> imageReslice, vtkSmartPointer<vtkImageActor> actor)
- {
- vtkSmartPointer<vtkMatrix4x4> AxialResliceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
- AxialResliceMatrix->DeepCopy(Matrix);
-
- AxialResliceMatrix->SetElement(0, 3, center[0]);
- AxialResliceMatrix->SetElement(1, 3, center[1]);
- AxialResliceMatrix->SetElement(2, 3, center[2]);
-
- imageReslice->SetInputConnection(pImageCast->GetOutputPort());
- imageReslice->SetOutputDimensionality(2);
- imageReslice->SetResliceAxes(AxialResliceMatrix);
- imageReslice->SetInterpolationModeToLinear();
- imageReslice->Update();
-
- actor->GetMapper()->SetInputConnection(imageReslice->GetOutputPort());
- actor->SetPosition(0, 0, 0);
- }
-
- void addImageInteractionCallback(vtkRenderWindowInteractor* interactor, vtkImageReslice* imageReslice)
- {
- vtkSmartPointer<vtkImageInteractionCallback> callback = vtkSmartPointer<vtkImageInteractionCallback>::New();
- callback->SetImageReslice(imageReslice);
-
- vtkSmartPointer<vtkInteractorStyleImage> imagestyle = vtkSmartPointer<vtkInteractorStyleImage>::New();
- interactor->SetInteractorStyle(imagestyle);
-
- imagestyle->AddObserver(vtkCommand::MouseMoveEvent, callback);
- imagestyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
- imagestyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);
- }
-
- int main()
- {
- vtkSmartPointer<vtkImageReslice> pImageResliceX = vtkSmartPointer<vtkImageReslice>::New();
- vtkSmartPointer<vtkImageReslice> pImageResliceY = vtkSmartPointer<vtkImageReslice>::New();
- vtkSmartPointer<vtkImageReslice> pImageResliceZ = vtkSmartPointer<vtkImageReslice>::New();
-
- vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
- reader->SetDirectoryName("D:\\image\\images\\011\\CT\\20200115\\67728\\1.3.46.670589.33.1.63714685715192329600004.5577472948825480582");
- reader->Update();
-
- int extent[6];
- double spacing[3];
- double origin[3];
-
- reader->GetOutput()->GetExtent(extent);
- reader->GetOutput()->GetSpacing(spacing);
- reader->GetOutput()->GetOrigin(origin);
-
- double center[3];
- center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
- center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
- center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);
-
- double Axial[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1 };
- double Coronal[16] = {
- 1, 0, 0, 0,
- 0, 0, -1, 0,
- 0, 1, 0, 0,
- 0, 0, 0, 1 };
- double Sagittal[16] = {
- 0, 0, 1, 0,
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 0, 1 };
-
- vtkSmartPointer<vtkImageCast> pImageCast = vtkSmartPointer<vtkImageCast>::New();
- pImageCast->SetInputConnection(reader->GetOutputPort());
- pImageCast->SetOutputScalarTypeToUnsignedChar();
- pImageCast->ClampOverflowOn();
- pImageCast->Update();
-
- vtkSmartPointer<vtkImageActor> pImageActorX = vtkSmartPointer<vtkImageActor>::New();
- vtkSmartPointer<vtkImageActor> pImageActorY = vtkSmartPointer<vtkImageActor>::New();
- vtkSmartPointer<vtkImageActor> pImageActorZ = vtkSmartPointer<vtkImageActor>::New();
-
- initImageActor(Axial, center, pImageCast, pImageResliceX, pImageActorX);
- initImageActor(Coronal, center, pImageCast, pImageResliceY, pImageActorY);
- initImageActor(Sagittal, center, pImageCast, pImageResliceZ, pImageActorZ);
-
- vtkSmartPointer<vtkRenderer> pRendererX = vtkSmartPointer<vtkRenderer>::New();
- vtkSmartPointer<vtkRenderer> pRendererY = vtkSmartPointer<vtkRenderer>::New();
- vtkSmartPointer<vtkRenderer> pRendererZ = vtkSmartPointer<vtkRenderer>::New();
- vtkSmartPointer<vtkRenderer> pRenderer = vtkSmartPointer<vtkRenderer>::New();
- vtkSmartPointer<vtkRenderWindow> pRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
-
- pRendererX->AddActor(pImageActorX);
- pRendererY->AddActor(pImageActorY);
- pRendererZ->AddActor(pImageActorZ);
-
- // 设置渲染器背景颜色
- pRendererX->SetBackground(0, 0, 0);
- pRendererY->SetBackground(0, 0, 0);
- pRendererZ->SetBackground(0, 0, 0);
- pRenderer->SetBackground(0.1, 0.2, 0.4);
-
- // 为每个渲染器设置视口
- double ltView[4] = { 0, 0, 0.5, 0.5 };
- double rtView[4] = { 0.5, 0, 1, 0.5 };
- double lbView[4] = { 0, 0.5, 0.5, 1 };
- double rbView[4] = { 0.5, 0.5, 1, 1 };
-
- pRenderer->SetViewport(rtView);
- pRendererX->SetViewport(lbView);
- pRendererY->SetViewport(rbView);
- pRendererZ->SetViewport(ltView);
-
- pRenderWindow->AddRenderer(pRendererX);
- pRenderWindow->AddRenderer(pRendererY);
- pRenderWindow->AddRenderer(pRendererZ);
- pRenderWindow->AddRenderer(pRenderer);
-
- // 设置体积渲染
- vtkSmartPointer<vtkPiecewiseFunction> volumeScalarOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
- volumeScalarOpacity->AddPoint(0, 0.0);
- volumeScalarOpacity->AddPoint(80, 0.0);
- volumeScalarOpacity->AddPoint(400, 1.0);
-
- vtkSmartPointer<vtkColorTransferFunction> volumeColor = vtkSmartPointer<vtkColorTransferFunction>::New();
- volumeColor->AddRGBPoint(0.0, 0.0, 0.0, 0.0);
- volumeColor->AddRGBPoint(80.0, 1.0, 1.0, 1.0);
- volumeColor->AddRGBPoint(400.0, 1.0, 1.0, 1.0);
-
- vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
- volumeProperty->SetColor(volumeColor);
- volumeProperty->SetScalarOpacity(volumeScalarOpacity);
- volumeProperty->ShadeOn();
- volumeProperty->SetInterpolationTypeToLinear();
-
- vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
- volumeMapper->SetInputConnection(reader->GetOutputPort());
-
- vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
- volume->SetMapper(volumeMapper);
- volume->SetProperty(volumeProperty);
-
- pRenderer->AddVolume(volume);
-
- vtkSmartPointer<vtkRenderWindowInteractor> pRenderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
- pRenderWindow->SetInteractor(pRenderWindowInteractor);
-
- pRenderWindow->SetSize(800, 800);
-
- // 为横断面视窗添加交互回调
- vtkSmartPointer<vtkRenderWindowInteractor> interactorX = vtkSmartPointer<vtkRenderWindowInteractor>::New();
- interactorX->SetRenderWindow(pRenderWindow);
- addImageInteractionCallback(interactorX, pImageResliceX);
-
- vtkSmartPointer<vtkRenderWindowInteractor> interactorY = vtkSmartPointer<vtkRenderWindowInteractor>::New();
- interactorY->SetRenderWindow(pRenderWindow);
- addImageInteractionCallback(interactorY, pImageResliceY);
-
- vtkSmartPointer<vtkRenderWindowInteractor> interactorZ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
- interactorZ->SetRenderWindow(pRenderWindow);
- addImageInteractionCallback(interactorZ, pImageResliceZ);
-
- // 为体绘制窗口添加交互回调
- vtkSmartPointer<vtkRenderWindowInteractor> interactorVolume = vtkSmartPointer<vtkRenderWindowInteractor>::New();
- interactorVolume->SetRenderWindow(pRenderWindow);
-
- vtkSmartPointer<vtkInteractorStyleTrackballCamera> volumeStyle = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
- interactorVolume->SetInteractorStyle(volumeStyle);
-
- pRenderWindow->Render();
- pRenderWindowInteractor->Initialize();
- pRenderWindowInteractor->Start();
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。