ITK入门教程(15)向量作为像素类型

1.概述

这个例子阐述了如何参数化一个点集来管理一个特定的像素类型。将向量值和点相关联以创建一个几何表示是很普遍的。

下面的代码展示了如何使用向量值作为点集PointSet类的像素类型。在这里使用itk::Vector 类作为像素类型。这个类很适合表示两个点之间的相对位置。然后就可以使用它来管理例如位移。

2.过程详解

为了使用向量类必须包含它的头文件和点集的头文件。

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

向量类是在用来表示空间坐标和空间维数的类型上进行模板化的。由于像素类型PixelType独立于点类型PointType,所以我们可以自由地选择任意维数的向量作为像素类型。但是,为了创建一个有趣的例子,我们使用的向量将可以代表点集PointSet 中的点的位移。然后选择这些向量的维数与点集PointSet的维数相同。

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

然后我们使用像素类型(事实上是向量)来对点集PointSet 类型进行实例化,进而创建一个点集对象。

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

下面的代码生成了一个球体,并分配向量值给点。如下图所示,这个例子中计算得到的向量元素用来表示圆上的切线。
在这里插入图片描述

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++;
}

现在我们可以访问所有的点,并使用像素值表示的向量来执行点上的一个位移。这遵循一种在它的每次迭代中都可以进行位移的可形变模型的原则。

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

注意:这里我们使用的是常量迭代器ConstIterator而不是一般的迭代器Iterator,因为像素值仅仅用来读取而不能更改。ITK 在API级别支持const-correctness

Itk::Vector 类重载了itk::Point类中的+操作。换句话说,向量可以加到点上来产生一个新的点。在循环体中利用这个特性就可以使用一条语句来更新点的位置。

最后我们可以访问所有的点并打印输出新的数值。

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

注意:itk::Vector 并不是表示表面法线和函数梯度的合适的类,这是由于向量在仿射变换(affine transforms)上的行为方式决定的。ITK 有一种表示法线和函数梯度的特殊类,就是itk::ConvariantVector类。

3.代码

 //  这个例子阐述了如何参数化一个点集来管理一个特定的像素类型。将向量值和点相关联以创建一个几何表示是很普遍的。
 // 下面的代码展示了如何使用向量值作为点集PointSet类的像素类型。在这里使用itk::Vector 类作为像素类型。
 // 这个类很适合表示两个点之间的相对位置。然后就可以使用它来管理例如位移。
 //
 //
 //  为了使用向量类必须包含它的头文件和点集的头文件。
#include "itkVector.h"
#include "itkPointSet.h"


int main(int, char *[])
{
	//  Vector类是在用来表示空间坐标和空间维数的类型上进行模板化的。由于像素类型PixelType独立于点类型PointType,
	// 所以我们可以自由地选择任意维数的向量作为像素类型。但是,为了创建一个有趣的例子,
	// 我们使用的向量将可以代表点集PointSet 中的点的位移。然后选择这些向量的维数与点集PointSet的维数相同。
	//
	constexpr unsigned int Dimension = 3;
	using PixelType = itk::Vector<float, Dimension>;



	//  然后我们使用PixelType(实际上是vector)实例化PointSet类型,并随后创建一个PointSet对象。

	using PointSetType = itk::PointSet<PixelType, Dimension>;
	PointSetType::Pointer pointSet = PointSetType::New();
	
	//
	//  下面的代码是生成一个球体并为这些点分配向量值。 在这个例子中,向量的分量被计算来表示与圆的切线,如下所示  
	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++;
	}

	// 现在我们可以访问所有的点,并使用像素值表示的向量来执行点上的一个位移。这遵循一种在它的每次迭代中都可以进行位移的可形变模型的原则。
	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;
	}

	//
	//  注意:这里我们使用的是常量迭代器ConstIterator而不是一般的迭代器Iterator,
	// 因为像素值仅仅用来读取而不能更改。ITK 在API级别支持const-correctness。


	//  Itk::Vector 类重载了itk::Point类中的+操作。换句话说,向量可以加到点上来产生一个新的点。
	//  在循环体中利用这个特性就可以使用一条语句来更新点的位置。
	//  最后我们可以访问所有的点并打印输出新的数值。

	pointIterator = pointSet->GetPoints()->Begin();
	pointEnd = pointSet->GetPoints()->End();
	while (pointIterator != pointEnd)
	{
		std::cout << pointIterator.Value() << std::endl;
		++pointIterator;
	}
	// 注意:itk::Vector 并不是表示表面法线和函数梯度的合适的类,这是由于向量在仿射变换(affine transforms)上的行为方式决定的。
	// ITK 有一种表示法线和函数梯度的特殊类,就是itk::ConvariantVector类。

	return EXIT_SUCCESS;
}

4.结果展示

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值