前言

“VTK图形图像开发进阶_张晓东_罗火灵”的学习笔记。
东灵工作室 教程系列导航:http://blog.csdn.net/www_doling_net/article/details/8763686

学习资料

VTK官网学习地址:https://vtk.org/doc/nightly/html/

学习笔记

区域提取

感兴趣区域(Volume of Interest, VOI)是图像内部的一块子区域。在VTK中,vtkExtractVOI类可根据用户指定的区域范围提取子图像。该Filter的输入和输出都是一个 vtklmageData,因此其结果可以直接作为图像保存。

	vtkSmartPointer<vtkBMPReader> reader =
		vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName (argv[1]);
	reader->Update();
	
	int dims[3];   //获取图像大小
	reader->GetOutput()->GetDimensions(dims);	
	
	vtkSmartPointer<vtkExtractVOI> extractVOI = vtkSmartPointer<vtkExtractVOI>::New();
	extractVOI->SetInputConnection(reader->GetOutputPort());
	//设置提取的区域大小(xmin,xmax,ymin,ymax,zmin,zmax)
	extractVOI->SetVOI(dims[0]/4.,3.*dims[0]/4.,dims[1]/4.,3.*dims[1]/4., 0, 0);
	extractVOI->Update();
	//显示原图
	vtkSmartPointer<vtkImageActor> originalActor = vtkSmartPointer<vtkImageActor>::New();
	originalActor->SetInputData(reader->GetOutput());
	//显示截图
	vtkSmartPointer<vtkImageActor> voiActor = vtkSmartPointer<vtkImageActor>::New();
	voiActor->SetInputData(extractVOI->GetOutput());

三维图像切片提取
切片是指三维图像中的一个切面对应的图像。切面可以是过图像内部一点且平行于XY、YZ、XZ平面的平面,也可以是任意的过三维图像内部一点任意方向的平面。通过提取切片可以方便的浏览和分析图像内部组织结构,是医学图像浏览软件中的一个重要的功能。在VTK中vtkImageReslice类实现图像切片提取功能。
程序展示 滑动鼠标切换三维图像切面
首先通过vtkMetaImageReader读取一张医学三维图像,并获取得到图像范围(extent),原点和像素间隔;由这三个参数可以计算图像的中心位置center;接下来定义了切面的变换矩阵axialElements,该矩阵的前三列分别表示x、y和z方向向量,第四列为中心点坐标;
在这里插入图片描述

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
#include <vtkSmartPointer.h>
#include <vtkImageReader2.h>
#include <vtkMatrix4x4.h>
#include <vtkImageReslice.h>
#include <vtkLookupTable.h>
#include <vtkImageMapToColors.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkCommand.h>
#include <vtkImageData.h>
#include <vtkMetaImageReader.h>
#include <vtkImageCast.h>

class vtkImageInteractionCallback : public vtkCommand
{
public:
    static vtkImageInteractionCallback *New()
    {
        return new vtkImageInteractionCallback;
    }

    vtkImageInteractionCallback()
    {
        this->Slicing = 0;
        this->ImageReslice = 0;
        this->Interactor = 0;
    }
    //设置vtkImageSclice对象,vtkImageSclice根据设置的变换矩阵提取三维图像切片
    void SetImageReslice(vtkImageReslice *reslice)
    {
        this->ImageReslice = reslice;
    }

    void SetImageMapToColors(vtkImageMapToColors *mapToColors)
    {
        this->mapToColors = mapToColors;
    }

    vtkImageReslice *GetImageReslice()
    {
        return this->ImageReslice;
    }
    //设置vtkRenderWindowInteractor对象,负责提取切面后刷新视图
    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];
                double center[4];
                point[0] = 0.0;
                point[1] = 0.0;
                point[2] = sliceSpacing * deltaY;
                point[3] = 1.0;
                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;
};

