VTK笔记-计算MPR切面-vtkImageReslice类

MPR

  MPR(Multi-planar Reformation),多平面重建;多平面重建是将扫描范围内所有的轴位图像叠加起来,再对某些标线标定的重组线所指定的组织进行冠状位、矢状位、任意角度斜位图像重组。
VTK笔记-计算MPR切面-vtkImageReslice类_第1张图片

MPR的优点

  1.能任意产生新的断层图像,而无需重复扫描;
  2.原图像的密度值被忠实保持到了结果图像上。
  3.曲面重组能在一副图像里展开显示弯曲物体的全长。

MPR的缺点

  1.难以表达复杂的空间结构;
  2.曲面重组易造成假阳性;

  多平面重建(MPR)是CT三维数据呈现的重要内容,其在三维数据的任一点空间位置,采用XY、XZ和YZ三个平面切空间数据得到三个切面分别为轴状面、冠状面和矢状面,而且X/Y/Z三个轴可以绕三维坐标原点任意旋转。

vtkImageReslice

  vtkImageReslice类可以从体数据内的一点沿着不同的方向切出一个平面图像;
  vtkImageReslice是图像几何过滤器的瑞士军刀:它可以以合理高效的任意组合排列、旋转、翻转、缩放、重采样、变形和填充图像数据。置换、重采样和填充等简单操作的效率与专用vtkImagePermute、vtkImageResample和vtkImagePad过滤器类似。  vtkimanageslice非常适合执行以下任务:
    1) 对图像进行简单的旋转、缩放和平移。通常,最好先使用vtkImageChangeInformation使图像居中,这样缩放和旋转就发生在图像的中心而不是左下角。
    2) 通过SetInformationInput()方法对一个数据集进行重采样,以匹配第二个数据集的体素采样,例如为了比较两个图像或合并两个图像。如果两幅图像不在同一坐标空间中,可以通过SetResliceTransform()方法同时应用线性或非线性变换。
    3) 从图像体中提取切片。使用vtkImageReslice可以从体数据中获取到指定的正交、斜切方向的上的切面图像;最方便的方法是使用SetResliceAxesDirectionCosines()指定切片的方向。方向余弦表示输出体积的x、y和z轴。SetOutputDimensionality(2)方法用于指定要输出切片而不是Volume的对象。SetResliceAxesOrigin()方法用于提供切片将通过的(x,y,z)点。可以同时使用ResliceAxes和ResliceTransform,以便从已应用转换的Volume中提取切片。
  3)内容是比较常用的内容,可以提取平行于XY平面、YZ平面、XZ平面的切片,还可以提取斜切切片;
设置切片的步骤是先计算出一个切片的中心位置,计算出切面的变换矩阵(4*4矩阵),前三列分别表示X、Y和Z方向矢量,第四列为切面坐标系原点。通过修改切面坐标系原点,可以得到不同位置的切面图像切面的原点必须过图像内部一点

vtkImageReslice类接口

设置变换矩阵

  变换矩阵是4*4的四阶矩阵,其中左上角的3*3矩阵是3个方向上的向量余弦值;一般情况下,Z轴方向上的方向向量是XY的叉积,也就是Z轴方向会垂直于XY平面;
  三个方向上的方向余弦值:

virtual void SetResliceAxes(vtkMatrix4x4*);
vtkGetObjectMacro(ResliceAxes, vtkMatrix4x4);  
void SetResliceAxesDirectionCosines(double x0, double x1, double x2, double y0, double y1,
     double y2, double z0, double z1, double z2);
