[vtkusers] Save a vtkContourTriangulator output inside a PNG
Romain LEGUAY
romain.leguay at gmail.com
Fri Nov 6 13:38:19 EST 2015
2015-11-06 15:41 GMT+01:00 Cory Quammen <cory.quammen at kitware.com>:
> Romain,
>
> Let's pop up a level and discuss what you are trying to do. It sounds like
> you are trying to voxelize a geometry into a 3D image. Is that right?
>
>
Exactly!
> You don't have to use the vtkCutter at all but rather set your geometry as
> the input for vtkPolyDataToImageStencil. I have used this class for
> voxelization in the past and it works very well.
>
I just did some test with just using vtkPolyDataToImageStencil and it works
perfectly!!!! At first I still had some black pictures but I fixed the
origin of the whiteImage and it's all working.
I forgot to put the code before, I'm going to fix my mistake now :)
Thanks again!
Romain
>
> HTH,
> Cory
>
> On Fri, Nov 6, 2015 at 9:32 AM, Romain LEGUAY <romain.leguay at gmail.com>
> wrote:
>
>> Thanks David for your answer!
>>
>> I just saw on the vtkPolyDataToImageStencil documentation that the
>> contour must be align throw the Z planes.
>>
>> I use vtkCutter to cut my mesh along Z-axis but all the pictures saved
>> are black. I attached my code and the CMakeLists.txt.
>>
>> Is there another way to "project" my filled contour on an image?
>>
>> Thanks again.
>>
>> Romain
>>
>>
>>
>> 2015-11-06 14:15 GMT+01:00 David Gobbi <david.gobbi at gmail.com>:
>>
>>> Hi Romain,
>>>
>>> The vtkPolyDataToImageStencil class needs a "hollow" shape as input,
>>> either a 3D surface or a 2D contour. If you fill the contour, then it
>>> can't
>>> be used by vtkPolyDataToImageStencil.
>>>
>>> - David
>>>
>>>
>>> On Fri, Nov 6, 2015 at 2:22 AM, Romain LEGUAY <romain.leguay at gmail.com>
>>> wrote:
>>>
>>>> Hello everyone,
>>>>
>>>> In purpose to create a series of pictures (with the same size 512*512
>>>> for example), I cut a mesh along an axis (X, Y or Z) with vtkCutter, then I
>>>> triangulate those contours with vtkContourTriangulator. I obtain some
>>>> "flat" vtkPolydata*s* (one per cut). Now, I want to save all those
>>>> "flat" meshes to 2D images with fixed size.
>>>> I saw on the wiki (
>>>> http://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/PolyDataToImageData)
>>>> how to convert a vtkPolydata in vtkImageData, but in this case, my
>>>> vtkPolydata is in a plane (the output of vtkContourTriangulator) so the
>>>> dimension of the white image is 0 or negative because of this part of code:
>>>>
>>>> vtkSmartPointer<vtkImageData> whiteImage =
>>>> vtkSmartPointer<vtkImageData>::New();
>>>> double bounds[6];
>>>> polydata->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])); // One of the dimension is 0
>>>> }
>>>> whiteImage->SetDimensions(dim);
>>>> whiteImage->SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1); //
>>>> Here
>>>>
>>>>
>>>> I don't know if there is other choice to convert a polydata to an image
>>>> but this code always give some black pictures.
>>>> I'm not sure if I use the good filter to convert my polydata to a 2D
>>>> image but I don't find anything.
>>>>
>>>> Do you have any clues?
>>>>
>>>> Thanks,
>>>>
>>>> Romain
>>>>
>>>
>>
>> _______________________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at
>> http://www.kitware.com/opensource/opensource.html
>>
>> Please keep messages on-topic and check the VTK FAQ at:
>> http://www.vtk.org/Wiki/VTK_FAQ
>>
>> Search the list archives at: http://markmail.org/search/?q=vtkusers
>>
>> Follow this link to subscribe/unsubscribe:
>> http://public.kitware.com/mailman/listinfo/vtkusers
>>
>>
>
>
> --
> Cory Quammen
> R&D Engineer
> Kitware, Inc.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20151106/51ef59c8/attachment.html>
-------------- next part --------------
cmake_minimum_required(VERSION 2.8)
PROJECT(Cutter)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(Cutter MACOSX_BUNDLE Cutter)
if(VTK_LIBRARIES)
target_link_libraries(Cutter ${VTK_LIBRARIES})
else()
target_link_libraries(Cutter vtkHybrid vtkWidgets)
endif()
-------------- next part --------------
#include <vtkSmartPointer.h>
#include <vtkOBJReader.h>
#include <vtkPNGWriter.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstdlib>
#include <iostream>
struct MatchPathSeparator
{
bool operator()(char ch) const
{
return ch == '/';
}
};
std::string basename(std::string const& pathname)
{
return std::string(std::find_if( pathname.rbegin(), pathname.rend(),
MatchPathSeparator() ).base(), pathname.end());
}
std::string removeExtension(std::string const& filename)
{
std::string::const_reverse_iterator pivot = std::find(
filename.rbegin(), filename.rend(), '.');
return pivot == filename.rend() ?
filename : std::string(filename.begin(), pivot.base() - 1);
}
/**
* Convert an object or a fundamental type to a std::string.
*/
template<typename T>
std::string toString(const T & val)
{
std::ostringstream oss;
oss << val;
return oss.str();
}
int main(int argc, char * argv[])
{
// Parse command line arguments
if(argc != 2)
{
std::cout << "Usage: " << argv[0] << " Filename(.obj)" << std::endl;
return EXIT_FAILURE;
}
std::string filename = argv[1];
vtkSmartPointer<vtkOBJReader> reader =
vtkSmartPointer<vtkOBJReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
double bounds[6];
reader->GetOutput()->GetBounds(bounds);
std::string baseOutput = removeExtension(basename(filename));
int count = 0;
for (double z = bounds[4]; z < bounds[5]; z += 0.1)
{
vtkSmartPointer<vtkPolyData> polydata = reader->GetOutput();
double spacing[3]; // desired volume spacing
spacing[0] = 0.005;
spacing[1] = 0.005;
spacing[2] = 1;
vtkSmartPointer<vtkImageData> whiteImage = vtkSmartPointer<vtkImageData>::New();
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];
origin[0] = bounds[0] + spacing[0] / 2;
origin[1] = bounds[2] + spacing[1] / 2;
origin[2] = bounds[4] + spacing[2] / 2 + z; // Move the origin along Z-axis
whiteImage->SetOrigin(origin);
whiteImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
// fill the image with foreground voxels:
unsigned char inval = 255;
unsigned char outval = 0;
vtkIdType pointCount = whiteImage->GetNumberOfPoints();
for (vtkIdType i = 0; i < pointCount; ++i)
{
whiteImage->GetPointData()->GetScalars()->SetTuple1(i, inval);
}
// polygonal data --> image stencil:
vtkSmartPointer<vtkPolyDataToImageStencil> pol2stenc =
vtkSmartPointer<vtkPolyDataToImageStencil>::New();
pol2stenc->SetInputData(polydata);
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->SetInputData(whiteImage);
imgstenc->SetStencilConnection(pol2stenc->GetOutputPort());
imgstenc->ReverseStencilOff();
imgstenc->SetBackgroundValue(outval);
imgstenc->Update();
std::string outputFilename = "./" + baseOutput + "_00" + toString(count) + ".png";
vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName(outputFilename.c_str());
writer->SetInputData(imgstenc->GetOutput());
writer->Write();
std::cout << outputFilename << std::endl;
++count;
}
return EXIT_SUCCESS;
}
More information about the vtkusers
mailing list