http://image.szpt.edu.cn/UploadFiles/%E5%9B%BE%E5%83%8F%E6%95%B0%E6%8D%AE%E5%8F%8A%E5%85%B6%E5%A4%84%E7%90%86.swf
图像数据集用类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(); } } }
效果图:美美的阿江与夫人