void SetResliceAxesDirectionCosines(const double x[3], const double y[3], const double z[3]){
     this->SetResliceAxesDirectionCosines(x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]);
}
void SetResliceAxesDirectionCosines(const double xyz[9]){
	this->SetResliceAxesDirectionCosines(xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5], xyz[6], xyz[7], xyz[8]);
}
void GetResliceAxesDirectionCosines(double x[3], double y[3], double z[3]);
void GetResliceAxesDirectionCosines(double xyz[9]){
     this->GetResliceAxesDirectionCosines(&xyz[0], &xyz[3], &xyz[6]);
}
double* GetResliceAxesDirectionCosines() VTK_SIZEHINT(9){
     this->GetResliceAxesDirectionCosines(this->ResliceAxesDirectionCosines);
     return this->ResliceAxesDirectionCosines;
}

  OutputDimensionality设置为3时,可以通过SetResliceAxes或者SetResliceTransform生成转换矩阵,将体数据进行缩放,扭曲,平移等变换;
  SetResliceAxesOrigin可以指定重新切片轴的原点,是变换矩阵最后一列的前三个元素。如果vtkImageReslice有变换矩阵就修改当前的变换矩阵内的值,如果没有,就创建新的变换矩阵;

void SetResliceAxesOrigin(double x, double y, double z);
void SetResliceAxesOrigin(const double xyz[3]){
	this->SetResliceAxesOrigin(xyz[0], xyz[1], xyz[2]);
}
void GetResliceAxesOrigin(double xyz[3]);
double* GetResliceAxesOrigin() VTK_SIZEHINT(3){
	this->GetResliceAxesOrigin(this->ResliceAxesOrigin);
	return this->ResliceAxesOrigin;
}

  设定由vtkTransform表示变换矩阵信息:

virtual void SetResliceTransform(vtkAbstractTransform*);
vtkGetObjectMacro(ResliceTransform, vtkAbstractTransform);

设置输出维度

  OutputDimensionality表示输出的维度有四种:1、2、3或0,默认值是3。不过一般切片的话,就是二维图像,设置为2;
  如果维度是2D,则输出的Z范围被强制为(0,0),输出的Z原点被强制为0.0(即输出范围被限制在xy平面)。如果维度是1D,则输出范围限制在x轴上。对于0D,输出范围由位于(0,0,0)的单个体素组成。

vtkSetMacro(OutputDimensionality, int);
vtkGetMacro(OutputDimensionality, int);

设置图像输入

  这里vtkImageReslice类输入的一般就是vtkImageData,vtkImageData为三维体数据,毕竟是从体数据中获取切片图像的嘛。
  使用SetInputConnection和SetInputData方法,SetInformationInput用来设置渲染管线中的信息,之前有讲过;

virtual void SetInformationInput(vtkImageData*);
vtkGetObjectMacro(InformationInput, vtkImageData);

设置标识

  TransformInputSampling用来指定是否根据重切片轴的方向余弦原点变换输入的间距、原点和范围,然后再将其应用为默认输出间距、原点和范围(默认值:true);

vtkSetMacro(TransformInputSampling, vtkTypeBool);
vtkBooleanMacro(TransformInputSampling, vtkTypeBool);
vtkGetMacro(TransformInputSampling, vtkTypeBool);

  AutoCropOutput项可以确保输出的范围足够大时,不会裁剪任何数据;默认值是禁用的。

vtkSetMacro(AutoCropOutput, vtkTypeBool);
vtkBooleanMacro(AutoCropOutput, vtkTypeBool);
vtkGetMacro(AutoCropOutput, vtkTypeBool);

  Wrap包裹标识;

vtkSetMacro(Wrap, vtkTypeBool);
vtkGetMacro(Wrap, vtkTypeBool);
vtkBooleanMacro(Wrap, vtkTypeBool);

  Mirror镜像标识;

vtkSetMacro(Mirror, vtkTypeBool);
vtkGetMacro(Mirror, vtkTypeBool);
vtkBooleanMacro(Mirror, vtkTypeBool);

  用Border设置是否将外观输入边界延伸半个体素(默认值:On)。
  这将更改在输入图像的边界处处理插值的方式:如果输出体素的中心超出输入图像的边缘,但在边缘的半体素宽度范围内(使用输入体素宽度),则计算输出体素的值,如同输入的边缘体素被复制到输入图像的边缘。如果“Mirror”或“Wrap”处于启用状态,则此操作无效。

