0
votes

I'm trying to generate a 3d mesh using 3d RLE binary mask. In itk, I find a class named itkBinaryMask3DMeshSource it's based on MarchingCubes algorithm some example, use this class, ExtractIsoSurface et ExtractIsoSurface

in my case, I have a rle 3D binary mask but represented in 1d vector format. I'm writing a function for this task.

My function takes as parameters :

  1. Inputs : crle 1d vector ( computed rle), dimension Int3
  2. Output : coord + coord indices ( or generate a single file contain both of those array; and next I can use them to visualize the mesh )

as a first step, I decoded this computed rle. next, I use imageIterator to create an image compatible to BinaryMask3DMeshSource.

I'm blocked, in the last step.

This is my code :

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());
}

any idea

I appreciate your time.

1

1 Answers

0
votes

Since image is not a filter you can plug it in directly: threshold->SetInput(image);. At the end of this function, you also need writer->Update();. The rest looks good.

Side-note: it looks like you might benefit from usage of import filter instead of manually iterating the buffer and copying values one at a time.