int main()
{
    vtkSmartPointer<vtkMetaImageReader> reader = vtkSmartPointer<vtkMetaImageReader>::New();
    reader->SetFileName ("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap05/data/brain.mhd" );//.mhd和.raw要放在一起
    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]);

    /*
    切面的变换矩阵:前三列分别表示xyz方向矢量 第四列为切面坐标系原点。
    通过修改切面坐标系原点 可以得到不同位置的切面图像
    The first column of the matrix specifies the x-axis vector (the fourth element must be set to zero), the second column specifies the y-axis, and the third column the z-axis. The fourth column is the origin of the axes (the fourth element must be set to one).
    An alternative to SetResliceAxes() is to use SetResliceAxesDirectionCosines() to set the directions of the axes and SetResliceAxesOrigin() to set the origin of the axes.
    */
    //切面坐标系与图像坐标系数一致
    static double axialElements[16] = {
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    //提取平行于XZ平面的切片:
    static double coronalElements[16] = {
     1, 0, 0, 0,
     0, 0, 1, 0,
     0,-1, 0, 0,
     0, 0, 0, 1 };
    //提取平行于YZ平面的切片:
    static double sagittalElements[16] = {
    0, 0,-1, 0,
    1, 0, 0, 0,
    0,-1, 0, 0,
    0, 0, 0, 1 };
    //提取斜切切片:
    static double obliqueElements[16] = {
    1, 0, 0, 0,
    0, 0.866025, -0.5, 0,
    0, 0.5, 0.866025, 0,
    0, 0, 0, 1 };
    vtkSmartPointer<vtkMatrix4x4> resliceAxes =
        vtkSmartPointer<vtkMatrix4x4>::New();
    resliceAxes->DeepCopy(axialElements);

    resliceAxes->SetElement(0, 3, center[0]);
    resliceAxes->SetElement(1, 3, center[1]);
    resliceAxes->SetElement(2, 3, center[2]);

    vtkSmartPointer<vtkImageReslice> reslice = vtkSmartPointer<vtkImageReslice>::New();
    reslice->SetInputConnection(reader->GetOutputPort());
    reslice->SetOutputDimensionality(2);             //指定输出的图像为一个二维图像
    reslice->SetResliceAxes(resliceAxes);            //设置变换矩阵
    reslice->SetInterpolationModeToLinear();         //指定切面提取中的插值方式为线性插值
    //reslice->SetInterpolationModeToCubic();          //三次线性插值
   // reslice->SetInterpolationModeToNearestNeighbor();//最近临插值

    vtkSmartPointer<vtkLookupTable> colorTable = vtkSmartPointer<vtkLookupTable>::New();
    colorTable->SetRange(0, 1000);
    colorTable->SetValueRange(0.0, 1.0);
    colorTable->SetSaturationRange(0.0, 0.0);
    colorTable->SetRampToLinear();
    colorTable->Build();

    vtkSmartPointer<vtkImageMapToColors> colorMap =
        vtkSmartPointer<vtkImageMapToColors>::New();
    colorMap->SetLookupTable(colorTable);
    colorMap->SetInputConnection(reslice->GetOutputPort());
    colorMap->Update();

    vtkSmartPointer<vtkImageActor> imgActor =
        vtkSmartPointer<vtkImageActor>::New();
    imgActor->SetInputData(colorMap->GetOutput());

    vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(imgActor);
    renderer->SetBackground(1, 1, 1);

    vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize(500, 500);
    renderWindow->AddRenderer(renderer);

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    vtkSmartPointer<vtkInteractorStyleImage> imagestyle =
        vtkSmartPointer<vtkInteractorStyleImage>::New();

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

    vtkSmartPointer<vtkImageInteractionCallback> callback =
        vtkSmartPointer<vtkImageInteractionCallback>::New();
    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();
    return EXIT_SUCCESS;
}

直方图统计

灰度图像直方图
直方图统计是图像处理中一种非常重要的操作。VTK中的vtklmageAccumulate类用于实现 直方图统计功能。它将每个组分的数值范围划分为离散的间隔,然后统计每个灰度间隔上的像素 数目。
在这里插入图片描述

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
#include <vtkActor.h>
#include <vtkBarChartActor.h>
#include <vtkFieldData.h>
#include <vtkImageAccumulate.h>
#include <vtkImageData.h>
#include <vtkIntArray.h>
#include <vtkJPEGReader.h>
#include <vtkLegendBoxActor.h>
#include <vtkProperty2D.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkTextProperty.h>

