[vtkusers] VTKPolyData to 3D image

David Welch dmwelch at engineering.uiowa.edu
Tue Apr 20 11:45:10 EDT 2010


Okay, I'm in the home stretch here... I've changed the code slightly to
output a XMLImageData file and take an input surface.  CMake runs fine on
it, but it dies in the make process with this error:

CMakeFiles/SurfaceToImage.dir/SurfaceToImage.cxx.o: In function
`vtkSmartPointer<vtkPolyDataToImageStencil>::New()':
/usr/local/include/vtk-5.7/vtkSmartPointer.h:113: undefined reference to
`vtkPolyDataToImageStencil::New()'

The smart pointer line is fundamentally no different than any other line of
code.  ???  Here's my code:
____________________________________________________________________________________________________________________
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkImageData.h>
#include <vtkPolyDataReader.h>
#include <vtkXMLImageDataWriter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <vtkPointData.h>

/**
 * This program generates a sphere (closed surface, vtkPolyData) and
converts it into volume
 * representation (vtkImageData) where the foreground voxels are 1 and the
background voxels are
 * 0. Internally vtkPolyDataToImageStencil is utilized. The resultant image
is saved to disk
 * in XML image data format.
 */
int main (int argc, char *argv[])
{
  if( argc < 3 )
  {
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputImageFile outputImageFile " << std::endl;
    return EXIT_FAILURE;
  }

  vtkSmartPointer<vtkPolyDataReader> surfaceSource =
vtkSmartPointer<vtkPolyDataReader>::New();
  surfaceSource->SetFileName( argv[1] );
  vtkSmartPointer<vtkPolyData> pd = surfaceSource->GetOutput();
  surfaceSource->Update();

  vtkSmartPointer<vtkImageData> whiteImage =
vtkSmartPointer<vtkImageData>::New();
  double bounds[6];
  pd->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]));
  }
  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);

  whiteImage->SetScalarTypeToUnsignedChar();
  whiteImage->AllocateScalars();

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

  // polygonal data --> image stencil:
  vtkSmartPointer<vtkPolyDataToImageStencil> pol2stenc =
vtkSmartPointer<vtkPolyDataToImageStencil>::New(); //<---- This is the
'problem'???
  pol2stenc->SetInput(pd);
  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();
  imgstenc->SetInput(whiteImage);
  imgstenc->SetStencil(pol2stenc->GetOutput());
  imgstenc->ReverseStencilOff();
  imgstenc->SetBackgroundValue(outval);
  imgstenc->Update();

  vtkSmartPointer<vtkXMLImageDataWriter> writer =
vtkSmartPointer<vtkXMLImageDataWriter>::New();
  writer->SetFileName( argv[2] ); //"SphereVolume.mhd");
  writer->SetInput(imgstenc->GetOutput());
  writer->Write();

  return EXIT_SUCCESS;
}
____________________________________________________________________________________________________________________



On Tue, Apr 20, 2010 at 6:37 AM, David Doria
<daviddoria+vtk at gmail.com<daviddoria%2Bvtk at gmail.com>
> wrote:

> On Tue, Apr 20, 2010 at 3:34 AM, Lars Friedrich Lars <
> lars-friedrich at gmx.net> wrote:
>
>> Hello David Welch,
>>
>> referring to your original question "how to voxelize a simple surface" I
>> added a VTK wiki example:
>>
>> http://www.cmake.org/Wiki/VTK/Examples/PolyDataToImageData
>>
>> It shows how we could incorporate vtkPolyDataToImageStencil into
>> voxelizing a *closed* surface.
>>
>> Please NOTE: as I wrote on the example page I'm not sure about the image
>> origin. The visual agreement in the sphere-image-overlay (paraview) is not
>> perfect and I'm not sure whether or not we had to introduce some
>> spacing-dependent image origin offset to compensate that. If you use that
>> code and find out something in this direction it would be great if you
>> contributed it to that example!
>>
>> HTH,
>>
>> lars
>>
>>
> David W -
>
> Yes, the normals are definitely necessary. With a mesh, you can simply run
> vtkPolyDataNormals. With a point set, you'd have to use my
> vtkPointSetNormalEstimation and vtkPointSetNormalOrientation filters (part
> of the same surface reconstruction journal submission). Unfortunately I
> don't know what it means by the missing ImageData element.
>
> Lars -
>
> Looks great, thanks! Hopefully David W will play around with it and solve
> the mystery of the origin problem.
>
> Thanks,
>
> David
>



-- 
David Welch
Graduate Student
Dept. of Biomedical Engineering
University of Iowa
Lab: (319) 335-5279
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20100420/65e41ed5/attachment.htm>


More information about the vtkusers mailing list