1、图像数据结构

数字图像文件内容由两个部分组成:图像头信息和数据。

 图像头信息定义了图像的基本信息,主要包括起点位置(Origin)像素间隔(space)维数(dimension)

通过这三个参数即可以决定图像空间位置和规模。图像可以看做是空间中的一个规则网格,网格中的每个最小单元称之为一个像素(二维)或者体素(三维),这样网格在每个方向上的像素或者体素个数即为图像在该方向的维数。像素索引表示每个像素在图像网格中的位置,是图像内部的网格坐标。而在医学图像中,每个图像除了内部坐标外,还存在一个世界坐标。这个世界坐标依赖于成像设备。在医学图像中起点位置(Origin),像素间隔(space)和图像维数决定了世界坐标系。这样通过起点位置,像素间隔和像素索引即可计算每个像素的世界坐标位置。
                                                                         

图像数据即为图像像素的像素值,一般采用一维数组来表示和存储。已知像素索引和图像维数下,即可计算每个像素对应的像素值。通常图像的像素值为一个标量,例如一般灰度图像;图像像素值也可以是一个向量,例如彩色图像;另外图像像素值还可以是张量,如梯度场图像。医学图像处理中大部分的图像都是灰度图像。
这里需要注意灰度图像的灰度值的数据类型,在一般的灰度图像处理中不需要考虑,因为其范围默认为0-255,可以采用一个unsigned char类型来表示。但是在医学图像处理中,256灰度级远远不能满足要求,因此灰度范围往往大于256级。常见的医学图像的像素数据类型为unsigned short,灰度范围为0-65536。
 

 2.采用Source创建源图像

VTK中内置多个创建图像的Source,利用这些Source可以快速的创建图像,其中以vtkImageCanvasSource2D为代表。该Source功能是创建一个画布(空白图像),并提供了多种几何图形(点、线段、圆、矩形以及图像等)的绘制填充功能。

#include <vtkAutoInit.h>      
VTK_MODULE_INIT(vtkRenderingOpenGL2);  
 
#include<vtkSmartPointer.h>
#include<vtkImageCanvasSource2D.h>
#include<vtkImageData.h>
#include<vtkImageActor.h>
#include<vtkRenderer.h>
#include<vtkRenderWindow.h>
#include<vtkRenderWindowInteractor.h>
#include<vtkInteractorStyleImage.h>
 
int main()
{
	vtkSmartPointer<vtkImageCanvasSource2D> canvas =
		vtkSmartPointer<vtkImageCanvasSource2D>::New();
	canvas->SetScalarTypeToUnsignedChar();
	canvas->SetNumberOfScalarComponents(1);
	canvas->SetExtent(0,100,0,100,0,0);
	canvas->SetDrawColor(0,0,0,0);
	canvas->FillBox(0,100,0,100);
	canvas->SetDrawColor(255,0,0,0);
	canvas->FillBox(20,40,20,40);
	canvas->Update();  //这一步还必不可少诶???
 
	//创建演员
	vtkSmartPointer<vtkImageActor> actor =
		vtkSmartPointer<vtkImageActor>::New();
	actor->SetInputData(canvas->GetOutput());
	//定义视窗
	double viewport[4] = {0,0,1,1};
	vtkSmartPointer<vtkRenderer> renderer = 
		vtkSmartPointer<vtkRenderer>::New();
	renderer->SetViewport(viewport);
	renderer->AddActor(actor);
	renderer->ResetCamera();
	renderer->SetBackground(1.0,1.0,1.0);
 
	//设置渲染窗口(搬上舞台)
	vtkSmartPointer<vtkRenderWindow> renderwindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderwindow->AddRenderer(renderer);
	renderwindow->SetSize(640,480);
	renderwindow->Render();
	renderwindow->SetWindowName("ImageCanvasSource2D");
 
	//设置窗口交互(演员-观众)
	vtkSmartPointer<vtkRenderWindowInteractor> rwi = 
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	vtkSmartPointer<vtkInteractorStyleImage> style = 
		vtkSmartPointer<vtkInteractorStyleImage>::New();
	rwi->SetInteractorStyle(style);
	rwi->SetRenderWindow(renderwindow);
	rwi->Initialize();
	rwi->Start();
 
	return 0;
}

 在上面代码中,首先定义了一个vtkImageCanvasSource2D的指针,然后设置画布的像素数据类型,像素成分数目和画布的大小。然后,在该画布中,利用FillBox绘制两个填充矩形,并通过SetDrawColor()来设置两个矩形的颜色。
代码运行结果为:

                                                             

 3.直接创建一幅图像

VTK中可以手动生成图像,然后根据需要进行像素赋值。

#include <vtkAutoInit.h>      
VTK_MODULE_INIT(vtkRenderingOpenGL2);  
 
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyle.h>
 
#include <vtkInformation.h>
 
int main()
{
	//vtk的新版本在vtkImageData类中取消了SetScalarTypeToUnsignedChar()方法;
	//现在仅能用如下方法设置:
	//static void SetScalarType(int, vtkInformation* meta_data);
	vtkSmartPointer<vtkImageData> img =
		vtkSmartPointer<vtkImageData>::New();
	vtkSmartPointer<vtkInformation> info =
		vtkSmartPointer<vtkInformation>::New(); 
	img->SetDimensions(16,16,1);
	img->SetScalarType(VTK_UNSIGNED_CHAR,info);
	img->SetNumberOfScalarComponents(1,info);//每个像素需要表示的组份 =1是指标量图
	img->AllocateScalars(info);//很重要
 
 
	unsigned char *ptr = NULL;
	ptr = (unsigned char*)img->GetScalarPointer();
 
	for(int i=0; i<16*16*1; i++)
	{
		*ptr ++ = i%256;
	}
	///////////////启动渲染引擎
	vtkSmartPointer<vtkImageActor> actor =
		vtkSmartPointer<vtkImageActor>::New();
	actor->SetInputData(img);
 
	double viewport[4] = {0,0,1,1};
	vtkSmartPointer<vtkRenderer> render =
		vtkSmartPointer<vtkRenderer>::New();
	render->SetViewport(viewport);
	render->AddActor(actor);
	render->ResetCamera();
	render->SetBackground(1,1,1);
 
	vtkSmartPointer<vtkRenderWindow> window =
		vtkSmartPointer<vtkRenderWindow>::New();
	window->AddRenderer(render);
	window->SetSize(640,480);
	window->Render();
	window->SetWindowName("CreateVTKImageData");
 
	vtkSmartPointer<vtkRenderWindowInteractor> rwi = 
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	vtkSmartPointer<vtkInteractorStyle> style =
		vtkSmartPointer<vtkInteractorStyle>::New();
	rwi->SetInteractorStyle(style);
	rwi->SetRenderWindow(window);
	rwi->Initialize();
	rwi->Start();
 
	return 0;
}

首先定义vtkImageData指针,然后指定图像的维数,而图像的原点和像素间隔则都是采用默认值,因此不需要设置。SetScalarType指定图像的每个像素值的数据类型为unsigned char,SetNumberOfScalarComponents则指定了每个像素值的数据成分为1,每个像素值为1个标量值,参数设置完毕后,调用AllocateScalars()分配内存,生成图像数据。图像生成后,默认所有像素值为0。可以通过访问图像数据数组来设置每个像素值,GetScalarPointer()即返回图像的数据数组(图像数据数组都采用一维数组),然后根据图像的大小,访问每个像素并为其赋值。生成的图像如下所示:

                                                                                    

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