什么是vtkImageData
vtkImageData
是一个表示规则的、均匀间隔的三维网格的数据结构。它是VTK中用于图像处理和体积渲染的基础类,可以用来表示从简单的二维图像到复杂的三维数据集。vtkImageData
通过定义每个网格点(或体素)上的标量或向量值来存储信息,使得它适用于各种科学计算和可视化应用。
关键概念和方法
维度、间距和原点
在使用vtkImageData
之前,理解其三个基本属性——维度、间距和原点——是非常重要的。
- 维度:指定了图像或体积数据在三个方向(x、y、z)上的大小。
- 间距:每个体素在各个方向上的实际物理距离,允许数据在不同的比例尺上被表示。
- 原点:数据集在空间中的起始点,通常是左下角的点。
Extent
Extent
由六个整数组成,格式为 [xMin, xMax, yMin, yMax, zMin, zMax]
,这六个值分别定义了数据集在X、Y、Z轴方向上的最小和最大索引。这意味着Extent定义了一个立方体(或者对于二维数据是一个矩形),包含了数据集中所有的数据点。
vtkImageData imageData = vtkImageData.New();
imageData.SetExtent(0, 9, 0, 9, 0, 0); // 对于二维图像,Z轴的范围通常是0到0
这段代码创建了一个10x10像素的二维图像,其中Extent在X和Y方向上从0到9,Z方向上是0(因为它是二维的)。
虽然
Extent
定义了数据点的索引范围,但Spacing
和Origin
则定义了这些点在实际物理空间中的位置和间隔。
数据分配与填充(AllocateScalars)
AllocateScalars
是vtkImageData
中的一个关键方法,用于在内存中为图像数据分配空间。这个方法的调用是在图像数据对象的初始化阶段的一个重要步骤,因为它为后续的数据填充和图像处理操作建立了基础。
AllocateScalars
的主要作用是为vtkImageData
对象预留足够的内存空间,以存储图像的标量值或颜色信息
。这一步骤确保了当我们向图像数据中填充值或对其进行操作时,有一个已经定义好大小和类型的数据结构等待我们的操作。
AllocateScalars
方法通常接受两个参数:
数据类型:指定存储图像标量值的数据类型。VTK提供了一系列的数据类型常量,如
VTK_UNSIGNED_CHAR
、VTK_FLOAT
等,以支持不同的数值范围和精度要求。选择合适的数据类型对于图像数据的有效表示非常重要。组件数:指定每个数据点可以有多少个分量。对于灰度图像,每个像素点通常只有一个分量;而对于彩色图像,可能有三个分量(红、绿、蓝)或更多,如果包含了透明度信息,则可能有四个分量。
调用时机和上下文:
在创建vtkImageData
对象并通过SetDimensions
、SetSpacing
和SetOrigin
方法设置好基本属性后,应该调用AllocateScalars
方法为该对象分配内存。这个步骤是在填充数据(例如,通过SetScalarComponentFromDouble
方法设置每个体素的值)之前必须完成的。
// 初始化vtkImageData
var imageData = vtkImageData.New();
imageData.SetDimensions(50, 50, 50);
imageData.SetSpacing(1.0, 1.0, 1.0);
imageData.SetOrigin(0.0, 0.0, 0.0);
imageData.AllocateScalars(3, 1);
// 填充数据
for (int z = 0; z < 50; z++)
{
for (int y = 0; y < 50; y++)
{
for (int x = 0; x < 50; x++)
{
var value = (x * y * z) % 255;
imageData.SetScalarComponentFromDouble(x, y, z, 0, value);
}
}
}
举个栗子:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 获取 RenderWindowControl 的渲染器
var renderer = renderWindowControl.RenderWindow.GetRenderers().GetFirstRenderer();
renderer.RemoveAllViewProps();
//var renderWindowInteractor = vtkRenderWindowInteractor.New();
//renderWindowInteractor.SetRenderWindow(renderWindow);
// 创建vtkImageData
var imageData = vtkImageData.New();
imageData.SetDimensions(50, 50, 50);
imageData.SetSpacing(1.0, 1.0, 1.0);
imageData.SetOrigin(0.0, 0.0, 0.0);
imageData.AllocateScalars(3, 3);
// 填充数据
int[] dims = imageData.GetDimensions();
for (int z = 0; z < dims[2]; z++)
{
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
byte[] pixel = { (byte)(x * 5), (byte)(y * 5), (byte)(z * 5) };
IntPtr ptr = imageData.GetScalarPointer(x, y, z);
System.Runtime.InteropServices.Marshal.Copy(pixel, 0, ptr, 3);
}
}
}
// 创建映射器和Actor来渲染图像数据
var mapper = vtkDataSetMapper.New();
mapper.SetInputData(imageData);
// 创建Actor
var actor = vtkActor.New();
actor.SetMapper(mapper);
// 将Actor添加到Renderer中
renderer.AddActor(actor);
renderer.SetBackground(0.1, 0.2, 0.4); // 设置背景颜色
}
出来的图就是酱紫的:
System.Runtime.InteropServices.Marshal.Copy
方法是.NET Framework
中一个非常重要的函数,用于在托管代码和非托管代码之间复制数据。这个方法属于System.Runtime.InteropServices
命名空间,主要用于高级内存操作,尤其是在需要直接与操作系统的内存进行交互时。Marshal.Copy
提供了一种安全的方式来复制字节数据,避免了直接使用指针可能引发的安全问题和稳定性问题。
Marshal.Copy
有几个重载版本,允许从托管数组到非托管内存、从非托管内存到托管数组的数据复制,以及在托管数组之间复制数据。以下是几个常见重载版本的简介:
1.从托管数组到非托管内存:
public static void Copy(byte[] source, int startIndex, IntPtr destination, int length);
public static void Copy(char[] source, int startIndex, IntPtr destination, int length);
public static void Copy(short[] source, int startIndex, IntPtr destination, int length);
public static void Copy(int[] source, int startIndex, IntPtr destination, int length);
这些重载允许将不同类型的托管数组(如byte[], char[], short[], **int[]**等)从指定的起始索引开始,复制指定长度的数据到非托管内存的指定位置。
2.从非托管内存到托管数组:
public static void Copy(IntPtr source, byte[] destination, int startIndex, int length);
public static void Copy(IntPtr source, char[] destination, int startIndex, int length);
public static void Copy(IntPtr source, short[] destination, int startIndex, int length);
public static void Copy(IntPtr source, int[] destination, int startIndex, int length);
这些重载允许从非托管内存的指定位置开始,复制指定长度的数据到托管数组的指定起始索引位置。
例如,当你使用VTK处理图像数据,并需要将颜色值直接填充到图像的像素中时,Marshal.Copy
可以用来将包含颜色值的托管数组(如RGB值)安全地复制到VTK图像数据结构的内存位置。这样的操作既高效又安全,是.NET中处理高级内存操作的首选方法。
支持输入/输出类型为vtkImageData的读写器类
类名 | 功能 |
---|---|
vtkBMPReader | 读BMP图像 |
vtkBMPWriter | 写BMP图像 |
vtkJPEGReader | 读JPEG图像 |
vtkJPEGWriter | 写JPEG图像 |
vtkPNGReader | 读PNG图像 |
vtkPNGWriter | 写PNG图像 |
vtkTIFFReader | 读TIFF图像 |
vtkTIFFWriter | 写TIFF图像 |
vtkMetaImageReader | 读MHA|MHD图像 |
vtkMetaImageWriter | 写MHA|MHD图像 |
vtkDicomImageReader | 读DICOM图像 |
vtkXMLImageDataReader | 读基于XML文件格式图像 |
vtkXMLImageDataWriter | 写基于XML文件格式图像 |
vtkImageReader | 读RAW格式图像 |
vtkImageWriter | 写RAW格式图像 |