基于vtkImageViewer2的MPR(一):初步实现

发布于:2025-08-28 ⋅ 阅读:(24) ⋅ 点赞:(0)

MPR多平面重建的初步实现

一、功能概述

  • 用三个窗口分别显示冠状位、矢状位、横断位的切面图像;
  • 左键按住调节窗宽;
  • 右键按住缩放;
  • 中键按住平移;
  • 滚轮滚动时翻页;

二、代码实现

class mprVtkInteractorStyleImage : public vtkInteractorStyleImage
{
public:
    static mprVtkInteractorStyleImage* New();
    vtkTypeMacro(mprVtkInteractorStyleImage, vtkInteractorStyleImage);

protected:
    vtkImageViewer2* _imageViewer;
    int _slice;
    int _minSlice;
    int _maxSlice;

public:
    void SetImageViewer(vtkImageViewer2* imageViewer)
    {
        _imageViewer = imageViewer;
        _minSlice = imageViewer->GetSliceMin();
        _maxSlice = imageViewer->GetSliceMax();
        _slice = imageViewer->GetSlice();
    }

    void MoveSliceForward()
    {
        if(_slice < _maxSlice)
        {
            _slice += 1;
            _imageViewer->SetSlice(_slice);
            _imageViewer->Render();
        }
    }

    void MoveSliceBackward()
    {
        if(_slice > _minSlice)
        {
            _slice -= 1;
            _imageViewer->SetSlice(_slice);
            _imageViewer->Render();
        }
    }

    virtual void OnKeyDown() override
    {
        string key = this->GetInteractor()->GetKeySym();
        if(key.compare("Up") == 0)
        {
            MoveSliceForward();
        }
        else if(key.compare("Down") == 0)
        {
            MoveSliceBackward();
        }
        //vtkInteractorStyleImage::OnKeyDown();//删除默认父类调用
    }

    virtual void OnMouseWheelForward() override
    {
        MoveSliceForward();
    }

    virtual void OnMouseWheelBackward() override
    {
        if(_slice > _minSlice)
        {
            MoveSliceBackward();
        }
    }
};

vtkStandardNewMacro(mprVtkInteractorStyleImage);
//一定要是全局变量,不能是局部变量;
//局部变量在函数结束后销毁,在mprVtkInteractorStyleImage访问时会报错;
vtkSmartPointer<vtkImageViewer2> viewX;
vtkSmartPointer<vtkImageViewer2> viewY;
vtkSmartPointer<vtkImageViewer2> viewZ;
vtkSmartPointer<mprVtkInteractorStyleImage> mprInteractorStyleX;
vtkSmartPointer<mprVtkInteractorStyleImage> mprInteractorStyleY;
vtkSmartPointer<mprVtkInteractorStyleImage> mprInteractorStyleZ;
void MainWindow::on_dataLoad_pB_clicked()
{
    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);
    viewX->SetSliceOrientation(0);//设置切面
    vtkSmartPointer<vtkRenderWindow> renderWindowX = this->ui->openGLWidget_MPR_X->renderWindow();
    viewX->SetRenderWindow(renderWindowX);
    viewX->SetColorLevel(25);
    viewX->SetColorWindow(3000);
    //创建交互器样式
    mprInteractorStyleX = vtkSmartPointer<mprVtkInteractorStyleImage>::New();
    //把imageView传进去
    mprInteractorStyleX->SetImageViewer(viewX);
    //创建交互器
    vtkSmartPointer<vtkRenderWindowInteractor> interactorX = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactorX->SetRenderWindow(renderWindowX);
    //一定是先设置;如果后设置,会覆盖之前的设置,style就会失效
    viewX->SetupInteractor(interactorX);
    //再设置样式
    interactorX->SetInteractorStyle(mprInteractorStyleX);
    //再初始化
    interactorX->Initialize();
    viewX->Render();
    viewX->GetRenderer()->ResetCamera();

    //矢状位
    viewY = vtkSmartPointer<vtkImageViewer2>::New();
    viewY->SetInputData(imageData);
    viewY->SetSliceOrientation(1);//设置切面
    vtkSmartPointer<vtkRenderWindow> renderWindowY = this->ui->openGLWidget_MPR_Y->renderWindow();
    viewY->SetRenderWindow(renderWindowY);
    viewY->SetColorLevel(25);
    viewY->SetColorWindow(3000);
    //创建交互器样式
    mprInteractorStyleY = vtkSmartPointer<mprVtkInteractorStyleImage>::New();
    //把imageView传进去
    mprInteractorStyleY->SetImageViewer(viewY);
    //创建交互器
    vtkSmartPointer<vtkRenderWindowInteractor> interactorY = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactorY->SetRenderWindow(renderWindowY);
    //一定是先设置;如果后设置,会覆盖之前的设置,style就会失效
    viewY->SetupInteractor(interactorY);
    //再设置样式
    interactorY->SetInteractorStyle(mprInteractorStyleY);
    //再初始化
    interactorY->Initialize();
    viewY->Render();
    viewY->GetRenderer()->ResetCamera();

    //横断位
    viewZ = vtkSmartPointer<vtkImageViewer2>::New();
    viewZ->SetInputData(imageData);
    viewZ->SetSliceOrientation(2);//设置切面
    vtkSmartPointer<vtkRenderWindow> renderWindowZ = this->ui->openGLWidget_MPR_Z->renderWindow();
    viewZ->SetRenderWindow(renderWindowZ);
    viewZ->SetColorLevel(25);
    viewZ->SetColorWindow(3000);
    //创建交互器样式
    mprInteractorStyleZ = vtkSmartPointer<mprVtkInteractorStyleImage>::New();
    //把imageView传进去
    mprInteractorStyleZ->SetImageViewer(viewZ);
    //创建交互器
    vtkSmartPointer<vtkRenderWindowInteractor> interactorZ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactorZ->SetRenderWindow(renderWindowZ);
    //一定是先设置;如果后设置,会覆盖之前的设置,style就会失效
    viewZ->SetupInteractor(interactorZ);
    //再设置样式
    interactorZ->SetInteractorStyle(mprInteractorStyleZ);
    //再初始化
    interactorZ->Initialize();
    viewZ->Render();
    viewZ->GetRenderer()->ResetCamera();
}

三、显示结果

在这里插入图片描述

四、遗留问题

  • 先在外面创建窗口,再嵌入到QT渲染窗口中,过程一闪而过,很明显;
  • 滚轮向上滚动时,先放大,然后才翻页;
  • 没有铺满整个窗口;

网站公告

今日签到

点亮在社区的每一天
去签到