一个读取CT图像序列,并进行表面重建的C++代码

        这篇文章中,介绍使用VTK进行读取CT图像(一个序列),然后进行表面重建。为什么不使用DCMTK呢?因为使用DCMTK需要一张一张读取,要自己写一个代码,还要创建一个容器来放读入的CT数据,比较复杂。在实际的工程中,我们需要寻找合适的工具来造出漂亮的项目。


        1 为什么使用VTK

VTK自己就带有DICOM文件读取类,同时VTK中的imagedata 类可以存储一个图像矩阵,是一个很受欢迎的容器。VTK中还有表面重建算法marchingcubes,也很好用的。

1.1 vtkImageData的特点
  1. 数据结构:vtkImageData是基于结构化网格的数据表示形式,数据点被组织成一个规则的二维或三维数组。这些数据点称为像素或格点,每个像素包含一个或多个数值表示的属性信息。vtkImageData使用这种结构方便地表示二维图像和三维体数据。
  2. 数据类型:vtkImageData支持多种数据类型,如VTK_FLOAT、VTK_INT、VTK_SHORT、VTK_UNSIGNED_CHAR等,可以满足不同图像数据的存储需求。
  3. 维度信息:vtkImageData对象的维度描述了其包含像素的行数、列数和深度(对于三维图像)。这些维度信息决定了数据在空间中的范围和形状。
  4. 原点与间距:vtkImageData具有原点和间距属性,它们定义了空间中像素的位置和大小。原点表示数据中第一个像素的位置坐标,间距定义了相邻像素在各个方向上的间隔距离。
  5. 灵活性:vtkImageData提供了丰富的方法和属性,用于访问和修改单个像素的数值,进行图像处理以及数据分析。同时,它还支持与其他VTK类进行集成,实现更复杂的可视化和分析任务。
1.2  vtkMarchingCubes类的特点
  1. 等值面提取
    vtkMarchingCubes类主要用于从三维规则体数据中提取等值面。它通过分析体数据中的每个体素(小立方体),并根据给定的等值面值,构造出逼近等值面的三角面片。

  2. 算法效率
    Marching Cubes算法实际上是一个分而治之的方法,它将等值面的抽取分布于每一个体素中进行。这种分布式处理使得算法在处理大规模数据时具有较高的效率。

  3. 适用性广泛
    vtkMarchingCubes类不仅适用于医学图像重建,如CT和MRI数据,还广泛应用于地质勘探、气象预报、流体力学等领域中的三维数据可视化。

  4. 法向量计算
    vtkMarchingCubes类在提取等值面的同时,还可以计算每个三角面片的法向量。法向量的计算对于提高渲染质量和实现光照效果至关重要。

  5. 集成性强
    vtkMarchingCubes类与VTK库中的其他类具有良好的集成性,可以方便地与其他可视化工具结合使用,实现更复杂的可视化任务。

2 CPP代码实践

    string filePath="../data";  //定义文件路径(CT序列存放的位置)
    // 定义一个reader指针,指向vtkDICOMIMageReader类
    vtkSmartPointer<vtkDICOMImageReader> reader=vtkSmartPointer<vtkDICOMImageReader>::New();
    reader->SetDirectoryName(filePath.c_str());  //设置路径
    reader->Update();                            //读取
    float* ipp;                                  //定义一个指向ImagePositionPatient类的指针,该方法不安全
    ipp=reader->GetImagePositionPatient();
    // 定义一个指向ImageData容器类的指针,用来存储读入的CT图像。
    vtkSmartPointer<vtkImageData> originalData = reader->GetOutput();
    int dim[3];    // 维度
    double spa[3], ori[3];   //空间分辨率,原点
    originalData->GetDimensions(dim);
    originalData->GetSpacing(spa);
    originalData->GetOrigin(ori);
    //输出
    cout<<"Origin: "<<ori[0]<<","<<ori[1]<<","<<ori[2]<<endl;
    cout<<"ImagePositionPatient: "<<ipp[0]<<","<<ipp[1]<<","<<ipp[2]<<endl;
    cout<<"Dimension: "<<dim[0]<<","<<dim[1]<<","<<dim[2]<<endl;
    cout<<"Spacing: "<<spa[0]<<","<<spa[1]<<","<<spa[2]<<endl;

输出结果为:

Origin: 0,0,0
ImagePositionPatient: -449.414,-449.414,-80
Dimension: 384,384,64
Spacing: 1.17188,1.17188,2.5

我们可以看到原点在0,0,0,这个是VTK图像自定义的原点,在图像体积的左下角,如下图所示:

        图1 VTK中默认的坐标系位置(红色到绿色到蓝色坐标系分别为X,Y,Z,右手系)

在实际的应用中,我们知道CT扫描的时候是有一个物理坐标系的。它的中心点(0,0,0)大致在CT孔颈的中心处,同时处在那一层的CT图像就是0层面。因为在实际的临床运用中,是需要坐标系的,比如远距离放射治疗,立体定向手术等。

使用vtkMarchingCubes类来获取表面重建

// 定义MarchingCubes指针
 vtkSmartPointer<vtkMarchingCubes> mc=vtkSmartPointer<vtkMarchingCubes>::New();
    mc->SetInputData(originalData);   //输入
    mc->SetValue(0,-100);             //阈值
    mc->Update();                     //数据更新

vtkSmartPointer<vtkPolyDataMapper> mapper=vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(mc->GetOutputPort());   //相当于演员的衣服

    vtkSmartPointer<vtkActor> actor=vtkSmartPointer<vtkActor>::New();  //演员
    actor->SetMapper(mapper);    //演员穿衣服
vtkSmartPointer<vtkAxesActor> axes=vtkSmartPointer<vtkAxesActor>::New();  //坐标轴
    axes->SetPosition(0,0,0);      //位置
    axes->AxisLabelsOff();         // 不显示X,Y,Z(很丑)
    axes->SetTotalLength(150,150,150);   // 坐标轴长度
    // 舞台
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();

    renderer->AddActor(axes);  //加入坐标轴
    renderer->AddActor(actor);  //加入演员

    vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();   //渲染窗口(可以调整大小)
    vtkSmartPointer<vtkRenderWindowInteractor> iren=vtkSmartPointer<vtkRenderWindowInteractor>::New();   //与窗口内容交互
    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style=vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();  //交互模式(我比较喜欢)
    renWin->AddRenderer(renderer);
    renWin->SetSize(600,600);
    //renWin->Render();
    iren->SetInteractorStyle(style);
    iren->SetRenderWindow(renWin);
    iren->Initialize();
    iren->Start();

输出的结果如下:

图2 CT图像表面重建结果(CatPhantom 503 模体)

本片文章的全部代码和CT数据在这里:https://download.csdn.net/download/kangdehua/89860561

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值