vtkSetMacro(Border, vtkTypeBool);
vtkGetMacro(Border, vtkTypeBool);
vtkBooleanMacro(Border, vtkTypeBool);

  当Border为On开启状态时,用BorderThickness设置图像的边框厚度(默认值:0.5);

vtkSetMacro(BorderThickness, double);
vtkGetMacro(BorderThickness, double);

  InterpolationMode是vtkImageReslice类使用的插值模式,默认为nearest neighbor插值;
  SetInterpolator设置要使用的插值器vtkAbstractImageInterpolator。默认插值器支持最近(Nearest)、线性(Linear)和三次插值模式(Cubic);

vtkSetClampMacro(InterpolationMode, int, VTK_RESLICE_NEAREST, VTK_RESLICE_CUBIC);
vtkGetMacro(InterpolationMode, int);
void SetInterpolationModeToNearestNeighbor() { this->SetInterpolationMode(VTK_RESLICE_NEAREST); }
void SetInterpolationModeToLinear() { this->SetInterpolationMode(VTK_RESLICE_LINEAR); }
void SetInterpolationModeToCubic() { this->SetInterpolationMode(VTK_RESLICE_CUBIC); }
virtual const char* GetInterpolationModeAsString();  
virtual void SetInterpolator(vtkAbstractImageInterpolator* sampler);
virtual vtkAbstractImageInterpolator* GetInterpolator();
void SetInterpolate(int t) {
     if (t && !this->GetInterpolate()) {
       this->SetInterpolationModeToLinear();
     }
     else if (!t && this->GetInterpolate()){
       this->SetInterpolationModeToNearestNeighbor();
     }
}
void InterpolateOn() { this->SetInterpolate(1); }
void InterpolateOff() { this->SetInterpolate(0); }
int GetInterpolate() { return (this->GetInterpolationMode() != VTK_RESLICE_NEAREST); }

  SlabMode是板模式,用来生成厚切片(类似MIP功能),默认值是Mean。如果调用SetSlabNumberOfSlices(N)时N大于1,则每个输出片实际上是N个片的组合。使用此方法需要指定要使用的合成模式。合成模式有四种:Min(最小)、Max(最大)、Mean(平均值)和Sum(累加和);

vtkSetClampMacro(SlabMode, int, VTK_IMAGE_SLAB_MIN, VTK_IMAGE_SLAB_SUM);
vtkGetMacro(SlabMode, int);
void SetSlabModeToMin() { this->SetSlabMode(VTK_IMAGE_SLAB_MIN); }
void SetSlabModeToMax() { this->SetSlabMode(VTK_IMAGE_SLAB_MAX); }
void SetSlabModeToMean() { this->SetSlabMode(VTK_IMAGE_SLAB_MEAN); }
void SetSlabModeToSum() { this->SetSlabMode(VTK_IMAGE_SLAB_SUM); }
virtual const char* GetSlabModeAsString();

  SlabNumberOfSlices用来设置Slab模式下,合并时用到的图层个数;

vtkSetMacro(SlabNumberOfSlices, int);
vtkGetMacro(SlabNumberOfSlices, int);

  SlabTrapezoidIntegration设定使用梯形积分进行板计算。Slab模式合并时,做加法和平均数的时候,把第一片和最后一片的权重减半。默认情况下,它处于禁用状态。

vtkSetMacro(SlabTrapezoidIntegration, vtkTypeBool);
vtkBooleanMacro(SlabTrapezoidIntegration, vtkTypeBool);
vtkGetMacro(SlabTrapezoidIntegration, vtkTypeBool);

  SlabSliceSpacingFraction是板间距,是输出片间距的一部分。
  当选择了各种slab模式中的一种时,通过生成几个“临时”输出片,然后根据slab模式组合它们来生成每个输出片。默认情况下,这些临时切片之间的间距是OutputSpacing的Z分量。此方法将这些临时切片之间的间距设置为输出间距的一小部分。

vtkSetMacro(SlabSliceSpacingFraction, double);
vtkGetMacro(SlabSliceSpacingFraction, double);

  优化标识Optimization,打开和关闭优化(默认为打开,仅应出于测试目的关闭它们);

