图像数据集用类vtkImageData表示。其结构与结构化点数据集是一样的,由像素(vtkPixel)或体素(vtkVoxel)构成。图像数据通常只有标量属性。后面提到的图像的灰度、颜色值,一般都是指标量数据。
当初,VTK是用vtkStructuredPoints来表达图像的。但是随着越来越多的图像处理功能要添加进VTK中,便要求共有一个更灵活的类,要能支持数据的并行处理和流处理等,于是vtkImageData就产生了。之后又经过了几个VTK发行版本,图像数据集开始可以和一般数据集放进同一条流水线中,这样vtkImageData和 vtkStructuredPoints就非常类似了。现在vtkStructuredPoints 几乎是vtkImageData的一个空子集。
以上摘自周振环老师的《医学图像编程技术》
手动创建图像数据集
手动创建图像数据集的结构和结构化点集一样,只要设置起点、尺寸和间隔,对于标量数据,除了可以可以使用SetScalars()指定一个数据数组以外,vtkImageData还有一些自己的方法。
代码如下:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void renderWindowControl1_Load(object sender, EventArgs e)
{
vtkImageData id = new vtkImageData();
id.SetDimensions(10,25,100);
//id.SetScalarTypeToUnsignedShort();
id.SetScalarTypeToUnsignedChar();
id.SetNumberOfScalarComponents(1);
id.AllocateScalars();//vtkImageData特有的方法,用于分配存储标量数据的内存空间
//AllocateScalars使用之前必须设置好相关参数,包括点的个数(通过尺寸设置),标量数据类型和标量分量个数
IntPtr ptr = id.GetScalarPointer();//vtkImageData特有的方法,用于获取标量数据存储地址的首地址
//这里和C++中的代码是不一样的。
Random random = new Random();
unsafe
{
byte* src = (byte*)ptr.ToPointer();
for (ushort i = 0; i < 10 * 25 * 100;i++ )
{
*src++ = (byte)(random.Next(0,256));
}
}
vtkImageActor actor = new vtkImageActor();
//vtkImageActor是一个复合类,其中包含一个actor和一个mapper
actor.SetInput(id);
vtkRenderWindow _renwin = renderWindowControl1.RenderWindow;
vtkRenderer _render = _renwin.GetRenderers().GetFirstRenderer();
_render.AddActor(actor);
_renwin.Render();
_render.ResetCamera();
}
}
程序化生成图像数据集
VTK提供一些源对象来程序化生成图像数据。程序化生成多变性数据集,主要创建的是数据集的结构,而这里主要创建的是标量数据。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void renderWindowControl1_Load(object sender, EventArgs e)
{
vtkImageCanvasSource2D imCan = new vtkImageCanvasSource2D();
//vtkImageCanvasSource2D可以按照指定大小和类型创建一个空白的2D图像画布(这里的空白指的是没有标量数据)
//然后可以在这个画布上画各种图形元素,包括方块、线和圆等
imCan.SetScalarTypeToUnsignedChar();//设置标量值类型
imCan.SetExtent(0,511,0,511,0,0);//设置图像画布的大小
imCan.SetDrawColor(86);
imCan.FillBox(0,511,0,511);//背景方块
imCan.SetDrawColor(0.0);
imCan.FillTube(500,20,30,400,5);//有宽度的线段
imCan.SetDrawColor(255);
imCan.DrawSegment(10,20,500,510);//线段
imCan.SetDrawColor(0.0);
imCan.DrawCircle(400,350,80.0);//圆周
imCan.SetDrawColor(255);
imCan.FillPixel(450,350);//填充
imCan.SetDrawColor(170);
imCan.FillTriangle(100,100,300,150,150,300);//三角形
vtkImageActor actor = new vtkImageActor();
actor.SetInput(imCan.GetOutput());
vtkRenderWindow _renwin = renderWindowControl1.RenderWindow;
vtkRenderer _render = _renwin.GetRenderers().GetFirstRenderer();
_render.AddActor(actor);
_renwin.Render();
_render.ResetCamera();
}
}
效果图如下:
vtkImageEllipsoidSource和vtkImageGaussionSource的的介绍这里省略了,以后有机会再找一下例子补上。
vtkImageGridSource 产生一个网格图像。整个图像分为网格线和网格内两部分,分别设置不同的颜色值。vtkImageGridSource 通常与vtkImageBlend混合使用,是现在一幅图像上面显示网格的效果。
namespace vtkImageGridSourcetest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void renderWindowControl1_Load(object sender, EventArgs e)
{
vtkPNGReader reader = new vtkPNGReader();
reader.SetFileName(@"E:\beauty.png");
reader.SetDataByteOrderToLittleEndian();
reader.Update();
int width = reader.GetOutput().GetDimensions()[0];
int height = reader.GetOutput().GetDimensions()[1];
vtkImageGridSource imageGrid = new vtkImageGridSource();
imageGrid.SetGridSpacing(100,100,0);
imageGrid.SetGridOrigin(0,0,0);
imageGrid.SetDataExtent(0,width,0,height, 0,0);
imageGrid.SetLineValue(4095);
imageGrid.SetFillValue(0);
imageGrid.SetDataScalarType(reader.GetDataScalarType());
vtkImageBlend blend = new vtkImageBlend();
blend.SetOpacity(0,0.5);
blend.SetOpacity(1,0.5);
blend.AddInputConnection(reader.GetOutputPort());
blend.AddInputConnection(imageGrid.GetOutputPort());
vtkImageActor actor = new vtkImageActor();
actor.SetInput(blend.GetOutput());
vtkRenderWindow _renwin = renderWindowControl1.RenderWindow;
vtkRenderer _render = _renwin.GetRenderers().GetFirstRenderer();
_render.AddActor(actor);
_renwin.Render();
_render.ResetCamera();
}
}
}
效果图:美美的阿江与夫人