[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