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<vtkJPEGReader> reader = 
                    vtkSmartPointer<vtkJPEGReader>::New();
        reader->SetFileNames(fileArray);

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

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

        vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
                  vtkSmartPointer<vtkRenderWindowInteractor>::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对象
    vtkSmartPointer<vtkBMPReader>Reader = 
                    vtkSmartPointer<vtkBMPReader>::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<vtkImageViewer2> imageViewer = 
            vtkSmartPointer<vtkImageViewer2>::New();
    imageViewer->SetInputConnection(Reader->GetOutputPort());

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

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

    renderWindowInteractor->Start();

方法三

vtkSmartPointer<vtkImageAppend > append =
          vtkSmartPointer<vtkImageAppend >::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一定要在循环体里面新建
     vtkSmartPointer<vtkBMPReader>reader =
                   vtkSmartPointer<vtkBMPReader>::New();

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

关于方法三的一些问题:

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

vtkSmartPointer<vtkImageAppend > append =
          vtkSmartPointer<vtkImageAppend >::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轴叠加

vtkSmartPointer<vtkBMPReader>reader =
                   vtkSmartPointer<vtkBMPReader>::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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值