//测试图像:../data/lena-gray.jpg
int main(int argc, char* argv[])
{
    //读取一副灰度图像 灰度范围0-255
    vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
    reader->SetFileName ("C:/Users/jbyyy/Desktop/lena-gray.jpg");
    reader->Update();

    int bins   = 16;    //灰度直方图的间隔数目
    int comps  = 1;     //一个组分

    //直方图
    vtkSmartPointer<vtkImageAccumulate> histogram = vtkSmartPointer<vtkImageAccumulate>::New();
    histogram->SetInputData(reader->GetOutput());
    //设置要计算每个组分的直方图的最小和最大值.
    //该例是灰度图像只有一个组分,第二和第三个组分设置为0;第一组分直方图维数为bins,其最小和最大范围为0和bins-1
    histogram->SetComponentExtent(0, bins-1, 0, 0, 0, 0);
    //设置统计每个组分直方图时的起始灰度值,这里设置为0,表示灰度从0开始统计直方图.
    //如果图像灰度范围为[1000,2000],其起始灰度应设置为1000
    histogram->SetComponentOrigin(0, 0, 0);
    //设置直方图每个间隔代表的灰度范围,当图像灰度范围为[1000,2000],统计直方图间隔数bins为100时
    //对应的space应该设置为SetComponentSpacing(100,0,0)
    histogram->SetComponentSpacing(256.0/bins, 0, 0);
    histogram->Update();

    int* output = static_cast<int*>(histogram->GetOutput()->GetScalarPointer());    //得到直方图数组

    vtkSmartPointer<vtkIntArray> frequencies = vtkSmartPointer<vtkIntArray>::New();
    frequencies->SetNumberOfComponents(1);

    //将直方图数组存储到vtkIntArray数组frequencies中
    for(int j = 0; j < bins; ++j)
    {
        for(int i=0; i<comps; i++)
        {
            frequencies->InsertNextTuple1(*output++);
        }
    }

    //将vtkImageData类型的直方图数据转换为vtkDataObject类型
    vtkSmartPointer<vtkDataObject> dataObject =
        vtkSmartPointer<vtkDataObject>::New();
    dataObject->GetFieldData()->AddArray( frequencies );

    vtkSmartPointer<vtkBarChartActor> barChart = vtkSmartPointer<vtkBarChartActor>::New();
    barChart->SetInput(dataObject);     //vtkBarChartActor对象接收vtkDataObject对象作为输入
    barChart->SetTitle("Histogram");
    barChart->GetPositionCoordinate()->SetValue(0.1,0.1,0.0);   //设置窗口中显示图表的所在矩形的左下角点坐标,注意:VTK的坐标系原点位于左下角点
    barChart->GetPosition2Coordinate()->SetValue(0.9,0.9,0.0);  //设置窗口中显示图表的所在矩形的右上角点坐标
    barChart->GetProperty()->SetColor(0.1,0.2,0.3);
    barChart->GetTitleTextProperty()->SetColor(0.3,0.2,0.1);
    barChart->GetLabelTextProperty()->SetColor(0.1,0.5,0.5);
    barChart->GetLegendActor()->SetNumberOfEntries(dataObject->GetFieldData()->GetArray(0)->GetNumberOfTuples());
    barChart->LegendVisibilityOff();
    barChart->LabelVisibilityOff();

    double colors[3][3] = {
        { 1, 0, 0 },
        { 0, 1, 0 },
        { 0, 0, 1 } };

    int count = 0;
    for( int i = 0; i < bins; ++i )
    {
        for( int j = 0; j < comps; ++j )
        {
            barChart->SetBarColor( count++, colors[j] );
        }
    }

    vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(barChart);
    renderer->SetBackground(1.0, 1.0, 1.0);

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

    vtkSmartPointer<vtkRenderWindowInteractor> interactor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);

    interactor->Initialize();
    interactor->Start();

    return EXIT_SUCCESS;
}

彩色图像直方图
彩色图像有三个颜色通道,因此需要提取RGB三个通道数据分别计算直方图。每个通道 计算直方图的方法与灰度图像直方图的计算方法一致。
在这里插入图片描述

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)

#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkImageAccumulate.h>
#include <vtkImageData.h>
#include <vtkImageExtractComponents.h>
#include <vtkBMPReader.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkXYPlotActor.h>
#include <vtkAxisActor2D.h>
#include <vtkProperty2D.h>
#include <vtkTextProperty.h>

