ITK tutorial (15) vector as pixel type

1. General

This example illustrates how to parameterize a point set to manage a specific pixel type. It is common to associate vector values with points to create a geometric representation.

The following code shows how to use a vector value as the pixel type of the PointSet pointset class. Here, the itk::Vector class is used as the pixel type. This class is well suited to represent the relative position between two points. It can then be used to manage, for example, displacement.

2. Process details

In order to use a vector class, you must include its header file and the header file of the point set.

#include "itkVector.h"
#include "itkPointSet.h"

Vector classes are templated on the types used to represent spatial coordinates and spatial dimensions. Since the pixel type PixelType is independent of the point type PointType, we are free to choose vectors of any dimension as the pixel type. However, in order to create an interesting example, the vector we use will represent the displacement of points in the PointSet. Then select that the dimension of these vectors is the same as that of the point set PointSet.

const unsigned int Dimension = 3;
typedef itk::Vector< float, Dimension > PixelType;

Then we use the pixel type (actually vector) to instantiate the PointSet type of the point set, and then create a point set object.

typedef itk::PointSet< PixelType, Dimension > PointSetType;
PointSetType::Pointer pointSet = PointSetType::New();

The following code generates a sphere and assigns vector values to points. As shown in the figure below, the vector element calculated in this example is used to represent the tangent on the circle.

PointSetType::PixelType tangent;
PointSetType::PointType point;
unsigned int pointId = 0;
const double radius = 300.0;
for(unsigned int i=0; i<360; i++)
{
	const double angle = i * itk::Math::pi / 180.0;
	point[0] = radius * std::sin( angle );
	point[1] = radius * std::cos( angle );
	point[2] = 1.0; // flat on the Z plane
	tangent[0] = std::cos(angle);
	tangent[1] = -std::sin(angle);
	tangent[2] = 0.0; // flat on the Z plane
	pointSet->SetPoint( pointId, point );
	pointSet->SetPointData( pointId, tangent );
	pointId++;
}

Now we can access all the points and perform a displacement on the point using the vector represented by the pixel value. This follows the principle of a deformable model that can be displaced in each iteration.

typedef PointSetType::PointDataContainer::ConstIterator PointDataIterator;
PointDataIterator pixelIterator = pointSet->GetPointData()->Begin();
PointDataIterator pixelEnd = pointSet->GetPointData()->End();
typedef PointSetType::PointsContainer::Iterator PointIterator;
PointIterator pointIterator = pointSet->GetPoints()->Begin();
PointIterator pointEnd = pointSet->GetPoints()->End();
while( pixelIterator != pixelEnd && pointIterator != pointEnd )
{
pointIterator.Value() = pointIterator.Value() + pixelIterator.Value();
++pixelIterator;
++pointIterator;
}

Note: Here we use the constant Iterator ConstIterator instead of the general Iterator, because the pixel value is only used for reading and cannot be changed. ITK supports const correction at the API level.

The Itk::Vector class overloads the + operation in the itk::Point class. In other words, a vector can be added to a point to produce a new point. Using this feature in the loop body, you can use a statement to update the position of the point.

Finally, we can access all the points and print out the new values.

pointIterator = pointSet->GetPoints()->Begin();
pointEnd = pointSet->GetPoints()->End();
while( pointIterator != pointEnd )
{
std::cout << pointIterator.Value() << std::endl;
++pointIterator;
}

Note: itk::Vector is not a suitable class to represent surface normals and function gradients, which is determined by the behavior of vectors on affine transforms. ITK has a special class that represents normals and function gradients, namely ITK:: covariantvector class.

3. Code

 //  This example illustrates how to parameterize a point set to manage a specific pixel type. It is common to associate vector values with points to create a geometric representation.
 // The following code shows how to use a vector value as the pixel type of the PointSet pointset class. Here, the itk::Vector class is used as the pixel type.
 // This class is well suited to represent the relative position between two points. It can then be used to manage, for example, displacement.
 //
 //
 //  In order to use a vector class, you must include its header file and the header file of the point set.
#include "itkVector.h"
#include "itkPointSet.h"


int main(int, char *[])
{
	//  The Vector class is templated on the type used to represent spatial coordinates and spatial dimensions. Because the pixel type PixelType is independent of the point type PointType,
	// Therefore, we can freely choose vectors of any dimension as pixel types. But to create an interesting example,
	// The vector we use will represent the displacement of the points in the PointSet. Then select that the dimension of these vectors is the same as that of the point set PointSet.
	//
	constexpr unsigned int Dimension = 3;
	using PixelType = itk::Vector<float, Dimension>;



	//  Then we instantiate the PointSet type using pixeltype (actually vector) and then create a PointSet object.

	using PointSetType = itk::PointSet<PixelType, Dimension>;
	PointSetType::Pointer pointSet = PointSetType::New();
	
	//
	//  The following code generates a sphere and assigns vector values to these points. In this example, the component of the vector is calculated to represent the tangent to the circle, as shown below  
	PointSetType::PixelType tangent;
	PointSetType::PointType point;

	unsigned int     pointId = 0;
	constexpr double radius = 300.0;

	for (unsigned int i = 0; i < 360; i++)
	{
		const double angle = i * itk::Math::pi / 180.0;
		point[0] = radius * std::sin(angle);
		point[1] = radius * std::cos(angle);
		point[2] = 1.0; // flat on the Z plane
		tangent[0] = std::cos(angle);
		tangent[1] = -std::sin(angle);
		tangent[2] = 0.0; // flat on the Z plane
		pointSet->SetPoint(pointId, point);
		pointSet->SetPointData(pointId, tangent);
		pointId++;
	}

	// Now we can access all the points and perform a displacement on the point using the vector represented by the pixel value. This follows the principle of a deformable model that can be displaced in each iteration.
	using PointDataIterator = PointSetType::PointDataContainer::ConstIterator;
	PointDataIterator pixelIterator = pointSet->GetPointData()->Begin();
	PointDataIterator pixelEnd = pointSet->GetPointData()->End();

	using PointIterator = PointSetType::PointsContainer::Iterator;
	PointIterator pointIterator = pointSet->GetPoints()->Begin();
	PointIterator pointEnd = pointSet->GetPoints()->End();

	while (pixelIterator != pixelEnd && pointIterator != pointEnd)
	{
		std::cout << pointIterator.Value() << std::endl;
		std::cout << pointIterator.Value() << std::endl;
		pointIterator.Value() = pointIterator.Value() + pixelIterator.Value();
		++pixelIterator;
		++pointIterator;
	}

	//
	//  Note: Here we use the constant Iterator ConstIterator instead of the general Iterator iterator,
	// Because pixel values are only used for reading and cannot be changed. ITK supports const correction at the API level.


	//  The Itk::Vector class overloads the + operation in the itk::Point class. In other words, a vector can be added to a point to produce a new point.
	//  Using this feature in the loop body, you can use a statement to update the position of the point.
	//  Finally, we can access all the points and print out the new values.

	pointIterator = pointSet->GetPoints()->Begin();
	pointEnd = pointSet->GetPoints()->End();
	while (pointIterator != pointEnd)
	{
		std::cout << pointIterator.Value() << std::endl;
		++pointIterator;
	}
	// Note: itk::Vector is not a suitable class to represent surface normals and function gradients, which is determined by the behavior of vectors on affine transforms.
	// ITK has a special class that represents normals and function gradients, namely ITK:: covariantvector class.

	return EXIT_SUCCESS;
}

4. Result display

Posted by scheda on Thu, 04 Nov 2021 12:20:37 -0700