PolyDataContourToImageData
VTKExamples/Cxx/PolyData/PolyDataContourToImageData
Description¶
- Contributed by: Lars Friedrich
This example generates a sphere, cuts it with a plane and, therefore, generates a circlular contour (vtkPolyData). Subsequently a binary image representation (vtkImageData) is extracted from it. Internally vtkPolyDataToImageStencil and vtkLinearExtrusionFilter are utilized. Both the circular poly data (circle.vtp) and the resultant image (labelImage.mhd) are saved to disk.
NOTE: Similarily to example PolyDataToImageData, I am not really sure whether or not the image origin needs to be adjusted as the sphere-image-overlay shows some offset in paraview visualization (at least I think ...). Maybe someone could verify that. Thanks!
Code¶
PolyDataContourToImageData.cxx
#include <vtkVersion.h> #include <vtkSmartPointer.h> #include <vtkPolyData.h> #include <vtkImageData.h> #include <vtkSphereSource.h> #include <vtkMetaImageWriter.h> #include <vtkPolyDataToImageStencil.h> #include <vtkImageStencil.h> #include <vtkPointData.h> #include <vtkCutter.h> #include <vtkPlane.h> #include <vtkStripper.h> #include <vtkLinearExtrusionFilter.h> #include <vtkXMLPolyDataWriter.h> /** * This example generates a sphere, cuts it with a plane and, therefore, generates a circlular contour (vtkPolyData). * Subsequently a binary image representation (vtkImageData) is extracted from it. Internally vtkPolyDataToImageStencil and * vtkLinearExtrusionFilter are utilized. Both the circular poly data (circle.vtp) and the resultant image (labelImage.mhd) * are saved to disk. */ int main(int, char *[]) { // 3D source sphere vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New(); sphereSource->SetPhiResolution(30); sphereSource->SetThetaResolution(30); sphereSource->SetCenter(40, 40, 0); sphereSource->SetRadius(20); // generate circle by cutting the sphere with an implicit plane // (through its center, axis-aligned) vtkSmartPointer<vtkCutter> circleCutter = vtkSmartPointer<vtkCutter>::New(); circleCutter->SetInputConnection(sphereSource->GetOutputPort()); vtkSmartPointer<vtkPlane> cutPlane = vtkSmartPointer<vtkPlane>::New(); cutPlane->SetOrigin(sphereSource->GetCenter()); cutPlane->SetNormal(0, 0, 1); circleCutter->SetCutFunction(cutPlane); vtkSmartPointer<vtkStripper> stripper = vtkSmartPointer<vtkStripper>::New(); stripper->SetInputConnection(circleCutter->GetOutputPort()); // valid circle stripper->Update(); // that's our circle vtkSmartPointer<vtkPolyData> circle = stripper->GetOutput(); // write circle out vtkSmartPointer<vtkXMLPolyDataWriter> polyDataWriter = vtkSmartPointer<vtkXMLPolyDataWriter>::New(); #if VTK_MAJOR_VERSION <= 5 polyDataWriter->SetInput(circle); #else polyDataWriter->SetInputData(circle); #endif polyDataWriter->SetFileName("circle.vtp"); polyDataWriter->SetCompressorTypeToNone(); polyDataWriter->SetDataModeToAscii(); polyDataWriter->Write(); // prepare the binary image's voxel grid vtkSmartPointer<vtkImageData> whiteImage = vtkSmartPointer<vtkImageData>::New(); double bounds[6]; circle->GetBounds(bounds); double spacing[3]; // desired volume spacing spacing[0] = 0.5; spacing[1] = 0.5; spacing[2] = 0.5; whiteImage->SetSpacing(spacing); // compute dimensions int dim[3]; for (int i = 0; i < 3; i++) { dim[i] = static_cast<int>(ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i])) + 1; if (dim[i] < 1) dim[i] = 1; } whiteImage->SetDimensions(dim); whiteImage->SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1); double origin[3]; // NOTE: I am not sure whether or not we had to add some offset! origin[0] = bounds[0];// + spacing[0] / 2; origin[1] = bounds[2];// + spacing[1] / 2; origin[2] = bounds[4];// + spacing[2] / 2; whiteImage->SetOrigin(origin); #if VTK_MAJOR_VERSION <= 5 whiteImage->SetScalarTypeToUnsignedChar(); whiteImage->AllocateScalars(); #else whiteImage->AllocateScalars(VTK_UNSIGNED_CHAR,1); #endif // fill the image with foreground voxels: unsigned char inval = 255; unsigned char outval = 0; vtkIdType count = whiteImage->GetNumberOfPoints(); for (vtkIdType i = 0; i < count; ++i) { whiteImage->GetPointData()->GetScalars()->SetTuple1(i, inval); } // sweep polygonal data (this is the important thing with contours!) vtkSmartPointer<vtkLinearExtrusionFilter> extruder = vtkSmartPointer<vtkLinearExtrusionFilter>::New(); #if VTK_MAJOR_VERSION <= 5 extruder->SetInput(circle); #else extruder->SetInputData(circle); #endif extruder->SetScaleFactor(1.); extruder->SetExtrusionTypeToNormalExtrusion(); extruder->SetVector(0, 0, 1); extruder->Update(); // polygonal data --> image stencil: vtkSmartPointer<vtkPolyDataToImageStencil> pol2stenc = vtkSmartPointer<vtkPolyDataToImageStencil>::New(); pol2stenc->SetTolerance(0); // important if extruder->SetVector(0, 0, 1) !!! pol2stenc->SetInputConnection(extruder->GetOutputPort()); pol2stenc->SetOutputOrigin(origin); pol2stenc->SetOutputSpacing(spacing); pol2stenc->SetOutputWholeExtent(whiteImage->GetExtent()); pol2stenc->Update(); // cut the corresponding white image and set the background: vtkSmartPointer<vtkImageStencil> imgstenc = vtkSmartPointer<vtkImageStencil>::New(); #if VTK_MAJOR_VERSION <= 5 imgstenc->SetInput(whiteImage); imgstenc->SetStencil(pol2stenc->GetOutput()); #else imgstenc->SetInputData(whiteImage); imgstenc->SetStencilConnection(pol2stenc->GetOutputPort()); #endif imgstenc->ReverseStencilOff(); imgstenc->SetBackgroundValue(outval); imgstenc->Update(); vtkSmartPointer<vtkMetaImageWriter> imageWriter = vtkSmartPointer<vtkMetaImageWriter>::New(); imageWriter->SetFileName("labelImage.mhd"); imageWriter->SetInputConnection(imgstenc->GetOutputPort()); imageWriter->Write(); return EXIT_SUCCESS; }
CMakeLists.txt¶
cmake_minimum_required(VERSION 2.8) PROJECT(PolyDataContourToImageData) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) add_executable(PolyDataContourToImageData MACOSX_BUNDLE PolyDataContourToImageData.cxx) target_link_libraries(PolyDataContourToImageData ${VTK_LIBRARIES})
Download and Build PolyDataContourToImageData¶
Danger
The generation of tar files has not been ported to the new VTKExamples. Some tarballs may be missing or out-of-date.
Click here to download PolyDataContourToImageData and its CMakeLists.txt file. Once the tarball PolyDataContourToImageData.tar has been downloaded and extracted,
cd PolyDataContourToImageData/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:
./PolyDataContourToImageData
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.