//测试图像:../data/lena.bmp
int main(int argc, char* argv[])
{
    vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
    reader->SetFileName("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap05/data/lena.bmp");
    reader->Update();
    //获取图片组分
    int numComponents = reader->GetOutput()->GetNumberOfScalarComponents();
    //该类可以用来显示二维曲线,它可以接收多个输入数据,
    //如本例输入了三条曲线,分别是图像红色分量直方图区域,绿色分量直方图曲线和蓝色分量直方图曲线。
    vtkSmartPointer<vtkXYPlotActor> plot = vtkSmartPointer<vtkXYPlotActor>::New();
    plot->ExchangeAxesOff();
    plot->SetLabelFormat( "%g" );
    plot->SetXTitle( "Intensity" );
    plot->SetYTitle( "Frequency" );
    plot->SetXValuesToValue();
    plot->GetProperty()->SetColor(0.0, 0.0, 0.0);
    plot->GetAxisLabelTextProperty()->SetColor(0.0, 0.0, 0.0);
    plot->GetAxisTitleTextProperty()->SetColor(0.0, 0.0, 0.0);
    
    
    double colors[3][3] = {
        { 1, 0, 0 },
        { 0, 1, 0 },
        { 0, 0, 1 }
    };
    
    const char* labels[3] = { "Red", "Green", "Blue" };
    
    int xmax = 0;   //最大横坐标
    int ymax = 0;   //最大纵坐标
    
    for( int i = 0; i < numComponents; ++i )
    {
        //彩色图像不能直接计算直方图,因此需要先提取每个通道图像
        vtkSmartPointer<vtkImageExtractComponents> extract =
                vtkSmartPointer<vtkImageExtractComponents>::New();
        extract->SetInputConnection( reader->GetOutputPort() );
        extract->SetComponents( i );
        extract->Update();
        
        double range[2];
        extract->GetOutput()->GetScalarRange( range );
        //直方图间隔的个数为:最大灰度值减去最小灰度值,再减1
        int extent = static_cast<int>(range[1])-static_cast<int>(range[0])-1;
        
        vtkSmartPointer<vtkImageAccumulate> histogram =
                vtkSmartPointer<vtkImageAccumulate>::New();
        histogram->SetInputConnection( extract->GetOutputPort() );
        histogram->SetComponentExtent( 0,extent, 0,0, 0,0);   //直方图间隔的个数
        histogram->SetComponentOrigin( range[0],0,0 );        //灰度起点为图像的最小灰度值
        histogram->SetComponentSpacing( 1,0,0 );              //直方图的间隔取(1, 0, 0),即每个灰度计算统计一个频率
        histogram->SetIgnoreZero( 1 );                        //在统计直方图时,像素值为0的像素不进行统计
        histogram->Update();
        
        if( range[1] > xmax )
        {
            xmax = range[1];
        }
        if( histogram->GetOutput()->GetScalarRange()[1] > ymax )
        {
            ymax = histogram->GetOutput()->GetScalarRange()[1];
        }
        
        plot->AddDataSetInput(histogram->GetOutput());
        plot->SetPlotColor(i,colors[i]);
        plot->SetPlotLabel(i,labels[i]);
        plot->LegendOn();
    }
    //设置X轴和Y轴的数据范围
    plot->SetXRange( 0, xmax);
    plot->SetYRange( 0, ymax);
    
    vtkSmartPointer<vtkRenderer> renderer =
            vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(plot);
    renderer->SetBackground(1.0, 1.0, 1.0);
    
    vtkSmartPointer<vtkRenderWindow> renderWindow =
            vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer( renderer );
    renderWindow->SetSize(640, 480);
    renderWindow->Render();
    renderWindow->SetWindowName("ImageAccumulateExample2");
    
    vtkSmartPointer<vtkRenderWindowInteractor> interactor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow( renderWindow );
    interactor->Initialize();
    interactor->Start();
    return EXIT_SUCCESS;
}

图像重采样

图像重釆样是指对数字图像按所需的像素位置或像素间距重新采样,以构成几何变换后 的新图像。重采样过程本质上是图像恢复过程,它用输入的离散数字图像重建代表原始图像二维连续函数,再按新的像素间距和像素位置进行采样。其数学过程是根据重建的连续函数(曲面),用周围若干像素点的值估计或内插出新采样点的值。图像重采样在图像处理中应用非常广泛,如SIFT特征提取。
图像重采样后图像的维数会发生改变。当重采样图像小于原图像维数时,称为降采样当重采样图像维数大于原图像时,称为升采样。VTK中可以方便的对图像进行重采样。vtkImageShrink3D类实现图像降采样。降采样需要设置每个方向的采样率,降采样率越大,图像越模糊。升采样的原理与降采样原理一致,只是增加采样点数来增加图像的维数。VTK中vtkImageMagnify来实现图像的升采样。
在这里插入图片描述

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkBMPReader.h>
#include <vtkImageShrink3D.h>
#include <vtkImageMagnify.h>

