# GenerateModelsFromLabels

VTKExamples/Cxx/Medical/GenerateModelsFromLabels

### Description

This example creates polydata models from a 3D volume that contains discrete labels. These volume are normally the output of a segmentation algorithm. The polydata for each label will be output into a separate file. If you want to see the segmentation results as cube models, see the example [cubes from labeled volume data]]. The input volume must be in [ MetaIO/Documentation| META format].

Once you generate the models, you can view them with Paraview

### Code

GenerateModelsFromLabels.cxx

    //
    // GenerateModelsFromLabels
    //   Usage: GenerateModelsFromLabels InputVolume Startlabel Endlabel
    //          where
    //          InputVolume is a meta file containing a 3 volume of
    //            discrete labels.
    //          StartLabel is the first label to be processed
    //          EndLabel is the last label to be processed
    //          NOTE: There can be gaps in the labeling. If a label does
    //          not exist in the volume, it will be skipped.
    //
    //
    #include <vtkMetaImageReader.h>
    #include <vtkImageAccumulate.h>
    #include <vtkDiscreteMarchingCubes.h>
    #include <vtkWindowedSincPolyDataFilter.h>
    #include <vtkMaskFields.h>
    #include <vtkThreshold.h>
    #include <vtkGeometryFilter.h>
    #include <vtkXMLPolyDataWriter.h>
    #include <vtkSmartPointer.h>

    #include <vtkImageData.h>
    #include <vtkPointData.h>
    #include <vtkUnstructuredGrid.h>
    #include <sstream>

    int main (int argc, char *argv[])
    {
      if (argc < 4)
      {
        std::cout << "Usage: " << argv[0] << " InputVolume StartLabel EndLabel" << std::endl;
        return EXIT_FAILURE;
      }

      // Create all of the classes we will need
      vtkSmartPointer<vtkMetaImageReader> reader =
        vtkSmartPointer<vtkMetaImageReader>::New();
      vtkSmartPointer<vtkImageAccumulate> histogram =
        vtkSmartPointer<vtkImageAccumulate>::New();
      vtkSmartPointer<vtkDiscreteMarchingCubes> discreteCubes =
        vtkSmartPointer<vtkDiscreteMarchingCubes>::New();
      vtkSmartPointer<vtkWindowedSincPolyDataFilter> smoother =
        vtkSmartPointer<vtkWindowedSincPolyDataFilter>::New();
      vtkSmartPointer<vtkThreshold> selector =
        vtkSmartPointer<vtkThreshold>::New();
      vtkSmartPointer<vtkMaskFields> scalarsOff =
        vtkSmartPointer<vtkMaskFields>::New();
      vtkSmartPointer<vtkGeometryFilter> geometry =
        vtkSmartPointer<vtkGeometryFilter>::New();
      vtkSmartPointer<vtkXMLPolyDataWriter> writer =
        vtkSmartPointer<vtkXMLPolyDataWriter>::New();

      // Define all of the variables
      unsigned int startLabel = atoi(argv[2]);
      unsigned int endLabel = atoi(argv[3]);
      std::string filePrefix = "Label";
      unsigned int smoothingIterations = 15;
      double passBand = 0.001;
      double featureAngle = 120.0;

      // Generate models from labels
      // 1) Read the meta file
      // 2) Generate a histogram of the labels
      // 3) Generate models from the labeled volume
      // 4) Smooth the models
      // 5) Output each model into a separate file

      reader->SetFileName(argv[1]);

      histogram->SetInputConnection(reader->GetOutputPort());
      histogram->SetComponentExtent(0, endLabel, 0, 0, 0, 0);
      histogram->SetComponentOrigin(0, 0, 0);
      histogram->SetComponentSpacing(1, 1, 1);
      histogram->Update();

      discreteCubes->SetInputConnection(reader->GetOutputPort());
      discreteCubes->GenerateValues(
        endLabel - startLabel + 1, startLabel, endLabel);

      smoother->SetInputConnection(discreteCubes->GetOutputPort());
      smoother->SetNumberOfIterations(smoothingIterations);
      smoother->BoundarySmoothingOff();
      smoother->FeatureEdgeSmoothingOff();
      smoother->SetFeatureAngle(featureAngle);
      smoother->SetPassBand(passBand);
      smoother->NonManifoldSmoothingOn();
      smoother->NormalizeCoordinatesOn();
      smoother->Update();

      selector->SetInputConnection(smoother->GetOutputPort());
      selector->SetInputArrayToProcess(0, 0, 0,
                                       vtkDataObject::FIELD_ASSOCIATION_CELLS,
                                       vtkDataSetAttributes::SCALARS);

      // Strip the scalars from the output
      scalarsOff->SetInputConnection(selector->GetOutputPort());
      scalarsOff->CopyAttributeOff(vtkMaskFields::POINT_DATA,
                                   vtkDataSetAttributes::SCALARS);
      scalarsOff->CopyAttributeOff(vtkMaskFields::CELL_DATA,
                                   vtkDataSetAttributes::SCALARS);

      geometry->SetInputConnection(scalarsOff->GetOutputPort());

      writer->SetInputConnection(geometry->GetOutputPort());

      for (unsigned int i = startLabel; i <= endLabel; i++)
      {
        // see if the label exists, if not skip it
        double frequency =
          histogram->GetOutput()->GetPointData()->GetScalars()->GetTuple1(i);
        if (frequency == 0.0)
        {
          continue;
        }

        // select the cells for a given label
        selector->ThresholdBetween(i, i);

        // output the polydata
        std::stringstream ss;
        ss << filePrefix << i << ".vtp";
        std::cout << argv[0] << " writing " << ss.str() << std::endl;

        writer->SetFileName(ss.str().c_str());
        writer->Write();

      }
      return EXIT_SUCCESS;
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)

    PROJECT(GenerateModelsFromLabels)

    find_package(VTK REQUIRED)
    include(${VTK_USE_FILE})

    add_executable(GenerateModelsFromLabels MACOSX_BUNDLE GenerateModelsFromLabels.cxx)

    target_link_libraries(GenerateModelsFromLabels ${VTK_LIBRARIES})

### Download and Build GenerateModelsFromLabels

Click here to download GenerateModelsFromLabels and its CMakeLists.txt file. Once the tarball GenerateModelsFromLabels.tar has been downloaded and extracted,

    cd GenerateModelsFromLabels/build

If VTK is installed:

    cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

    cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

    make

and run it:

    ./GenerateModelsFromLabels

WINDOWS USERS PLEASE NOTE: Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.