vtkSetMacro(Optimization, vtkTypeBool);
vtkGetMacro(Optimization, vtkTypeBool);
vtkBooleanMacro(Optimization, vtkTypeBool);

  设置输出标量数据类型,有 VTK_CHAR, VTK_SIGNED_CHAR, VTK_UNSIGNED_CHAR, VTK_SHORT, VTK_UNSIGNED_SHORT, VTK_INT, VTK_UNSIGNED_INT, VTK_FLOAT, or VTK_DOUBLE,除此之外的类型均不支持,如果设定了输出类型,那么标量数值就被限定在类型的有效范围内。

vtkSetMacro(OutputScalarType, int);
vtkGetMacro(OutputScalarType, int);

  SetBackgroundColor对多分量图像设置背景颜色,这里背景颜色是不是数值的意思,暂时还没弄明白;
  SetBackgroundLevel对单通道的灰度图像设置设置背景灰度值;
  SetStencilData使用模具将计算限制到输出的特定区域。输出模具的“outside”的部分将被清除为背景色(莫非是刚才的背景色)。
  SetGenerateStencilOutput设置是否生成一个输出模具,该模具定义哪些像素被插值,哪些像素超出输入范围。

vtkSetVector4Macro(BackgroundColor, double);
vtkGetVector4Macro(BackgroundColor, double);  
void SetBackgroundLevel(double v) { this->SetBackgroundColor(v, v, v, v); }
double GetBackgroundLevel() { return this->GetBackgroundColor()[0]; }  
void SetStencilData(vtkImageStencilData* stencil);
vtkImageStencilData* GetStencil();  
vtkSetMacro(GenerateStencilOutput, vtkTypeBool);
vtkGetMacro(GenerateStencilOutput, vtkTypeBool);
vtkBooleanMacro(GenerateStencilOutput, vtkTypeBool);  
vtkAlgorithmOutput* GetStencilOutputPort() { return this->GetOutputPort(1); }
vtkImageStencilData* GetStencilOutput();
void SetStencilOutput(vtkImageStencilData* stencil);

实例

代码

  1.使用vtkMetaImageReader类读取一个.mha文件;
  mha文件一定要和.raw文件放在同一个文件夹,要不然会报错;

ERROR: In I:\v-vtk\VTK-8.2.0\IO\Image\vtkMetaImageReader.cxx, line 237
vtkMetaImageReader (013DEC00): MetaImage cannot read data from file.

  2.计算获取切面的变换矩阵vtkMatrix4x4信息;
  3.使用vtkImageReslice类获取切面数据;
  4.进行渲染显示;

#include "vtkSmartPointer.h"
#include "vtkMetaImageReader.h"
#include "vtkImageData.h"
#include "vtkMatrix4x4.h"
#include "vtkImageReslice.h"
#include "vtkLookupTable.h"
#include "vtkImageMapToColors.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyleImage.h"
#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

using namespace std;
int main(){
	vtkNew<vtkMetaImageReader> reader;
	reader->SetFileName("D:\\data\\brain.mhd");
	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]);

	static double axialElements[16] = {
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1
	};

	vtkNew<vtkMatrix4x4> resliceAxes;
	resliceAxes->DeepCopy(axialElements);
	resliceAxes->SetElement(0, 3, center[0]);
	resliceAxes->SetElement(1, 3, center[1]);
	resliceAxes->SetElement(2, 3, center[2]);

	vtkNew<vtkImageReslice> reslice;
	reslice->SetInputConnection(reader->GetOutputPort());
	reslice->SetOutputDimensionality(2);
	reslice->SetResliceAxes(resliceAxes);
	reslice->SetInterpolationModeToLinear();

	vtkNew<vtkLookupTable> colorTable;
	colorTable->SetRange(0, 1000);
	colorTable->SetValueRange(0.0, 1.0);
	colorTable->SetSaturationRange(0.0, 0.0);
	colorTable->SetRampToLinear();
	colorTable->Build();

	vtkNew<vtkImageMapToColors> colorMap;
	colorMap->SetLookupTable(colorTable);
	colorMap->SetInputConnection(reslice->GetOutputPort());

	vtkNew<vtkImageActor> imgActor;
	imgActor->GetMapper()->SetInputConnection(colorMap->GetOutputPort());

	vtkNew<vtkRenderer> renderer;
	renderer->AddActor(imgActor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->Render();
	renderWindow->SetSize(640, 480);
	renderWindow->SetWindowName("ImageResliceExample");

	vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
	vtkNew<vtkInteractorStyleImage> imagestyle;

	renderWindowInteractor->SetInteractorStyle(imagestyle);
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindowInteractor->Initialize();
	renderWindowInteractor->Start();
	return 0;
}