//测试图像:../data/lena.bmp
int main(int argc, char* argv[])
{
    vtkSmartPointer<vtkBMPReader> reader =
        vtkSmartPointer<vtkBMPReader>::New();
    reader->SetFileName ("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap05/data/lena.bmp");
    reader->Update();
    //降采样
    vtkSmartPointer<vtkImageShrink3D> shrinkFilter =
        vtkSmartPointer<vtkImageShrink3D>::New();
    shrinkFilter->SetInputConnection(reader->GetOutputPort());
    shrinkFilter->SetShrinkFactors(16,16,1);          //像素间隔变大16倍 图像维数变小16倍
    shrinkFilter->Update();
    //升采样
    vtkSmartPointer<vtkImageMagnify> magnifyFilter =
        vtkSmartPointer<vtkImageMagnify>::New();
    magnifyFilter->SetInputConnection(reader->GetOutputPort());
    magnifyFilter->SetMagnificationFactors(10,10,1);  //像素间隔变16十倍 图像维数变大16倍
    magnifyFilter->Update();

    int originalDims[3];
    reader->GetOutput()->GetDimensions(originalDims);

    double originalSpace[3];
    reader->GetOutput()->GetSpacing(originalSpace);

    int shrinkDims[3];
    shrinkFilter->GetOutput()->GetDimensions(shrinkDims);

    double shrinkSpace[3];
    shrinkFilter->GetOutput()->GetSpacing(shrinkSpace);

    int magnifyDims[3];
    magnifyFilter->GetOutput()->GetDimensions(magnifyDims);

    double magnifySpace[3];
    magnifyFilter->GetOutput()->GetSpacing(magnifySpace);

    std::cout<<"原图图像维数      :"<<originalDims[0] << " "<<originalDims[1]<<" "<<originalDims[2]<<std::endl;
    std::cout<<"原图图像像素间隔  :"<<originalSpace[0] << " "<<originalSpace[1]<<" "<<originalSpace[2]<<std::endl;
    std::cout<<"降采样图像维数    :"<<shrinkDims[0] << " "<<shrinkDims[1]<<" "<<shrinkDims[2]<<std::endl;
    std::cout<<"降采样图像像素间隔:"<<shrinkSpace[0] << " "<<shrinkSpace[1]<<" "<<shrinkSpace[2]<<std::endl;
    std::cout<<"升采样图像维数    :"<<magnifyDims[0] << " "<<magnifyDims[1]<<" "<<magnifyDims[2]<<std::endl;
    std::cout<<"升采样图像像素间隔:"<<magnifySpace[0] << " "<<magnifySpace[1]<<" "<<magnifySpace[2]<<std::endl;

    vtkSmartPointer<vtkImageActor> originalActor =
        vtkSmartPointer<vtkImageActor>::New();
    originalActor->SetInputData(reader->GetOutput());

    vtkSmartPointer<vtkImageActor> shrinkActor =
        vtkSmartPointer<vtkImageActor>::New();
    shrinkActor->SetInputData(shrinkFilter->GetOutput());

    vtkSmartPointer<vtkImageActor> magnifyActor =
        vtkSmartPointer<vtkImageActor>::New();
    magnifyActor->SetInputData(magnifyFilter->GetOutput());

    double originalViewport[4] = {0.0, 0.0, 0.33, 1.0};
    double shrinkViewport[4] = {0.33, 0.0, 0.66, 1.0};
    double magnifyViewport[4] = {0.66, 0.0, 1.0, 1.0};

    vtkSmartPointer<vtkRenderer> originalRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    originalRenderer->SetViewport(originalViewport);
    originalRenderer->AddActor(originalActor);
    originalRenderer->ResetCamera();
    originalRenderer->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkRenderer> shrinkRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    shrinkRenderer->SetViewport(shrinkViewport);
    shrinkRenderer->AddActor(shrinkActor);
    shrinkRenderer->ResetCamera();
    shrinkRenderer->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkRenderer> magnifyRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    magnifyRenderer->SetViewport(magnifyViewport);
    magnifyRenderer->AddActor(magnifyActor);
    magnifyRenderer->ResetCamera();
    magnifyRenderer->SetBackground(1.0, 1.0, 1.0);

    vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(originalRenderer);
    renderWindow->AddRenderer(shrinkRenderer);
    renderWindow->AddRenderer(magnifyRenderer);
    renderWindow->SetSize(640, 320);
    renderWindow->Render();
    renderWindow->SetWindowName("ImageShrinkMagnifyExample");

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    vtkSmartPointer<vtkInteractorStyleImage> style =
        vtkSmartPointer<vtkInteractorStyleImage>::New();

    renderWindowInteractor->SetInteractorStyle(style);
    renderWindowInteractor->SetRenderWindow(renderWindow);
    renderWindowInteractor->Initialize();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