当前位置: 首页 > news >正文

基于vtkImageViewer2的MPR(二):改进

文章目录

  • 一、(一)中的问题:
    • 1、滚轮向上滚动时,先放大,然后才翻页;没有铺满整个窗口;
      • 原因:
      • 详细解释:
    • 2、先在外面创建窗口,再嵌入到QT渲染窗口中,过程一闪而过,很明显;
      • 原因:
      • 详细解释:
  • 二、完善后的代码:
  • 三、显示结果


一、(一)中的问题:

1、滚轮向上滚动时,先放大,然后才翻页;没有铺满整个窗口;

原因:

Render()和 ResetCamera()的调用顺序错误;

详细解释:

在 VTK 中,ResetCamera() 和 Render() 的顺序非常重要:

  • ResetCamera():这个函数会重新计算相机参数,使所有可见对象(在这个案例中是图像)能够完全适应渲染窗口。它会根据当前渲染器中的内容调整相机的位置、焦距和视角。
  • Render():这个函数执行实际的渲染过程,将场景绘制到渲染窗口中。

如果先调用 Render() 再调用 ResetCamera(),会发生以下情况:

  • 第一次 Render() 使用当前的相机设置(可能是默认设置或之前的设置)进行渲染;(小图)
  • 然后 ResetCamera() 调整相机参数以适应图像;(自适应铺满,但没有重新Render())
  • 但是这次调整后的相机设置不会立即生效,需要再次调用 Render() 才能看到效果

这会导致图像不能正确填充窗口,因为第一次渲染使用的是不合适的相机参数。

2、先在外面创建窗口,再嵌入到QT渲染窗口中,过程一闪而过,很明显;

原因:

SetSliceOrientation()和SetRenderWindow()调用顺序问题;

详细解释:

没有设置RenderWindow,先调用SetSliceOrientation时,vtkImageViewer2内部可能会创建一个默认的渲染窗口,因为它需要一个有效的渲染窗口来设置切片方向。这个默认窗口会作为独立窗口显示,然后当后续调用SetRenderWindow时,才会将其替换为Qt中的窗口。

二、完善后的代码:

QString path = QFileDialog::getExistingDirectory(this,"请选择文件夹路径...","D:/S100/");
//1、读取Dicom文件
vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(path.toStdString().c_str());
reader->Update();vtkSmartPointer<vtkImageData> imageData = reader->GetOutput();
//冠状位
viewX = vtkSmartPointer<vtkImageViewer2>::New();
viewX->SetInputData(imageData);vtkSmartPointer<vtkRenderWindow> renderWindowX = this->ui->openGLWidget_MPR_X->renderWindow();
viewX->SetRenderWindow(renderWindowX);
viewX->SetSliceOrientation(0);//设置切面
viewX->SetColorLevel(25);
viewX->SetColorWindow(3000);
//创建交互器样式
mprInteractorStyleX = vtkSmartPointer<mprVtkInteractorStyleImage>::New();
//把imageView传进去
mprInteractorStyleX->SetImageViewer(viewX);
//创建交互器
vtkSmartPointer<vtkRenderWindowInteractor> interactorX = renderWindowX->GetInteractor();
//一定是先设置;如果后设置,会覆盖之前的设置,style就会失效
viewX->SetupInteractor(interactorX);
//再设置样式
interactorX->SetInteractorStyle(mprInteractorStyleX);
viewX->GetRenderer()->ResetCamera();
viewX->Render();//矢状位
viewY = vtkSmartPointer<vtkImageViewer2>::New();
viewY->SetInputData(imageData);vtkSmartPointer<vtkRenderWindow> renderWindowY = this->ui->openGLWidget_MPR_Y->renderWindow();
viewY->SetRenderWindow(renderWindowY);
viewY->SetSliceOrientation(1);//设置切面
viewY->SetColorLevel(25);
viewY->SetColorWindow(3000);
//创建交互器样式
mprInteractorStyleY = vtkSmartPointer<mprVtkInteractorStyleImage>::New();
//把imageView传进去
mprInteractorStyleY->SetImageViewer(viewY);
//创建交互器
vtkSmartPointer<vtkRenderWindowInteractor> interactorY = renderWindowY->GetInteractor();
//一定是先设置;如果后设置,会覆盖之前的设置,style就会失效
viewY->SetupInteractor(interactorY);
//再设置样式
interactorY->SetInteractorStyle(mprInteractorStyleY);
viewY->GetRenderer()->ResetCamera();
viewY->Render();//横断位
viewZ = vtkSmartPointer<vtkImageViewer2>::New();
viewZ->SetInputData(imageData);
vtkSmartPointer<vtkRenderWindow> renderWindowZ = this->ui->openGLWidget_MPR_Z->renderWindow();
viewZ->SetRenderWindow(renderWindowZ);
viewZ->SetSliceOrientation(2);//设置切面
viewZ->SetColorLevel(25);
viewZ->SetColorWindow(3000);
//创建交互器样式
mprInteractorStyleZ = vtkSmartPointer<mprVtkInteractorStyleImage>::New();
//把imageView传进去
mprInteractorStyleZ->SetImageViewer(viewZ);
//创建交互器
vtkSmartPointer<vtkRenderWindowInteractor> interactorZ = renderWindowZ->GetInteractor();
//一定是先设置;如果后设置,会覆盖之前的设置,style就会失效
viewZ->SetupInteractor(interactorZ);
//再设置样式
interactorZ->SetInteractorStyle(mprInteractorStyleZ);
viewZ->GetRenderer()->ResetCamera();
viewZ->Render();

三、显示结果

在这里插入图片描述

http://www.dtcms.com/a/344778.html

相关文章:

  • JavaScript 操作 DOM
  • 图论——Floyd算法
  • 四十一、【高级特性篇】API 文档驱动:OpenAPI/Swagger 一键导入测试用例
  • 上市公司能源消耗数据库
  • 【python】os.makedirs和with open
  • 密码管理中硬编码密码
  • (论文速读)并行自回归视觉生成
  • 硬件驱动---linux内核驱动 启动
  • 【LeetCode】21. 合并两个有序链表
  • 开发二手车小程序时,如何确保信息的真实性和可靠性?
  • Prometheus+Grafana监控redis
  • 【连接器专题】连接器接触界面的理解
  • Elasticsearch Rails 集成(elasticsearch-model / ActiveRecord)
  • 高速互联技术——NVLink
  • SpringBoot3集成Oauth2.1——8自定义认证模式(密码模式)
  • 第九届86358贾家庄短片周在山西汾阳贾家庄举办
  • 将博客网站完整迁移至本地虚拟机
  • 爬虫基础学习-授权认证,cookie认证,异常处理
  • 最短路径问题(图论)
  • 中国SM系列密码算法的入门教程
  • 网络实践——Socket编程UDP
  • Seaborn数据可视化实战:Seaborn颜色与样式定制教程
  • elasticsearch的使用
  • odoo-065 两个视图中的action类型的button互相引用,造成死循环
  • ubuntu使用fstab挂载USB设备(移动硬盘)
  • Claude Code接入Serena mcp
  • ESP32C5,使用espidf框架配置wifi扫描时报错,为什么会提示,ghz_5_channels的参数无效呢
  • 开发避坑指南(32):FastJSON异常JSONArray cannot be cast to JSONObject解决方案
  • 什么是数据分类分级?数据分类分级技术实现路径及产品推荐
  • ​Kubernetes 详解:云原生时代的容器编排与管理