Extract surface mesh from 3D binary mask images

I have generated a segmentation mask for a CT volume and and saved it as a nifti format. This image volume consists of below set of categories.

0: Background (None of the following organs)
1: Liver
2: Bladder
3: Lungs
4: Kidneys
5: Bone
6: Brain

In order to extract the surface mesh which belongs to the liver (i.e. 1) from this label mask, first I converted this nifti image to a binary mask image where liver indicates with value 1 and otherwise zero. After that, I have applied BinaryMask3DMeshSource filter to extract the surface from this 3D binary mask image (see my code below).

But I’m not able to extract the liver surface mesh correctly and the generated file is empty (i.e. only contains the headers).

I have herewith attached the binary mask image for your further reference.

Please refer my code below. Any help will be appreciated.
labels-0.nii.gz (98.7 KB)

int isoSurfaceMeshWriter(string inputFileName, string outFileName)
{
    using PixelType = unsigned char;
    constexpr unsigned int Dimension = 3;
    using ImageType = itk::Image<PixelType, Dimension>;

    using ReaderType = itk::ImageFileReader<ImageType>;
    ReaderType::Pointer reader = ReaderType::New();
    reader->SetFileName(inputFileName);

    try
    {
        reader->Update();
    }
    catch (itk::ExceptionObject& ex)
    {
        std::cout << ex << std::endl;
    }

    using BinaryThresholdFilterType = itk::BinaryThresholdImageFilter<ImageType, ImageType>;
    BinaryThresholdFilterType::Pointer threshold = BinaryThresholdFilterType::New();
    threshold->SetInput(reader->GetOutput());
    threshold->SetLowerThreshold(1);
    threshold->SetUpperThreshold(1);
    threshold->SetOutsideValue(0);

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

    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(outFileName);
    writer->SetInput(filter->GetOutput());
    try
    {
        writer->Update();
    }
    catch (itk::ExceptionObject& error)
    {
        std::cerr << "Error: " << error << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Either set filter->SetObjectValue(255); or threshold->SetInsideValue(1);. This works for me:

#include "itkBinaryMask3DMeshSource.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkMeshFileWriter.h"

template <typename TImage>
void
WriteImage(TImage * out, std::string filename, bool compress)
{
  using WriterType = itk::ImageFileWriter<TImage>;
  typename WriterType::Pointer w = WriterType::New();
  w->SetInput(out);
  w->SetFileName(filename);
  w->SetUseCompression(compress);
  w->Update();
}

int
isoSurfaceMeshWriter(std::string inputFileName, std::string outFileName)
{
  using PixelType = unsigned char;
  constexpr unsigned int Dimension = 3;
  using ImageType = itk::Image<PixelType, Dimension>;

  using ReaderType = itk::ImageFileReader<ImageType>;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputFileName);

  try
  {
    reader->Update();
  }
  catch (itk::ExceptionObject & ex)
  {
    std::cout << ex << std::endl;
  }

  using BinaryThresholdFilterType = itk::BinaryThresholdImageFilter<ImageType, ImageType>;
  BinaryThresholdFilterType::Pointer threshold = BinaryThresholdFilterType::New();
  threshold->SetInput(reader->GetOutput());
  threshold->SetLowerThreshold(1);
  threshold->SetUpperThreshold(1);
  threshold->SetOutsideValue(0);

  WriteImage(threshold->GetOutput(), "M:/Dropbox/Docs/Desktop/labels-0.nrrd", true);

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

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

  using WriterType = itk::MeshFileWriter<MeshType>;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outFileName);
  writer->SetInput(filter->GetOutput());
  try
  {
    writer->Update();
  }
  catch (itk::ExceptionObject & error)
  {
    std::cerr << "Error: " << error << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

int
main(int, char *argv[])
{
  return isoSurfaceMeshWriter("M:/Dropbox/Docs/Desktop/labels-0.nii.gz", "M:/Dropbox/Docs/Desktop/labels-0.obj");
}
1 Like