VTK学习笔记(一)------序列图像的读取及误区

        下面简单地介绍三种读取序列图像的方法,后续在窗口中的显示使用vtkImageActor、vtkImageviewer2或vtkActor都可以 。

方法一

   使用一个数组先读入文件名,然后再将数组名作为reader->SetFileNames的参数传入

void MainWindow::ReadSeriesImages1(){
        //生成图像序列的文件名数组
        vtkSmartPointer< vtkStringArray > fileArray = 
            vtkSmartPointer< vtkStringArray >::New();
        char fileName[128];
        for(int i = 1; i < 100; i++)
        {
            sprintf(fileName, "VTK_test/Head/head%03d.jpg", i);
            std::string fileStr(fileName);
            fileArray->InsertNextValue(fileStr);
        }

        //读取JPG序列图像
        vtkSmartPointer reader = 
                    vtkSmartPointer::New();
        reader->SetFileNames(fileArray);

        vtkSmartPointer style =                         
                  vtkSmartPointer::New();

        //显示读取的JPG图像
        vtkSmartPointer imageViewer = 
                    vtkSmartPointer::New();
        imageViewer->SetInputConnection(reader->GetOutputPort());

        vtkSmartPointer renderWindowInteractor =
                  vtkSmartPointer::New();
        renderWindowInteractor->SetInteractorStyle(style);

        imageViewer->SetSlice(50); //默认显示第50个切片(即第50层)
        imageViewer->SetSliceOrientationToXY();
        //imageViewer->SetSliceOrientationToYZ();
        //imageViewer->SetSliceOrientationToXZ();
        imageViewer->SetupInteractor(renderWindowInteractor);
        imageViewer->Render();

        imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
        imageViewer->SetSize(640, 480);
        imageViewer->GetRenderWindow()->SetWindowName("ReadSeriesImages1");

        renderWindowInteractor->Start();
}

方法二

参数SetFilePrefix()表示文件名中相同的部分,SetFilePattern()表示文件名中不同的部分,Reader->SetDataExtent(0, 2047, 0, 2047, 1, 30)表示图像为2048x2048,序号为1-30

    //创建reader对象
    vtkSmartPointerReader = 
                    vtkSmartPointer::New();
    Reader->SetDataScalarTypeToUnsignedChar();
    Reader->SetFileDimensionality(3);
    //设置图像的文件名前缀
    Reader->SetFilePrefix("/home/yanghantao/Documents/ruxian/");
    Reader->SetFileNameSliceSpacing(1);
    //设置图像文件名后缀
    Reader->SetFilePattern("%s%03d_R.bmp");
    //图像大小为2048*2048,序号为1-30
    Reader->SetDataExtent(0, 2047, 0, 2047, 1, 30);
    Reader->SetDataSpacing(1, 1, 10);
    //数据流更新
    Reader->Update();
// 显示读取的BMP图像
    vtkSmartPointer imageViewer = 
            vtkSmartPointer::New();
    imageViewer->SetInputConnection(Reader->GetOutputPort());

    vtkSmartPointer renderWindowInteractor =
            vtkSmartPointer::New();

    imageViewer->SetupInteractor(renderWindowInteractor);
    imageViewer->SetColorLevel(128);
    imageViewer->SetColorWindow(256);
    imageViewer->SetSlice(2);
    imageViewer->SetSliceOrientationToXY();
    //imageViewer->SetSize(512,512);
    imageViewer->Render();

    renderWindowInteractor->Start();

方法三

vtkSmartPointer append =
          vtkSmartPointer::New();
/*
This axis is expanded to hold the multiple images.
The default AppendAxis is the X axis. 
If you want to create a volue from a series of XY images, 
then you should set the AppendAxis to 2 (Z axis).
*/
append->SetAppendAxis(2);//设置图片叠加方式为沿Z轴叠加

for(int i = 1; i < 31; i++)
 {
    //reader一定要在循环体里面新建
     vtkSmartPointerreader =
                   vtkSmartPointer::New();

     char fileName[128];
     sprintf(fileName,"/home/yanghantao/Documents/ruxian/%03d_R.bmp", i);
     reader->SetFileName(fileName);
     append->AddInputConnection(reader->GetOutputPort());
  }
append->Update();       

关于方法三的一些问题:

网传的大部分代码是这样写的:

vtkSmartPointer append =
          vtkSmartPointer::New();
/*
This axis is expanded to hold the multiple images.
The default AppendAxis is the X axis. 
If you want to create a volue from a series of XY images, 
then you should set the AppendAxis to 2 (Z axis).
*/
append->SetAppendAxis(2);//设置图片叠加方式为沿Z轴叠加

vtkSmartPointerreader =
                   vtkSmartPointer::New();

for(int i = 1; i < 31; i++)
 {
     char fileName[128];
     sprintf(fileName,"/home/yanghantao/Documents/ruxian/%03d_R.bmp", i);
     reader->SetFileName(fileName);
     append->AddInputConnection(reader->GetOutputPort());
  }
     append->Update();       

这个在教程及网页上广为流传的代码有问题,也就是AddInputConnection,是一个建立数据流的指针,他指向的reader的输出,但这里reader是一个唯一地址,每次读取,其地址不变,但内容变了,append因此add了30个同一个地址指向,而reader内容会随着每个循环动态更新,最后,所有的append的指向指针都是同一图,然后怎样更新,都不变。所以我们需要在循环里面每次新建一个reader。

详细请看:Wrong behaviour stacking different images with vtkImageAppend - Support - VTK

你可能感兴趣的:(VTK,c++)