Extract Iso Surface


Extract the iso surface as one itk::Mesh from a 3D itk::Image


Input image and resulting mesh

Input 3D image with iso-surface mesh



#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

#include "itkMesh.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkBinaryMask3DMeshSource.h"
#include "itkMeshFileWriter.h"

main(int argc, char * argv[])
  if (argc != 5)
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0];
    std::cerr << " <InputFileName> <OutputFileName> <Lower Threshold> <Upper Threshold>";
    std::cerr << std::endl;
    return EXIT_FAILURE;

  const char * inputFileName = argv[1];
  const char * outputFileName = argv[2];

  constexpr unsigned int Dimension = 3;

  using PixelType = unsigned char;
  using ImageType = itk::Image<PixelType, Dimension>;

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

  auto lowerThreshold = static_cast<PixelType>(std::stoi(argv[3]));
  auto upperThreshold = static_cast<PixelType>(std::stoi(argv[4]));

  using BinaryThresholdFilterType = itk::BinaryThresholdImageFilter<ImageType, ImageType>;
  BinaryThresholdFilterType::Pointer threshold = BinaryThresholdFilterType::New();

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

  using FilterType = itk::BinaryMask3DMeshSource<ImageType, MeshType>;
  FilterType::Pointer filter = FilterType::New();

  using WriterType = itk::MeshFileWriter<MeshType>;
  WriterType::Pointer writer = WriterType::New();
  catch (itk::ExceptionObject & error)
    std::cerr << "Error: " << error << std::endl;
    return EXIT_FAILURE;

  return EXIT_SUCCESS;

Classes demonstrated

template<typename TInputImage, typename TOutputMesh>
class BinaryMask3DMeshSource : public itk::ImageToMeshFilter<TInputImage, TOutputMesh>

This class tries to construct a 3D mesh surface based on a binary mask. It can be used to integrate a region-based segmentation method and a deformable model into one hybrid framework.

To construct a mesh, we need to construct elements in a voxel and combine those elements later to form the final mesh. Before go through every voxel in the 3D volume, we first construct 2 look up tables. The index of these 2 tables are the on-off combination of the 8 nodes that form the voxel. So both of these tables has the size of $2^8$ bytes. According to previous work, all those $2^8$ combination of the nodes can be grouped into 16 final combinations. In the first table, we record the final combination that can be transformed from the current combination. The entries of the second table are made up of the transforming sequence that is necessary for the current combination transform to one of the final combinations.

We then go through the 3D volume voxel by voxel, using those two tables we have defined to construct elements within each voxel. We then merge all these mesh elements into one 3D mesh.


The ObjectValue parameter is used to identify the object. In most applications, pixels in the object region are assigned to “1”, so the default value of ObjectValue is set to “1”


W. Lorensen and H. Cline, “Marching Cubes: A High Resolution 3D Surface Construction Algorithm”, Computer Graphics 21, pp. 163-169, 1987.


The input should be a 3D binary image.

See itk::BinaryMask3DMeshSource for additional documentation.