VTK笔记-计算MPR切面-vtkImageReslice类_第2张图片

鼠标点击进行图层切换

#include "pch.h"
#include "TestDicomImage.h"
#include "vtk_include.h"
#include "dcmtk\config\osconfig.h"
#include "dcmtk\dcmdata\dctk.h"
#include   /* for dcmjpeg decoders */
#include 
#include 		//for JPEG-LS decode
#include 		//for JPEG-LS encode

#include 
#include 

using namespace std;
class vtkImageInteractionCallback : public vtkCommand{
public:
	static vtkImageInteractionCallback *New(){
		return new vtkImageInteractionCallback;
	}
	vtkImageInteractionCallback(){
		this->Slicing = 0;
		this->ImageReslice = 0;
		this->Interactor = 0;
	}
	void SetImageReslice(vtkImageReslice *reslice){
		this->ImageReslice = reslice;
	}
	void SetImageMapToColors(vtkImageMapToColors *mapToColors){
		this->mapToColors = mapToColors;
	}
	vtkImageReslice *GetImageReslice(){
		return this->ImageReslice;
	}
	void SetInteractor(vtkRenderWindowInteractor *interactor){
		this->Interactor = interactor;
	}
	vtkRenderWindowInteractor *GetInteractor(){
		return this->Interactor;
	}
	virtual void Execute(vtkObject *, unsigned long event, void *){
		vtkRenderWindowInteractor *interactor = this->GetInteractor();
		int lastPos[2];
		interactor->GetLastEventPosition(lastPos);
		int currPos[2];
		interactor->GetEventPosition(currPos);

		if (event == vtkCommand::LeftButtonPressEvent){
			this->Slicing = 1;
		}
		else if (event == vtkCommand::LeftButtonReleaseEvent){
			this->Slicing = 0;
		}
		else if (event == vtkCommand::MouseMoveEvent){
			if (this->Slicing){
				vtkImageReslice *reslice = this->ImageReslice;
				// Increment slice position by deltaY of mouse
				int deltaY = lastPos[1] - currPos[1];
				reslice->Update();
				double sliceSpacing = reslice->GetOutput()->GetSpacing()[2];
				vtkMatrix4x4 *matrix = reslice->GetResliceAxes();
				// move the center point that we are slicing through
				double point[4] = {0.0};
				double center[4];				
				point[2] = sliceSpacing * deltaY;				
				matrix->MultiplyPoint(point, center);
				matrix->SetElement(0, 3, center[0]);
				matrix->SetElement(1, 3, center[1]);
				matrix->SetElement(2, 3, center[2]);
				mapToColors->Update();
				interactor->Render();
			}
			else{
				vtkInteractorStyle *style = vtkInteractorStyle::SafeDownCast(interactor->GetInteractorStyle());
				if (style){
					style->OnMouseMove();
				}
			}
		}
	}

private:
	int Slicing;
	vtkImageReslice *ImageReslice;
	vtkRenderWindowInteractor *Interactor;
	vtkImageMapToColors *mapToColors;
};

