基于ITK和VTK实现三维体数据的区域生长分割和可视化

该文由Markdown语法编译器编辑完成。

1. 前言:

在医学影像的开源库中,ITK主要擅长图像分割和图像配准算法的 研究,VTK则擅长三维可视化的实现。通过结合二者,可以实现基本的图像分割或配准算法的执行和结果显示。

本文主要介绍ITK中的基于itkConnectedThresholdFilter的区域生长分割算法,并且利用 VTK将区域生长分割后的体数据进行显示。

2. 基本步骤:

本文所采用的基本开发环境为:

序号 软件 版本号
1 ITK 4.10.0
2 VTK 6.0.0
3 QT 5.1.0
4 Visual Studio 2012
5 OS Windows 7

这篇文章是基于当前我正在公司开发的一个项目中抽取的部分需求来撰写的。其中的需求是输入患者的一组CT数据,首先基于阈值进行分割,然后在阈值分割的基础上,再进行区域生长分割,这样可以快速地获取用户需要后处理的感兴趣区域。

由于要处理的是医学体数据,而且是已经进行完阈值分割后的数据,因此它的数据类型设为vtkImageData。

由于VTK和ITK的数据类型不能直接使用,因此首先需要将VTK类型的体数据vtkImageData转化成itkImage,然后再调用ITK中的区域生长的算法,最后再将分割后的数据再转换回vtkImageData,进行后续的三维后处理等。

好在,ITK中已经提供了转化数据类型的filter,只需根据需要选择使用即可。

以下是主要的实现代码:


//.h文件:
static const int kDimension=3;
typedef itk::Image< int, kDimension > ImageType;
typedef ImageType::IndexType PixelIndexType;
ImageType::Pointer m_itkImage;
ImageType::IndexType m_pixelIndex;

//.cpp文件:
void ConstructITKImage(const vtkImageData* originalImageData) 
{
    double imageSpacing[3] = {0.0};
    double imageOrigin[3] = {0.0};
    int imageDimension[3] = {0};
    originalImageData->GetSpacing(imageSpacing);
    originalImageData->GetOrigin(imageOrigin);
    originalImageData->GetDimensions(imageDimension);

    const ImageType::SizeType  size  = {{imageDimension[0], imageDimension[1], imageDimension[2]}}; //Size along {X,Y,Z}
    const ImageType::IndexType start = {{0,0,0}}; // First index on {X,Y,Z}

    ImageType::RegionType region;
    region.SetSize( size );
    region.SetIndex( start );

    //Types for converting between ITK and VTK
    typedef itk::VTKImageToImageFilter VTKImageToImageType;

    //Converting to ITK Image Format
    VTKImageToImageType::Pointer vtkImageToImageFilter = VTKImageToImageType::New();
    vtkImageToImageFilter->SetInput(originalImageData);
    vtkImageToImageFilter->UpdateLargestPossibleRegion();

    //将vtk的图像转化为itk的图像,以便利用itk的分割算法进行分割.
    m_itkImage->SetRegions( region );
    m_itkImage->Allocate();
    m_itkImage = const_castint, kDimension>*>(vtkImageToImageFilter->GetImporter()->GetOutput());

    ImageType::SpacingType spacing;
    spacing[0] = imageSpacing[0]; // spacing along X
    spacing[1] = imageSpacing[1]; // spacing along Y
    spacing[2] = imageSpacing[2]; // spacing along Z
    m_itkImage->SetSpacing( spacing );

    ImageType::PointType newOrigin;
    newOrigin[0] = imageOrigin[0];
    newOrigin[1] = imageOrigin[1];
    newOrigin[2] = imageOrigin[2];
    m_itkImage->SetOrigin( newOrigin );

    ImageType::DirectionType direction;
    direction.SetIdentity();
    m_itkImage->SetDirection( direction );
    m_itkImage->UpdateOutputInformation();
};

bool CheckSeedPointInsideImage( double worldSeedPoint[3] )
{
    typedef itk::Point< double, ImageType::ImageDimension > PointType;
    PointType point;
    point[0] = worldSeedPoint[0];    // x coordinate
    point[1] = worldSeedPoint[1];    // y coordinate
    point[2] = worldSeedPoint[2];    // z coordinate

    //根据选取的种子点的世界坐标,获取这个种子点在itk图像中的像素索引值.
    bool isInside = m_itkImage->TransformPhysicalPointToIndex(point, m_pixelIndex);
    return isInside;
}

int RegionGrowingByConnectedThredholdFilter(const vtkImageData* pImage, double worldSeedPoint[3])
{
    ConstructITKImage(originalImageData);

    bool isSeedPointInsideImage = CheckSeedPointInsideImage(worldSeedPoint);
    if (!isSeedPointInsideImage)
    {
        return;
    }

    typedef itk::Image< int, kDimension > InternalImageType;
    typedef itk::ConnectedThresholdImageFilter< InternalImageType, InternalImageType > ConnectedFilterType;
    ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New( );

    connectedThreshold->SetInput(m_itkImage);

    //由于区域生长是在阈值分割后进行的,此时的vtkImageData是二值的,灰度只有0和1。因此基于阈值的区域生长的灰度上下限都是1.
    //区域生长分割后的图像,要经过vtkLookupTable进行颜色映射.vtkLookupTable也只有0和1两个预设值.
    connectedThreshold->SetLower(1);
    connectedThreshold->SetUpper(1);
    connectedThreshold->SetReplaceValue(1);
    connectedThreshold->SetSeed(m_pixelIndex);

    typedef itk::ImageToVTKImageFilter ConnectorType;

    //Converting Back from ITK to VTK Image for Visualization.
    ConnectorType::Pointer connector = ConnectorType::New();
    connector->SetInput(connectedThreshold->GetOutput());
    connector->Update();
}
;

3. 区域生长分割结果及显示:

基于ITK和VTK实现三维体数据的区域生长分割和可视化_第1张图片

基于ITK和VTK实现三维体数据的区域生长分割和可视化_第2张图片

基于ITK和VTK实现三维体数据的区域生长分割和可视化_第3张图片

完。

你可能感兴趣的:(VTK,ITK,医学影像处理,ITK,VTK,区域生长,图像分割)