​ 本篇文章将参考大神们的足迹,模仿这实现四视图。

电梯

  • 1 参考资料
  • 2 参考代码
  • 3 自己的代码
  • 4 运行效果
  • ☞ 源码

1 参考资料

​ 其实说四视图是不是很不专业,是不是应该叫多平面重建及三维切片显示呀。参考资料如下:

参考:https://blog.csdn.net/hit1524468/article/details/113446783

​ https://www.cnblogs.com/fuzhuoxin/p/12513872.html

​ https://blog.csdn.net/weixin_38500110/article/details/78807196

2 参考代码

#ifndef QtVTKRenderWindows_H
#define QtVTKRenderWindows_H#include "vtkSmartPointer.h"
#include "vtkResliceImageViewer.h"
#include "vtkImagePlaneWidget.h"
#include "vtkDistanceWidget.h"
#include "vtkResliceImageViewerMeasurements.h"
#include <QMainWindow>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)// Forward Qt class declarations
class Ui_QtVTKRenderWindows;class QtVTKRenderWindows : public QMainWindow
{Q_OBJECT
public:// Constructor/DestructorQtVTKRenderWindows(int argc, char *argv[]);~QtVTKRenderWindows() override {}public slots:virtual void slotExit();virtual void resliceMode(int);virtual void thickMode(int);virtual void SetBlendModeToMaxIP();virtual void SetBlendModeToMinIP();virtual void SetBlendModeToMeanIP();virtual void SetBlendMode(int);virtual void ResetViews();virtual void Render();virtual void AddDistanceMeasurementToView1();virtual void AddDistanceMeasurementToView( int );protected:vtkSmartPointer< vtkResliceImageViewer > riw[3];vtkSmartPointer< vtkImagePlaneWidget > planeWidget[3];vtkSmartPointer< vtkDistanceWidget > DistanceWidget[3];vtkSmartPointer< vtkResliceImageViewerMeasurements > ResliceMeasurements;protected slots:private:// Designer formUi_QtVTKRenderWindows *ui;
};#endif // QtVTKRenderWindows_H
#include "ui_QtVTKRenderWindows.h"
#include "QtVTKRenderWindows.h"#include "vtkBoundedPlanePointPlacer.h"
#include "vtkCellPicker.h"
#include "vtkCommand.h"
#include "vtkDICOMImageReader.h"
#include "vtkDistanceRepresentation.h"
#include "vtkDistanceRepresentation2D.h"
#include "vtkDistanceWidget.h"
#include <vtkGenericOpenGLRenderWindow.h>
#include "vtkHandleRepresentation.h"
#include "vtkImageData.h"
#include "vtkImageMapToWindowLevelColors.h"
#include "vtkImageSlabReslice.h"
#include "vtkInteractorStyleImage.h"
#include "vtkLookupTable.h"
#include "vtkPlane.h"
#include "vtkPlaneSource.h"
#include "vtkPointHandleRepresentation2D.h"
#include "vtkPointHandleRepresentation3D.h"
#include "vtkProperty.h"
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include "vtkRenderWindowInteractor.h"
#include "vtkResliceImageViewer.h"
#include "vtkResliceCursorLineRepresentation.h"
#include "vtkResliceCursorThickLineRepresentation.h"
#include "vtkResliceCursorWidget.h"
#include "vtkResliceCursorActor.h"
#include "vtkResliceCursorPolyDataAlgorithm.h"
#include "vtkResliceCursor.h"
#include "vtkMetaImageReader.h"
#include "vtkResliceImageViewerMeasurements.h"//----------------------------------------------------------------------------
class vtkResliceCursorCallback : public vtkCommand
{
public:static vtkResliceCursorCallback *New(){ return new vtkResliceCursorCallback; }void Execute( vtkObject *caller, unsigned long ev,void *callData ) override{if (ev == vtkResliceCursorWidget::WindowLevelEvent ||ev == vtkCommand::WindowLevelEvent ||ev == vtkResliceCursorWidget::ResliceThicknessChangedEvent){// Render everythingfor (int i = 0; i < 3; i++){this->RCW[i]->Render();}this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();return;}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());// Although the return value is not used, we keep the get calls// in case they had side-effectsrep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor();for (int i = 0; i < 3; i++){vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(this->IPW[i]->GetPolyDataAlgorithm());ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetOrigin());ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetPoint1());ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetPoint2());// If the reslice plane has modified, update it on the 3D widgetthis->IPW[i]->UpdatePlacement();}}// Render everythingfor (int i = 0; i < 3; i++){this->RCW[i]->Render();}this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();}vtkResliceCursorCallback() {}vtkImagePlaneWidget* IPW[3];vtkResliceCursorWidget *RCW[3];
};QtVTKRenderWindows::QtVTKRenderWindows( int vtkNotUsed(argc), char *argv[])
{this->ui = new Ui_QtVTKRenderWindows;this->ui->setupUi(this);
#if 0vtkSmartPointer< vtkDICOMImageReader > reader = vtkSmartPointer<vtkDICOMImageReader >::New();
//  reader->SetDirectoryName(argv[1]);reader->SetDirectoryName("/home/hsw/Qt_workSpace/build-RSVtkLearn_FourPaneViewer-Desktop_Qt_5_12_2_GCC_64bit-Debug/DCM/");
#elsevtkSmartPointer<vtkMetaImageReader> reader = vtkSmartPointer<vtkMetaImageReader>::New();reader->SetFileName("/home/hsw/Downloads/brain/brain.mhd");
#endifreader->Update();int imageDims[3];reader->GetOutput()->GetDimensions(imageDims);for (int i = 0; i < 3; i++){riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New();vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;riw[i]->SetRenderWindow(renderWindow);}this->ui->view1->SetRenderWindow(riw[0]->GetRenderWindow());riw[0]->SetupInteractor(this->ui->view1->GetRenderWindow()->GetInteractor());this->ui->view2->SetRenderWindow(riw[1]->GetRenderWindow());riw[1]->SetupInteractor(this->ui->view2->GetRenderWindow()->GetInteractor());this->ui->view3->SetRenderWindow(riw[2]->GetRenderWindow());riw[2]->SetupInteractor(this->ui->view3->GetRenderWindow()->GetInteractor());for (int i = 0; i < 3; i++){// make them all share the same reslice cursor object.vtkResliceCursorLineRepresentation *rep = vtkResliceCursorLineRepresentation::SafeDownCast(riw[i]->GetResliceCursorWidget()->GetRepresentation());riw[i]->SetResliceCursor(riw[0]->GetResliceCursor());rep->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i);riw[i]->SetInputData(reader->GetOutput());riw[i]->SetSliceOrientation(i);riw[i]->SetResliceModeToAxisAligned();}vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();picker->SetTolerance(0.005);vtkSmartPointer<vtkProperty> ipwProp = vtkSmartPointer<vtkProperty>::New();vtkSmartPointer< vtkRenderer > ren = vtkSmartPointer< vtkRenderer >::New();vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;this->ui->view4->SetRenderWindow(renderWindow);this->ui->view4->GetRenderWindow()->AddRenderer(ren);vtkRenderWindowInteractor *iren = this->ui->view4->GetInteractor();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);color[0] /= 4.0;color[1] /= 4.0;color[2] /= 4.0;riw[i]->GetRenderer()->SetBackground( 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);planeWidget[i]->SetWindowLevel(1358, -27);planeWidget[i]->On();planeWidget[i]->InteractionOn();}vtkSmartPointer<vtkResliceCursorCallback> cbk = vtkSmartPointer<vtkResliceCursorCallback>::New();for (int i = 0; i < 3; i++){cbk->IPW[i] = planeWidget[i];cbk->RCW[i] = riw[i]->GetResliceCursorWidget();riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk );riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::WindowLevelEvent, cbk );riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk );riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResetCursorEvent, cbk );riw[i]->GetInteractorStyle()->AddObserver(vtkCommand::WindowLevelEvent, cbk );// Make them all share the same color map.riw[i]->SetLookupTable(riw[0]->GetLookupTable());planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable());//planeWidget[i]->GetColorMap()->SetInput(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()->GetInput());planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap());}this->ui->view1->show();this->ui->view2->show();this->ui->view3->show();// Set up action signals and slotsconnect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(slotExit()));connect(this->ui->resliceModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(resliceMode(int)));connect(this->ui->thickModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(thickMode(int)));this->ui->thickModeCheckBox->setEnabled(0);connect(this->ui->radioButton_Max, SIGNAL(pressed()), this, SLOT(SetBlendModeToMaxIP()));connect(this->ui->radioButton_Min, SIGNAL(pressed()), this, SLOT(SetBlendModeToMinIP()));connect(this->ui->radioButton_Mean, SIGNAL(pressed()), this, SLOT(SetBlendModeToMeanIP()));this->ui->blendModeGroupBox->setEnabled(0);connect(this->ui->resetButton, SIGNAL(pressed()), this, SLOT(ResetViews()));connect(this->ui->AddDistance1Button, SIGNAL(pressed()), this, SLOT(AddDistanceMeasurementToView1()));
};void QtVTKRenderWindows::slotExit()
{qApp->exit();
}void QtVTKRenderWindows::resliceMode(int mode)
{this->ui->thickModeCheckBox->setEnabled(mode ? 1 : 0);this->ui->blendModeGroupBox->setEnabled(mode ? 1 : 0);for (int i = 0; i < 3; i++){riw[i]->SetResliceMode(mode ? 1 : 0);riw[i]->GetRenderer()->ResetCamera();riw[i]->Render();}
}void QtVTKRenderWindows::thickMode(int mode)
{for (int i = 0; i < 3; i++){riw[i]->SetThickMode(mode ? 1 : 0);riw[i]->Render();}
}void QtVTKRenderWindows::SetBlendMode(int m)
{for (int i = 0; i < 3; i++){vtkImageSlabReslice *thickSlabReslice = vtkImageSlabReslice::SafeDownCast(vtkResliceCursorThickLineRepresentation::SafeDownCast(riw[i]->GetResliceCursorWidget()->GetRepresentation())->GetReslice());thickSlabReslice->SetBlendMode(m);riw[i]->Render();}
}void QtVTKRenderWindows::SetBlendModeToMaxIP()
{this->SetBlendMode(VTK_IMAGE_SLAB_MAX);
}void QtVTKRenderWindows::SetBlendModeToMinIP()
{this->SetBlendMode(VTK_IMAGE_SLAB_MIN);
}void QtVTKRenderWindows::SetBlendModeToMeanIP()
{this->SetBlendMode(VTK_IMAGE_SLAB_MEAN);
}void QtVTKRenderWindows::ResetViews()
{// Reset the reslice image viewsfor (int i = 0; i < 3; i++){riw[i]->Reset();}// Also sync the Image plane widget on the 3D top right view with any// changes to the reslice cursor.for (int i = 0; i < 3; i++){vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(planeWidget[i]->GetPolyDataAlgorithm());ps->SetNormal(riw[0]->GetResliceCursor()->GetPlane(i)->GetNormal());ps->SetCenter(riw[0]->GetResliceCursor()->GetPlane(i)->GetOrigin());// If the reslice plane has modified, update it on the 3D widgetthis->planeWidget[i]->UpdatePlacement();}// Render in response to changes.this->Render();
}void QtVTKRenderWindows::Render()
{for (int i = 0; i < 3; i++){riw[i]->Render();}this->ui->view3->GetRenderWindow()->Render();
}void QtVTKRenderWindows::AddDistanceMeasurementToView1()
{this->AddDistanceMeasurementToView(1);
}void QtVTKRenderWindows::AddDistanceMeasurementToView(int i)
{// remove existing widgets.if (this->DistanceWidget[i]){this->DistanceWidget[i]->SetEnabled(0);this->DistanceWidget[i] = nullptr;}// add new widgetthis->DistanceWidget[i] = vtkSmartPointer< vtkDistanceWidget >::New();this->DistanceWidget[i]->SetInteractor(this->riw[i]->GetResliceCursorWidget()->GetInteractor());// Set a priority higher than our reslice cursor widgetthis->DistanceWidget[i]->SetPriority(this->riw[i]->GetResliceCursorWidget()->GetPriority() + 0.01);vtkSmartPointer< vtkPointHandleRepresentation2D > handleRep =vtkSmartPointer< vtkPointHandleRepresentation2D >::New();vtkSmartPointer< vtkDistanceRepresentation2D > distanceRep =vtkSmartPointer< vtkDistanceRepresentation2D >::New();distanceRep->SetHandleRepresentation(handleRep);this->DistanceWidget[i]->SetRepresentation(distanceRep);distanceRep->InstantiateHandleRepresentation();distanceRep->GetPoint1Representation()->SetPointPlacer(riw[i]->GetPointPlacer());distanceRep->GetPoint2Representation()->SetPointPlacer(riw[i]->GetPointPlacer());// Add the distance to the list of widgets whose visibility is managed based// on the reslice plane by the ResliceImageViewerMeasurements classthis->riw[i]->GetMeasurements()->AddItem(this->DistanceWidget[i]);this->DistanceWidget[i]->CreateDefaultRepresentation();this->DistanceWidget[i]->EnabledOn();
}

3 自己的代码

#ifndef IMAGEMANAGE_H
#define IMAGEMANAGE_H#include <QWidget>
#include <QSplitter>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QResizeEvent>
#include <QtDebug>#include "QVTKOpenGLWidget.h"               //新版本,旧版QVTKWidget
#include "vtkAutoInit.h"
#include "vtkSmartPointer.h"
#include "vtkResliceImageViewer.h"
#include "vtkImagePlaneWidget.h"
#include "vtkDistanceWidget.h"
#include "vtkResliceImageViewerMeasurements.h"
#include "vtkBoundedPlanePointPlacer.h"
#include "vtkCellPicker.h"
#include "vtkCommand.h"
#include "vtkDICOMImageReader.h"
#include "vtkDistanceRepresentation.h"
#include "vtkDistanceRepresentation2D.h"
#include "vtkDistanceWidget.h"
#include <vtkGenericOpenGLRenderWindow.h>
#include "vtkHandleRepresentation.h"
#include "vtkImageData.h"
#include "vtkImageMapToWindowLevelColors.h"
#include "vtkImageSlabReslice.h"
#include "vtkInteractorStyleImage.h"
#include "vtkLookupTable.h"
#include "vtkPlane.h"
#include "vtkPlaneSource.h"
#include "vtkPointHandleRepresentation2D.h"
#include "vtkPointHandleRepresentation3D.h"
#include "vtkProperty.h"
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include "vtkRenderWindowInteractor.h"
#include "vtkResliceImageViewer.h"
#include "vtkResliceCursorLineRepresentation.h"
#include "vtkResliceCursorThickLineRepresentation.h"
#include "vtkResliceCursorWidget.h"
#include "vtkResliceCursorActor.h"
#include "vtkResliceCursorPolyDataAlgorithm.h"
#include "vtkResliceCursor.h"
#include "vtkResliceImageViewerMeasurements.h"class vtkResliceCursorCallback;namespace Ui {
class ImageManage;
}class ImageManage : public QWidget
{Q_OBJECTpublic:explicit ImageManage(QWidget *parent = nullptr);~ImageManage();void setCurrentTab(int temp =0);
public slots:/*** @brief slot_ReaderDICOMImage* @param fn* 读取DICOM文件*/void slot_ReaderDICOMImage(const char* fn);
protected:void resizeEvent(QResizeEvent *event) override;
private:Ui::ImageManage *ui;QSplitter *mSplitterMain = nullptr;QSplitter *mSplitterVertical = nullptr;QSplitter *mSplitterUp = nullptr;QSplitter *mSplitterDown = nullptr;double color[3] = {0,0,0};                                              //颜色vtkSmartPointer<vtkDICOMImageReader> reader = nullptr;                  //读取DICOM文件int imageDims[3] = {0};                                                 //暂时不理解vtkSmartPointer< vtkResliceImageViewer > riw[3];                        //三个二维视图vtkSmartPointer< vtkImagePlaneWidget > planeWidget[3];vtkSmartPointer< vtkDistanceWidget > DistanceWidget[3];                 //测试距离的,暂时没有移植,无用vtkSmartPointer< vtkResliceImageViewerMeasurements > ResliceMeasurements;   //不知道干啥,没有用到vtkSmartPointer<vtkProperty> ipwProp;                                       //属性vtkSmartPointer<vtkCellPicker> picker;                                      //拾取器vtkSmartPointer< vtkRenderer > ren;                                         //3D渲染器vtkSmartPointer<vtkResliceCursorCallback> cbk;                              //回调类};#endif // IMAGEMANAGE_H
#include "imagemanage.h"
#include "ui_imagemanage.h"class vtkResliceCursorCallback : public vtkCommand
{
public:static vtkResliceCursorCallback *New(){ return new vtkResliceCursorCallback; }void Execute( vtkObject *caller, unsigned long ev, void *callData ) override{if (ev == vtkResliceCursorWidget::WindowLevelEvent || ev == vtkCommand::WindowLevelEvent || ev == vtkResliceCursorWidget::ResliceThicknessChangedEvent){// Render everythingfor (int i = 0; i < 3; i++){this->RCW[i]->Render();}this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();
//      return;                                                                 //这里需要注释掉,不然呵呵呵,返回了,还搞个毛线}vtkImagePlaneWidget* ipw = dynamic_cast< vtkImagePlaneWidget* >( caller );
//    qDebug() << "11" << caller << ipw;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);
//    qDebug() << "22" << caller << rcw;if (rcw){vtkResliceCursorLineRepresentation *rep = dynamic_cast<vtkResliceCursorLineRepresentation * >(rcw->GetRepresentation());// Although the return value is not used, we keep the get calls// in case they had side-effectsrep->GetResliceCursorActor()->GetCursorAlgorithm()->GetResliceCursor();for (int i = 0; i < 3; i++){vtkPlaneSource *ps = static_cast< vtkPlaneSource * >(this->IPW[i]->GetPolyDataAlgorithm());ps->SetOrigin(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetOrigin());ps->SetPoint1(this->RCW[i]->GetResliceCursorRepresentation()-> GetPlaneSource()->GetPoint1());ps->SetPoint2(this->RCW[i]->GetResliceCursorRepresentation()->GetPlaneSource()->GetPoint2());// If the reslice plane has modified, update it on the 3D widgetthis->IPW[i]->UpdatePlacement();}}// Render everythingfor (int i = 0; i < 3; i++){this->RCW[i]->Render();}this->IPW[0]->GetInteractor()->GetRenderWindow()->Render();}vtkResliceCursorCallback() {}vtkImagePlaneWidget* IPW[3];vtkResliceCursorWidget *RCW[3];
};static QPoint lastPos;
ImageManage::ImageManage(QWidget *parent) :QWidget(parent),ui(new Ui::ImageManage)
{ui->setupUi(this);/******************窗口大小分割*************************/mSplitterMain = new QSplitter(Qt::Horizontal,this);mSplitterVertical = new QSplitter(Qt::Vertical,mSplitterMain);mSplitterUp = new QSplitter(Qt::Horizontal,mSplitterVertical);mSplitterUp->addWidget(ui->widget_1);mSplitterUp->addWidget(ui->widget_2);mSplitterUp->setStretchFactor(0,1);mSplitterUp->setStretchFactor(1,1);mSplitterDown = new QSplitter(Qt::Horizontal,mSplitterVertical);mSplitterDown->addWidget(ui->widget_3);mSplitterDown->addWidget(ui->widget_4);mSplitterDown->setStretchFactor(0,1);mSplitterDown->setStretchFactor(1,1);mSplitterMain->insertWidget(0,mSplitterVertical);mSplitterMain->insertWidget(1,ui->widget_5);mSplitterMain->setStretchFactor(0,1);               //很魔性啊
}ImageManage::~ImageManage()
{delete ui;
}void ImageManage::setCurrentTab(int temp)
{Q_UNUSED(temp);
}
void ImageManage::slot_ReaderDICOMImage(const char *fn)
{if(!reader){reader = vtkSmartPointer<vtkDICOMImageReader>::New();}reader->SetDirectoryName(fn);                              //这里主要,是文件夹哈,不是文件名reader->Update();                                          //得更新呀,惰性渲染reader->GetOutput()->GetDimensions(imageDims);             //还不理解,翻译为获取维度,注释掉以后三维中有影响for (auto i = 0; i < 3; i++){riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New();vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;riw[i]->SetRenderWindow(renderWindow);}
//    ui->widget_1->SetRenderWindow(riw[0]->GetRenderWindow());riw[0]->SetupInteractor(ui->widget_1->GetRenderWindow()->GetInteractor());riw[0]->SetRenderWindow(ui->widget_1->GetRenderWindow());
//    ui->widget_2->SetRenderWindow(riw[1]->GetRenderWindow());riw[1]->SetupInteractor(ui->widget_2->GetRenderWindow()->GetInteractor());riw[1]->SetRenderWindow(ui->widget_2->GetRenderWindow());
//    ui->widget_3->SetRenderWindow(riw[2]->GetRenderWindow());riw[2]->SetRenderWindow(ui->widget_3->GetRenderWindow());riw[2]->SetupInteractor(ui->widget_3->GetRenderWindow()->GetInteractor());for (int i = 0; i < 3; i++){// make them all share the same reslice cursor object.vtkResliceCursorLineRepresentation *rep =vtkResliceCursorLineRepresentation::SafeDownCast(riw[i]->GetResliceCursorWidget()->GetRepresentation());riw[i]->SetResliceCursor(riw[0]->GetResliceCursor());rep->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i);riw[i]->SetInputData(reader->GetOutput());riw[i]->SetSliceOrientation(i);riw[i]->SetResliceModeToAxisAligned();}picker = vtkSmartPointer<vtkCellPicker>::New();picker->SetTolerance(0.005);ipwProp = vtkSmartPointer<vtkProperty>::New();ren = vtkSmartPointer< vtkRenderer >::New();ui->widget_4->GetRenderWindow()->AddRenderer(ren);for (int i = 0; i < 3; i++){planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New();planeWidget[i]->SetInteractor( ui->widget_4->GetInteractor() );planeWidget[i]->SetPicker(picker);planeWidget[i]->RestrictPlaneToVolumeOn();color[0] = 0;color[1] = 0;color[2] = 0;color[i] = 1;planeWidget[i]->GetPlaneProperty()->SetColor(color);color[0] = 0;color[1] = 0;color[2] = 0;riw[i]->GetRenderer()->SetBackground( 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);planeWidget[i]->SetWindowLevel(1358, -27);planeWidget[i]->On();planeWidget[i]->InteractionOn();}cbk = vtkSmartPointer<vtkResliceCursorCallback>::New();for (int i = 0; i < 3; i++){cbk->IPW[i] = planeWidget[i];cbk->RCW[i] = riw[i]->GetResliceCursorWidget();riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk );riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::WindowLevelEvent, cbk );riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk );riw[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResetCursorEvent, cbk );riw[i]->GetInteractorStyle()->AddObserver(vtkCommand::WindowLevelEvent, cbk );// Make them all share the same color map.riw[i]->SetLookupTable(riw[0]->GetLookupTable());planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable());//planeWidget[i]->GetColorMap()->SetInput(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()->GetInput());planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap());}
//    ui->widget_1->GetRenderWindow()->Render();
//    ui->widget_2->GetRenderWindow()->Render();
//    ui->widget_3->GetRenderWindow()->Render();
//    ui->widget_4->GetRenderWindow()->Render();//十字线for (int i = 0; i < 3; i++){riw[i]->SetResliceMode(1);riw[i]->GetRenderer()->ResetCamera();riw[i]->Render();}
// 还不知道干啥
//    for (int i = 0; i < 3; i++)
//      {
//        riw[i]->SetThickMode(1);
//        riw[i]->Render();
//      }//    for (int i = 0; i < 3; i++)
//      {
//        vtkImageSlabReslice *thickSlabReslice = vtkImageSlabReslice::SafeDownCast(
//            vtkResliceCursorThickLineRepresentation::SafeDownCast(
//              riw[i]->GetResliceCursorWidget()->GetRepresentation())->GetReslice());
//        thickSlabReslice->SetBlendMode(1);
//        riw[i]->Render();
//      }}void ImageManage::resizeEvent(QResizeEvent *event)
{Q_UNUSED(event);mSplitterMain->resize(this->size());
}

4 运行效果

☞ 源码

源码链接:https://github.com/DreamLife-Jianwei/Qt-Vtk

使用方法:☟☟☟


医学四视图-002-四视图实现相关推荐

  1. MVG学习笔记(5) --四视图几何和n视图重建

    四视图几何和n视图重建   可以使用基于张量的方法再进行一步,并定义四个视图中可见的四焦点张量相关实体. 然而这种方法很少使用,因为计算符合其内部约束的四焦点张量的相对困难.   然而,它确实提供了基 ...

  2. mysql实验四数据库查询和视图_数据库-第四次实验报告-视图-t-sql语句

    实验十报告 创建视图 实验目的 1.掌握创建视图的SQL语句的用法. 2.掌握使用企业管管理器创建视图的方法. 3.掌握使用创建视图向导创建视图的方法. 4.掌握查看视图的系统存储过程的用法. 5.掌 ...

  3. mysql实验四数据库查询和视图_实验四 数据库查询和视图.doc

    实验四 数据库查询和视图 测试过程:(实验中出现的问题.错误.解决方法) 问题一:新建查询,调试过程中出现提示无效行或列 问题二:新建查询,调试过程中出现第几行出现错误 解决办法:检查新建的查询,标点 ...

  4. 《Spring In Action(第4版)》阅读总结(四)渲染Web视图

    渲染Web视图 将模型数据渲染为HTML 使用JSP视图 通过tiles定义视图布局 使用Thymealeaf视图 理解视图渲染 控制器只负责处理请求并返回模型数据和视图名 将控制器中请求处理逻辑与视 ...

  5. Mysql第四天笔记04——视图和索引

    目录 1.为什么要使用视图 2.视图分类 3.创建视图 4.修改视图 5.视图上执行DML操作 6.索引 1.为什么要使用视图 限制其它用户对数据库表的访问,因为视图可以有选择性的显示数据库表的一部分 ...

  6. 建立视图实发工资mysql_MYSQL人事工资管理系统--设计视图(四)

    什么是视图? 视图(view)是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的.视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的. 视图相对普通 ...

  7. 数据库 实验四 创建视图,使用视图,修改视图

    1.创建视图 --***① 将Student Course 和sc表中学生的学号,姓名,课程号,课程名,成绩定义为视图V_S_C_G *** CREATE VIEW V_S_C_G ASSELECT ...

  8. 【Android 逆向】IDA 工具使用 ( 十六进制视图 Hex View-1 | 结构体视图 Structures | 枚举视图 Enums | 导入视图 Import | 导出视图 )

    文章目录 一.十六进制视图 Hex View-1 二.结构体视图 Structures 三.枚举视图 Enums 四.导入视图 Import 五.导出视图 Export 一.十六进制视图 Hex Vi ...

  9. 物化视图VS普通视图

    2019独角兽企业重金招聘Python工程师标准>>> 物化视图是一种特殊的物理表,"物化"(Materialized)视图是相对普通视图而言的.普通视图是虚拟表 ...

  10. 表格视图,文本视图和Web视图

    表格视图,文本视图和web视图是具有多种功能的界面元素,它们在iPhone应用程序中有着不同的用途.例如,表格视图可以用来显示简短的选项列表,详细信息的分组列表或者长的项目索引列表.文本视图和web视 ...

最新文章

  1. ThreadLocalMap的enrty的key为什么要设置成弱引用
  2. 如何把pdf转换为txt文档,pdf转txt的好方法
  3. 说说云盘背后的黑科技!
  4. 这里有一份面筋请查收(五)
  5. Ext---CheckBoxGroup的取值和赋值
  6. 密码学专题 信息摘要和数字签名指令
  7. IntelliJ IDEA 中文官方文档
  8. vue 打包html静态页面,vue项目打包、vue项目打包后空白界面解决办法
  9. Shell脚本字符串截取方法总结
  10. socket 实现淘宝秒杀器(抢拍器) 附源码与截图
  11. 深信服虚拟服务器大融合,从虚拟化向云计算转型 深信服选择了超融合
  12. 余世伟视频笔记----如何塑造管理者的性格魅力领袖根性之积极和大度
  13. 微信小程序云开发 1 - 数据库
  14. 学生管理系统IPO图_高校学生考勤管理系统
  15. 怎样用html制作歌词字幕,爱剪辑可以制作歌词字幕吗 教你用爱剪辑加歌词字幕的方法--系统之家...
  16. Magento compare products ajax
  17. Halcon二维码扫描算法总结
  18. 归并排序(递归+非递归)
  19. frequentism-and-bayesianism-chs-ii
  20. Android仿今日头条的开源项目

热门文章

  1. linux怎么撤销关机命令,Linux怎么关机
  2. 怎么解决问卷回收率低的问题?
  3. [飞桨] 目标检测篇 YOLO-V3 学习笔记(一)
  4. 02 Android 植物人大战僵尸-背景图层布置
  5. 工控自动化方案:和利时LE系列PLC数采通讯
  6. 3D132期预测号码是多少
  7. mini usb 管脚图
  8. 音乐人的 NFT 指南
  9. 三峡大学计算机学院毕业答辩问题,毕业答辩会问点什么问题?
  10. 光学efl_光学专业英语