使用itk将3D二进制图像转换为3D网格

时间:2018-07-05 12:35:32

标签: itk

我正在尝试使用3d RLE二进制蒙版生成3d网格。 在itk中,我找到了一个名为itkBinaryMask3DMeshSource的类。 它基于MarchingCubes算法 例如,使用此类ExtractIsoSurface和ExtractIsoSurface

在我的情况下,我有一个3D二进制掩码,但以1D矢量格式表示。 我正在为此任务编写函数。

我的函数采用以下参数:

  1. 输入:crle 1d向量(计算的rle),尺寸Int3
  2. 输出:coord + coord索引(或生成包含这两个数组的单个文件;接下来我可以使用它们来可视化网格)

第一步,我解码了这个计算出的规则。 接下来,我使用imageIterator创建与BinaryMask3DMeshSource兼容的图像。

在最后一步,我被阻止了。

这是我的代码:

void GenerateMeshFromCrle(const std::vector<int>& crle, const Int3 & dim,
        std::vector<float>* coords, std::vector<int>*coord_indices, int* nodes,
        int* cells, const char* outputmeshfile) {

    std::vector<int> mask(crle.back());
    CrleDecode(crle, mask.data());

    //  here we define our itk Image type with a 3 dimension
    using ImageType = itk::Image< unsigned char, 3 >;
    ImageType::Pointer image = ImageType::New();

    // an Image is defined by start index and size for each axes
    // By default, we set the first start index from x=0,y=0,z=0
    ImageType::IndexType start;
    start[0] = 0;  // first index on X
    start[1] = 0;  // first index on Y
    start[2] = 0;  // first index on Z

    // until here, no problem

    // We set the image size on x,y,z from the dim input parameters
    // itk takes Z Y X
    ImageType::SizeType size;
    size[0] = dim.z;  // size along X
    size[1] = dim.y;  // size along Y
    size[2] = dim.x;  // size along Z

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

    image->SetRegions(region);
    image->Allocate();

    // Set the pixels to value from rle
    // This is a fast way
    itk::ImageRegionIterator<ImageType> imageIterator(image, region);

    int n = 0;
    while (!imageIterator.IsAtEnd() && n < mask.size()) {
        // Set the current pixel to the value from rle
        imageIterator.Set(mask[n]);
        ++imageIterator;
        ++n;
    }

    // In this step, we launch itkBinaryMask3DMeshSource

    using BinaryThresholdFilterType = itk::BinaryThresholdImageFilter< ImageType, ImageType >;
    BinaryThresholdFilterType::Pointer threshold =
            BinaryThresholdFilterType::New();
    threshold->SetInput(image->GetOutput()); // here it's an error, since no GetOutput member for image
    threshold->SetLowerThreshold(0);
    threshold->SetUpperThreshold(1);
    threshold->SetOutsideValue(0);

    using MeshType = itk::Mesh< double, 3 >;

    using FilterType = itk::BinaryMask3DMeshSource< ImageType, MeshType >;
    FilterType::Pointer filter = FilterType::New();
    filter->SetInput(threshold->GetOutput());
    filter->SetObjectValue(1);

    using WriterType = itk::MeshFileWriter< MeshType >;
    WriterType::Pointer writer = WriterType::New();
    writer->SetFileName(outputmeshfile);
    writer->SetInput(filter->GetOutput());
}

任何想法

感谢您的宝贵时间。

1 个答案:

答案 0 :(得分:0)

由于image不是过滤器,因此可以直接将其插入:threshold->SetInput(image);。在此功能结束时,您还需要writer->Update();。其余的看起来不错。

旁注:看来您可能会受益于import filter的使用,而不是手动迭代缓冲区并一次复制一个值。