平台由许多子系统组成,下面将对一些主要的子系统进行介绍。本章的后半部分(在后 续章节中)将对这些概念进行详细介绍(注意:前面章节已经介绍了其他两个 InsightDocuments 和 InsightApplications)。
像其他软件系统一样,ITK 也是围绕一些核心设计概念创建的。重要的 概念包括有:范型编程、内存管理智能指针、可修改对象实例的对象工厂、使用 command/observer 图表的事件管理和多线程支持。
有两个基本的类来表示数据:itk::Image 和 itk::Mesh。另外,有许多类型的迭代器和容器用来保持和转移数据。其他一些重要但不常用的类也可以用来表示数 据,例如 histograms 和 BLOX 图像。
表示数据的类(数据对象)经过滤波器操作被组织进入数据流管道。这
些管道保持静态并只在必要时才会运行。它们同样支持多线程和流动功能(例如:能将数据 最小化到内存区域中)。
同数据处理管道相关联的是 sources 和 mappers,sources 是初始化管道的滤波 器,mappers 是终止管道的滤波器。sources 和 mappers 的标准样例分别是 readers 和 writters。
readers 输入数据(通常从一个文件),而 writters 从管道输出数据。
ITK 中使用空间对象层来表示几何图形。这些类支持解剖结构模式。使用一
个普通的基本界面,空间对象就可以用不同的方式来表示空间区域。例如:网状结构、图像 模块和用来作为潜在表达方案的暗含等式方程。空间对象是一个自然数据结构,它可以与图 像分割结果相关联和对分割和配准方法事先做解剖介绍。
一个灵活的配准框架支持四种不同的配准类型:图像配准、多方式配准、基
于 PDE 的配准和 FEM(有限成员方法 Finite Element Method)配准。
ITK 包含有一个处理基本 FEM 问题的子系统,尤其是非严格配准。FEM 工
具包包含有网格定义(结点和成员)、载入和边界条件。
水平集框架是一个创建滤波器的类群,用来增加有限变换反复迭代的方法
求解关于图像的偏微分方程。这个水平集框架由有限的几个不同的 solvers 组成,包括一个 稀疏的水平集 solvers、一个通用水平集分割滤波器和一些特定的子类,这些子类包括基于 阈值、Canny 和拉普拉斯的方法。
ITK 使用一个独特的、强有力的系统来生成一个界面(例如:封装),该界面用 来解释像 Tc l 和 Python 之类的程序语言。GCC_XML 工具用来产生一个对任何复杂 C++代 码的 XML 描述;然后使用 CSWIG 工具包将 XML 描述转化成封装。
在系统中有许多辅助子系统可以为其他类做支持。例如:计算机类产生特定
的算子来为滤波器提供支持(例如:均值计算机计算一个样本的均值)。其他功能还包括有: 一个偏 DICOM 剖析器、MetaIO 文件支持、png、zlib、FLTK/Qt 图像视窗和 VTK 系统界面。
以上可以看为是整个ITK的几个大块,看成是不同的章节,当然彼此是有相互使用的地方。
ITK中有两种基本的数据表达类型: Image、Mesh。这两个类都是itk::DataObject的子类。 在ITK中,数据对象是哪些分送系统和参与数据流管道的类。
itk::Image 表示一个 n 维、规则的样品数据。采样方向平行于任一个坐标轴,采样起点、 像素间隔和每个方向上的样品数量(如图像维数)是特定的。这个样品或像素在 ITK 中的 类型是任意的,一个模板参数 TPixel 指定了模板实例的类型(当对图像类实例化时图像的 维也必须指定)。如果要在所有情况下编译代码(例如使用这些操作通过特定的滤波器来进 行处理),关键就是像素的类型必须支持这些操作(如加法和减法)。在实际中 ITK 用户通 常使用 C++中的简单类型(如整型、浮点型)或预定义像素类型而很少创建新的像素类型。
ITK 中关于图像的一个重要概念是区域【regions】,它是一个矩形的、连续的图像块。区域用来指定图像中处理的部分,例如多线程或保留在内存中的部分。在 ITK 中有三种常用的区域类型:
网格类表示一个n维无结构的格子。网格类的拓扑布局是由一套单元(cells)来表示的,单元是通过n维的点(points)组合而成的。 网格的几何结构是不同单元利用插补函数来定义的。网格设计为 一个自适应表达结构,按照在其上实行的操作来进行改变。表达一个网格最起码是需要点和单元的;但是也可以增加额外的拓扑信息。
网格以三个模板参数的形式来定义:
网格是 itk::pointSet 的一个子类。点集类可以用来表示云点和随意分布的特征点等。点
集类和拓扑结构无关。
数据对象(例如图像和网格)是用来代表数据的,过程对象就是用来操作数据对象并产生新的数据对象的类。
像 sourse、filter object 和 mappers 都是过程对象。Sourse(例如 readers)生成数据,filter object 载入数据并经过处理产生新的数据,而 mappers 接收数据并输出到一个文件或其他系统中。有时 filter 可以在广义上表示所有三种类型。
数据处理管道连接了数据对象(如图像和网格)和过程对象。管道支持一个自动更新机制。该机制在当且仅当它的输入或内在状态改变时才会唤起一个滤波器来运行。另外,数据管道还支持 streaming,可以自动将数据分成许多小部分,对这些小部分进行逐一处理,并重新集合处理后的数据产生最终结果。
通常使用SetInput()和GetOuput()方式连接数据对象和过程对象。例如:
typedef itk::Image<float,2> FloatImage2DType;
itk::RandomImageSource<FloatImage2DType>::Pointer random;
random = itk::RandomImageSource<FloatImage2DType>::New( );
random->SetMin(0.0);
random->SetMax(1.0);
itk::ShrinkImageFilter<FloatImage2DType,FloatImage2DType>::Pointer shrink;
shrink = itk::ShrinkImageFilter<FloatImage2DType,FloatImage2DType>::New( );
shrink->SetInput(random->GetOutput( ));
shrink->SetShrinkFactors(2);
itk::ImageFileWriter::Pointer<FloatImage2DType> writer;
writer = itk::ImageFileWriter::Pointer<FloatImage2DType>::New( );
writer->SetInput (shrink->GetOutput( ));
writer->SetFileName( ‘‘test.raw’’ );
writer->Update( );
在这个例子中,源代码对象 itk::RandomImageSource 同 itk::ShrinkImageFilter 相连接,shrink 滤波器和 mapper itk::ImageFileWriter 相连。当调用 Update( )方式时,数据处理管道就会按顺序使用这些滤波器,并将最终结果储存到文件中。