void TestDicomImage::Test(){
	DJDecoderRegistration::registerCodecs();
	DJLSEncoderRegistration::registerCodecs();		//JPEG-LS encoder registerCodecs
	DJLSDecoderRegistration::registerCodecs();		//JPEG-LS decoder registerCodecs
	
	int count = 273;
	int single_img = 512 * 512;
	int size_all = count * single_img;
	short* pBuf = new short[size_all] {0};

	for (int i = 1; i < 274; i++)	{
		string fileName = "G:\\data\\" + to_string(i) + ".DCM";
		DcmFileFormat *myFileFormat = new DcmFileFormat;
		OFCondition cond = myFileFormat->loadFile(fileName.c_str());
		DcmElement* pElement = nullptr;
		myFileFormat->getDataset()->chooseRepresentation(EXS_DeflatedLittleEndianExplicit, NULL);
		myFileFormat->getDataset()->findAndGetElement(DCM_PixelData, pElement);
		if (pElement != NULL) {
			int size = pElement->getLength() / 2;
			OFCondition cond = pElement->loadAllDataIntoMemory();
			if (cond.good()) {
				Uint16 * ptr;
				cond = pElement->getUint16Array(ptr);
				if (cond.good()) {
					memcpy(pBuf + (i - 1)*single_img, ptr, size * sizeof(short));
				}
			}
		}
		delete myFileFormat;
	}

	int extent[6] = { 0,511,0,511,0,272 };
	double spacing[3] = { 0.3, 0.3, 0.75 };
	double origin[3] = { 0 };
	double center[3] = { 0 };
	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]);

	vtkNew<vtkShortArray> dataArray;
	dataArray->SetArray(pBuf, size_all, 1);
	vtkNew<vtkImageData> pALLImageData;

	pALLImageData->AllocateScalars(VTK_SHORT, 1);
	pALLImageData->SetDimensions(512, 512, 273);
	pALLImageData->GetPointData()->SetScalars(dataArray);
	pALLImageData->SetSpacing(spacing);
	pALLImageData->SetOrigin(origin);
	
	static double axialElements[16] = {
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1
	};

	vtkNew<vtkMatrix4x4> resliceAxes;
	resliceAxes->DeepCopy(axialElements);
	resliceAxes->SetElement(0, 3, center[0]);
	resliceAxes->SetElement(1, 3, center[1]);
	resliceAxes->SetElement(2, 3, center[2]);

	vtkNew<vtkImageReslice> reslice;
	reslice->SetInputData(pALLImageData);
	reslice->SetOutputDimensionality(2);
	reslice->SetResliceAxes(resliceAxes);
	reslice->SetInterpolationModeToLinear();

	vtkNew<vtkLookupTable> colorTable;
	colorTable->SetRange(0, 1000);
	colorTable->SetValueRange(0.0, 1.0);
	colorTable->SetSaturationRange(0.0, 0.0);
	colorTable->SetRampToLinear();
	colorTable->Build();

	vtkNew<vtkImageMapToColors> colorMap;
	colorMap->SetLookupTable(colorTable);
	colorMap->SetInputConnection(reslice->GetOutputPort());
	colorMap->Update();

	vtkNew<vtkImageActor> imgActor;
	imgActor->SetInputData(colorMap->GetOutput());

	vtkNew<vtkRenderer> renderer;
	renderer->AddActor(imgActor);
	renderer->SetBackground(0.3, 0.4, 0.3);

	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->SetSize(500, 500);
	renderWindow->AddRenderer(renderer);

	vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
	vtkNew<vtkInteractorStyleImage> imagestyle;

	renderWindowInteractor->SetInteractorStyle(imagestyle);
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindowInteractor->Initialize();

	vtkNew<vtkImageInteractionCallback> callback;
	callback->SetImageReslice(reslice);
	callback->SetInteractor(renderWindowInteractor);
	callback->SetImageMapToColors(colorMap);

	imagestyle->AddObserver(vtkCommand::MouseMoveEvent, callback);
	imagestyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);
	imagestyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);
	renderWindowInteractor->Start();
}

参考资料

1.vtkImageReslice Class Reference

你可能感兴趣的:(VTK笔记-切面重建,VTK)