当前位置:   article > 正文

VTK学习日志:基于VTK9.3.0+Visual Studio c++实现DICOM影像MPR多平面重建+V R体绘制4个视图展示功能的实现(二)_c++ vtk开发

c++ vtk开发

        前段时间对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体绘制的代码了。

  1. class vtkImageInteractionCallback : public vtkCommand
  2. {
  3. public:
  4. static vtkImageInteractionCallback* New()
  5. {
  6. return new vtkImageInteractionCallback();
  7. }
  8. vtkImageInteractionCallback()
  9. : ImageReslice(nullptr), Slicing(0) {}
  10. void SetImageReslice(vtkImageReslice* reslice) { this->ImageReslice = reslice; }
  11. virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) override
  12. {
  13. vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::SafeDownCast(caller);
  14. if (!interactor) return;
  15. int x, y;
  16. interactor->GetEventPosition(x, y);
  17. if (eventId == vtkCommand::MouseMoveEvent)
  18. {
  19. if (this->Slicing)
  20. {
  21. this->ProcessSlicing(interactor, x, y);
  22. }
  23. }
  24. else if (eventId == vtkCommand::LeftButtonPressEvent)
  25. {
  26. this->Slicing = 1;
  27. }
  28. else if (eventId == vtkCommand::LeftButtonReleaseEvent)
  29. {
  30. this->Slicing = 0;
  31. }
  32. }
  33. protected:
  34. void ProcessSlicing(vtkRenderWindowInteractor* interactor, int x, int y)
  35. {
  36. // 获取当前切片的中心位置
  37. double sliceCenter[3];
  38. this->ImageReslice->GetOutput()->GetCenter(sliceCenter);
  39. // 获取鼠标移动的增量
  40. int lastX = interactor->GetLastEventPosition()[0];
  41. int lastY = interactor->GetLastEventPosition()[1];
  42. int deltaY = y - lastY;
  43. // 根据移动的方向和增量调整切片位置
  44. double newSlicePosition = sliceCenter[2] + deltaY * 0.1; // 比例因子可以调整
  45. sliceCenter[2] = newSlicePosition;
  46. // 设置新的切片位置
  47. this->ImageReslice->SetResliceAxesOrigin(sliceCenter);
  48. interactor->Render(); // 渲染更新后的图像
  49. }
  50. vtkImageReslice* ImageReslice;
  51. int Slicing;
  52. };
  53. void initImageActor(double* Matrix, double* center, vtkSmartPointer<vtkImageCast> pImageCast,
  54. vtkSmartPointer<vtkImageReslice> imageReslice, vtkSmartPointer<vtkImageActor> actor)
  55. {
  56. vtkSmartPointer<vtkMatrix4x4> AxialResliceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
  57. AxialResliceMatrix->DeepCopy(Matrix);
  58. AxialResliceMatrix->SetElement(0, 3, center[0]);
  59. AxialResliceMatrix->SetElement(1, 3, center[1]);
  60. AxialResliceMatrix->SetElement(2, 3, center[2]);
  61. imageReslice->SetInputConnection(pImageCast->GetOutputPort());
  62. imageReslice->SetOutputDimensionality(2);
  63. imageReslice->SetResliceAxes(AxialResliceMatrix);
  64. imageReslice->SetInterpolationModeToLinear();
  65. imageReslice->Update();
  66. actor->GetMapper()->SetInputConnection(imageReslice->GetOutputPort());
  67. actor->SetPosition(0, 0, 0);
  68. }
  69. void addImageInteractionCallback(vtkRenderWindowInteractor* interactor, vtkImageReslice* imageReslice)
  70. {
  71. vtkSmartPointer<vtkImageInteractionCallback> callback = vtkSmartPointer<vtkImageInteractionCallback>::New();
  72. callback->SetImageReslice(imageReslice);
  73. vtkSmartPointer<vtkInteractorStyleImage> imagestyle = vtkSmartPointer<vtkInteractorStyleImage>::New();
  74. interactor->SetInteractorStyle(imagestyle);
  75. imagestyle->AddObserver(vtkCommand::MouseMoveEvent, callback);
  76. imagestyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
  77. imagestyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);
  78. }
  79. int main()
  80. {
  81. vtkSmartPointer<vtkImageReslice> pImageResliceX = vtkSmartPointer<vtkImageReslice>::New();
  82. vtkSmartPointer<vtkImageReslice> pImageResliceY = vtkSmartPointer<vtkImageReslice>::New();
  83. vtkSmartPointer<vtkImageReslice> pImageResliceZ = vtkSmartPointer<vtkImageReslice>::New();
  84. vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
  85. reader->SetDirectoryName("D:\\image\\images\\011\\CT\\20200115\\67728\\1.3.46.670589.33.1.63714685715192329600004.5577472948825480582");
  86. reader->Update();
  87. int extent[6];
  88. double spacing[3];
  89. double origin[3];
  90. reader->GetOutput()->GetExtent(extent);
  91. reader->GetOutput()->GetSpacing(spacing);
  92. reader->GetOutput()->GetOrigin(origin);
  93. double center[3];
  94. center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
  95. center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
  96. center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);
  97. double Axial[16] = {
  98. 1, 0, 0, 0,
  99. 0, 1, 0, 0,
  100. 0, 0, 1, 0,
  101. 0, 0, 0, 1 };
  102. double Coronal[16] = {
  103. 1, 0, 0, 0,
  104. 0, 0, -1, 0,
  105. 0, 1, 0, 0,
  106. 0, 0, 0, 1 };
  107. double Sagittal[16] = {
  108. 0, 0, 1, 0,
  109. 1, 0, 0, 0,
  110. 0, 1, 0, 0,
  111. 0, 0, 0, 1 };
  112. vtkSmartPointer<vtkImageCast> pImageCast = vtkSmartPointer<vtkImageCast>::New();
  113. pImageCast->SetInputConnection(reader->GetOutputPort());
  114. pImageCast->SetOutputScalarTypeToUnsignedChar();
  115. pImageCast->ClampOverflowOn();
  116. pImageCast->Update();
  117. vtkSmartPointer<vtkImageActor> pImageActorX = vtkSmartPointer<vtkImageActor>::New();
  118. vtkSmartPointer<vtkImageActor> pImageActorY = vtkSmartPointer<vtkImageActor>::New();
  119. vtkSmartPointer<vtkImageActor> pImageActorZ = vtkSmartPointer<vtkImageActor>::New();
  120. initImageActor(Axial, center, pImageCast, pImageResliceX, pImageActorX);
  121. initImageActor(Coronal, center, pImageCast, pImageResliceY, pImageActorY);
  122. initImageActor(Sagittal, center, pImageCast, pImageResliceZ, pImageActorZ);
  123. vtkSmartPointer<vtkRenderer> pRendererX = vtkSmartPointer<vtkRenderer>::New();
  124. vtkSmartPointer<vtkRenderer> pRendererY = vtkSmartPointer<vtkRenderer>::New();
  125. vtkSmartPointer<vtkRenderer> pRendererZ = vtkSmartPointer<vtkRenderer>::New();
  126. vtkSmartPointer<vtkRenderer> pRenderer = vtkSmartPointer<vtkRenderer>::New();
  127. vtkSmartPointer<vtkRenderWindow> pRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
  128. pRendererX->AddActor(pImageActorX);
  129. pRendererY->AddActor(pImageActorY);
  130. pRendererZ->AddActor(pImageActorZ);
  131. // 设置渲染器背景颜色
  132. pRendererX->SetBackground(0, 0, 0);
  133. pRendererY->SetBackground(0, 0, 0);
  134. pRendererZ->SetBackground(0, 0, 0);
  135. pRenderer->SetBackground(0.1, 0.2, 0.4);
  136. // 为每个渲染器设置视口
  137. double ltView[4] = { 0, 0, 0.5, 0.5 };
  138. double rtView[4] = { 0.5, 0, 1, 0.5 };
  139. double lbView[4] = { 0, 0.5, 0.5, 1 };
  140. double rbView[4] = { 0.5, 0.5, 1, 1 };
  141. pRenderer->SetViewport(rtView);
  142. pRendererX->SetViewport(lbView);
  143. pRendererY->SetViewport(rbView);
  144. pRendererZ->SetViewport(ltView);
  145. pRenderWindow->AddRenderer(pRendererX);
  146. pRenderWindow->AddRenderer(pRendererY);
  147. pRenderWindow->AddRenderer(pRendererZ);
  148. pRenderWindow->AddRenderer(pRenderer);
  149. // 设置体积渲染
  150. vtkSmartPointer<vtkPiecewiseFunction> volumeScalarOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
  151. volumeScalarOpacity->AddPoint(0, 0.0);
  152. volumeScalarOpacity->AddPoint(80, 0.0);
  153. volumeScalarOpacity->AddPoint(400, 1.0);
  154. vtkSmartPointer<vtkColorTransferFunction> volumeColor = vtkSmartPointer<vtkColorTransferFunction>::New();
  155. volumeColor->AddRGBPoint(0.0, 0.0, 0.0, 0.0);
  156. volumeColor->AddRGBPoint(80.0, 1.0, 1.0, 1.0);
  157. volumeColor->AddRGBPoint(400.0, 1.0, 1.0, 1.0);
  158. vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
  159. volumeProperty->SetColor(volumeColor);
  160. volumeProperty->SetScalarOpacity(volumeScalarOpacity);
  161. volumeProperty->ShadeOn();
  162. volumeProperty->SetInterpolationTypeToLinear();
  163. vtkSmartPointer<vtkGPUVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
  164. volumeMapper->SetInputConnection(reader->GetOutputPort());
  165. vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New();
  166. volume->SetMapper(volumeMapper);
  167. volume->SetProperty(volumeProperty);
  168. pRenderer->AddVolume(volume);
  169. vtkSmartPointer<vtkRenderWindowInteractor> pRenderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  170. pRenderWindow->SetInteractor(pRenderWindowInteractor);
  171. pRenderWindow->SetSize(800, 800);
  172. // 为横断面视窗添加交互回调
  173. vtkSmartPointer<vtkRenderWindowInteractor> interactorX = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  174. interactorX->SetRenderWindow(pRenderWindow);
  175. addImageInteractionCallback(interactorX, pImageResliceX);
  176. vtkSmartPointer<vtkRenderWindowInteractor> interactorY = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  177. interactorY->SetRenderWindow(pRenderWindow);
  178. addImageInteractionCallback(interactorY, pImageResliceY);
  179. vtkSmartPointer<vtkRenderWindowInteractor> interactorZ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  180. interactorZ->SetRenderWindow(pRenderWindow);
  181. addImageInteractionCallback(interactorZ, pImageResliceZ);
  182. // 为体绘制窗口添加交互回调
  183. vtkSmartPointer<vtkRenderWindowInteractor> interactorVolume = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  184. interactorVolume->SetRenderWindow(pRenderWindow);
  185. vtkSmartPointer<vtkInteractorStyleTrackballCamera> volumeStyle = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
  186. interactorVolume->SetInteractorStyle(volumeStyle);
  187. pRenderWindow->Render();
  188. pRenderWindowInteractor->Initialize();
  189. pRenderWindowInteractor->Start();
  190. return 0;
  191. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/797043
推荐阅读
相关标签
  

闽ICP备14008679号