VTK笔记-vtkImageData

vtkImageData

  vtkImageData是由vtkDataSet所派生出的一个子类,由之前的笔记VTK笔记-数据集与数据属性中可以知道,数据集由组织结构以及组织结构相关联的属性数据;数据集的组织结构由拓扑结构和几何结构两部分组成。vtkDataSet是一个抽象基类,结构的实现及表达由其具体的子类来完成;
在这里插入图片描述
  vtkImageData用于表示VTK中的图像数据,是VTK中常见的数据集之一;vtkImageData可以表示3维立体图像也可以表示2维平面图像,在VTK内与图像相关的数据集以及图像处理的管线中,vtkImageData都占据了极为的重要地位;
  vtkImageData可以用于不同格式图像的读取Reader和保存Writer;
  vtkImageData可以用于规则的离散点或者序列图像的的float数据和short数据转换vtkImageData,用于图像的渲染显示;

接口

单元和点

获取Get
// 获取单元个数
vtkIdType GetNumberOfCells() override;
// 获取点个数
inline vtkIdType vtkImageData::GetNumberOfPoints()
{
   const int* extent = this->Extent;
   vtkIdType dims[3];
   dims[0] = extent[1] - extent[0] + 1;
   dims[1] = extent[3] - extent[2] + 1;
   dims[2] = extent[5] - extent[4] + 1;  
   return dims[0] * dims[1] * dims[2];
}
// 根据点ID获取点坐标(x,y,z),非线性安全;
double* GetPoint(vtkIdType ptId) VTK_SIZEHINT(3) override;
// 根据点ID获取点坐标(x,y,z),非线性安全(如果只是读取,可以是线性安全的);
void GetPoint(vtkIdType id, double x[3]) override;
// 根据单元ID获取单元信息;
vtkCell* GetCell(vtkIdType cellId) override;
vtkCell* GetCell(int i, int j, int k) override;
void GetCell(vtkIdType cellId, vtkGenericCell* cell) override;
// 获取单元的边界信息;
void GetCellBounds(vtkIdType cellId, double bounds[6]) override;
int GetCellType(vtkIdType cellId) override;
void GetCellPoints(vtkIdType cellId, vtkIdList* ptIds) override
{
   vtkStructuredData::GetCellPoints(cellId, ptIds, this->DataDescription, this->GetDimensions());
}
void GetPointCells(vtkIdType ptId, vtkIdList* cellIds) override
{
	vtkStructuredData::GetPointCells(ptId, cellIds, this->GetDimensions());
}
// 获取指定单元周围单元
void GetCellNeighbors(vtkIdType cellId, vtkIdList* ptIds, vtkIdList* cellIds) override;  
void GetCellNeighbors(vtkIdType cellId, vtkIdList* ptIds, vtkIdList* cellIds, int* seedLoc);
查找Find
// 查找与给定坐标(x,y,z)最为接近的点;
virtual vtkIdType FindPoint(double x, double y, double z)
{
	return this->vtkDataSet::FindPoint(x, y, z);
}
vtkIdType FindPoint(double x[3]) override;
// 根据给定坐标(x,y,z)和公差平方定位几何图元信息;
vtkIdType FindCell(double x[3], vtkCell* cell, vtkIdType cellId, double tol2, int& subId,
	double pcoords[3], double* weights) override;
vtkIdType FindCell(double x[3], vtkCell* cell, vtkGenericCell* gencell, vtkIdType cellId,
     double tol2, int& subId, double pcoords[3], double* weights) override;
vtkCell* FindAndGetCell(double x[3], vtkCell* cell, vtkIdType cellId, double tol2, int& subId,
     double pcoords[3], double* weights) override;

维度

  vtkImageData使用Dimensions记录各个维度上的数据点个数;
  每个维度中的值可以具有最小值“1”,这样计算数据点总数可以通过简单地通过dims[0]*dims[1]*dims[2]来实现。

int Dimensions[3];
void GetCellDims(int cellDims[3]);  
virtual void SetDimensions(int i, int j, int k);  
virtual void SetDimensions(const int dims[3]);  
virtual int* GetDimensions() VTK_SIZEHINT(3);  
virtual void GetDimensions(int dims[3]);
// 获取维度个数
virtual int GetDataDimension();

数据类型

  为vtkImageData设置数据类型(VTK_FLOAT, VTK_INT,VTK_SHORT),numComponents为每个数据点的元组内个数;

virtual void AllocateScalars(int dataType, int numComponents);  
virtual void AllocateScalars(vtkInformation* pipeline_info);

像素间隔

double Spacing[3];
vtkGetVector3Macro(Spacing, double);
virtual void SetSpacing(double i, double j, double k);
virtual void SetSpacing(const double ijk[3]);

数据的起始坐标

double Origin[3];
vtkGetVector3Macro(Origin, double);
virtual void SetOrigin(double i, double j, double k);
virtual void SetOrigin(const double ijk[3]);

数据的范围

int Extent[6];
virtual void SetExtent(int extent[6]);
virtual void SetExtent(int x1, int x2, int y1, int y2, int z1, int z2);
vtkGetVector6Macro(Extent, int);
virtual void SetAxisUpdateExtent(int axis, int min, int max, const int* updateExtent, int* axisUpdateExtent);
virtual void GetAxisUpdateExtent(int axis, int& min, int& max, const int* updateExtent);

标量数据

static void SetScalarType(int, vtkInformation* meta_data);
static int GetScalarType(vtkInformation* meta_data);
static bool HasScalarType(vtkInformation* meta_data);
int GetScalarType();
const char* GetScalarTypeAsString() { return vtkImageScalarTypeNameMacro(this->GetScalarType()); }  
static void SetNumberOfScalarComponents(int n, vtkInformation* meta_data);
static int GetNumberOfScalarComponents(vtkInformation* meta_data);
static bool HasNumberOfScalarComponents(vtkInformation* meta_data);
int GetNumberOfScalarComponents();
virtual double GetScalarTypeMin(vtkInformation* meta_data);
virtual double GetScalarTypeMin();
virtual double GetScalarTypeMax(vtkInformation* meta_data);
virtual double GetScalarTypeMax();  
virtual int GetScalarSize(vtkInformation* meta_data);
virtual int GetScalarSize();

增量

vtkIdType Increments[3];
virtual vtkIdType* GetIncrements() VTK_SIZEHINT(3);
virtual void GetIncrements(vtkIdType& incX, vtkIdType& incY, vtkIdType& incZ);
virtual void GetIncrements(vtkIdType inc[3]);
virtual vtkIdType* GetIncrements(vtkDataArray* scalars) VTK_SIZEHINT(3);
virtual void GetIncrements(vtkDataArray* scalars, vtkIdType& incX, vtkIdType& incY, vtkIdType& incZ);
virtual void GetIncrements(vtkDataArray* scalars, vtkIdType inc[3]);

支持输入/输出类型为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格式图像

  注意:读写RAW裸数据格式,要指定图像各个维度的大小、字节顺序(大端法或小端法)、存储像素值的类型等信息;
  一般需要指定的数据信息有:图像的维度、图像各维度的大小、图像像素的大小、图像像素的间隔、图像像素值的数据类型等

数组转换vtkImageData

int extent[6] = { 0,511,0,511,0,272 };
double spacing[3] = { 0.3, 0.3, 0.75 };
double origin[3] = { 0 };

vtkNew<vtkShortArray> dataArray;
// 设置short*的缓存指针和数组大小,设定每个数据点元组个数为1;
dataArray->SetArray(pBuf, size_all, 1);
vtkNew<vtkImageData> pImageData;
// 给vtkImageData指定VTK_SHORT类型,元组个数为1;
pImageData->AllocateScalars(VTK_SHORT, 1);
pImageData->SetDimensions(512, 512, 273);
pImageData->GetPointData()->SetScalars(dataArray);
pImageData->SetSpacing(spacing);
pImageData->SetOrigin(origin);

与vtkImageData相关的类

  VTK中与vtkImageData相关的类实在太多了,基本上以vtkImage开头的类都是跟图像处理相关的类,这里不一一列举,以后有机会再增加;

示例

  将之前的体渲染的例子进行了修改;
    1.使用一个序列的DICOM图像,获取每张图像内的像素矩阵,生成一个vtkShortArray数据;
    2.定义一个vtkImageData对象,设置数据类型为SHORT类型,设定三维每个维度上的数值和像素间距等信息;
    3.体渲染;

#pragma once
#include "vtk_include.h"
#include "vtkNIFTIImageReader.h"
#include "vtkInformation.h"
#include "dcmtk\config\osconfig.h"
#include "dcmtk\dcmdata\dctk.h"
#include <dcmtk/dcmjpeg/djdecode.h>  /* for dcmjpeg decoders */
#include <dcmtk/dcmjpeg/djencode.h>
#include <dcmtk/dcmjpls/djdecode.h>		//for JPEG-LS decode
#include <dcmtk/dcmjpls/djencode.h>		//for JPEG-LS encode
class Test_volume
{
public:
	static void Test()
	{
		DJDecoderRegistration::registerCodecs();
		DJLSEncoderRegistration::registerCodecs();		//JPEG-LS encoder registerCodecs
		DJLSDecoderRegistration::registerCodecs();		//JPEG-LS decoder registerCodecs

		int count = 273;
		int single_img = 512 * 512;
		int size_all = count * single_img;
		short* pBuf = new short[size_all] {0};

		for (int i = 1; i < 274; i++)
		{
			std::string fileName = "G:\\Data\\" + std::to_string(i) + ".DCM";

			DcmFileFormat *myFileFormat = new DcmFileFormat;
			OFCondition cond = myFileFormat->loadFile(fileName.c_str());

			DcmElement* pElement = nullptr;
			myFileFormat->getDataset()->chooseRepresentation(EXS_DeflatedLittleEndianExplicit, NULL);
			myFileFormat->getDataset()->findAndGetElement(DCM_PixelData, pElement);
			if (pElement != NULL) {
				int size = pElement->getLength() / 2;
				OFCondition cond = pElement->loadAllDataIntoMemory();
				if (cond.good()) {
					Uint16 * ptr;
					cond = pElement->getUint16Array(ptr);
					if (cond.good()) {
						memcpy(pBuf + (i - 1)*single_img, ptr, size * sizeof(short));
					}
				}
			}
			delete myFileFormat;
		}

		int extent[6] = { 0,511,0,511,0,272 };
		double spacing[3] = { 0.3, 0.3, 0.75 };
		double origin[3] = { 0 };

		vtkNew<vtkShortArray> dataArray;
		dataArray->SetArray(pBuf, size_all, 1);
		vtkNew<vtkImageData> pImageData;

		pImageData->AllocateScalars(VTK_SHORT, 1);
		pImageData->SetDimensions(512, 512, 273);
		pImageData->GetPointData()->SetScalars(dataArray);
		pImageData->SetSpacing(spacing);
		pImageData->SetOrigin(origin);
		
		vtkNew<vtkFixedPointVolumeRayCastMapper> volumeMapper;
		volumeMapper->SetInputData(pImageData);		
		vtkNew<vtkVolumeProperty> volumeProperty;
		volumeProperty->SetInterpolationTypeToLinear();
		volumeProperty->ShadeOn();  //打开或者关闭阴影测试
		volumeProperty->SetAmbient(0.4);
		volumeProperty->SetDiffuse(1.6);  //漫反射
		volumeProperty->SetSpecular(0.2); //镜面反射
		
		//设置不透明度
		vtkNew<vtkPiecewiseFunction> compositeOpacity;
		compositeOpacity->AddPoint(70, 0.00);
		compositeOpacity->AddPoint(90, 0.40);
		compositeOpacity->AddPoint(180, 0.60);
		volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

		vtkNew<vtkPiecewiseFunction> volumeGradientOpacity;
		volumeGradientOpacity->AddPoint(10, 0.0);
		volumeGradientOpacity->AddPoint(90, 0.5);
		volumeGradientOpacity->AddPoint(100, 1.0);

		vtkNew<vtkColorTransferFunction> color;
		color->AddRGBPoint(0.000, 0.00, 0.00, 0.00);
		color->AddRGBPoint(64.00, 1.00, 0.52, 0.30);
		color->AddRGBPoint(190.0, 1.00, 1.00, 1.00);
		color->AddRGBPoint(220.0, 0.20, 0.20, 0.20);
		volumeProperty->SetColor(color);

		vtkNew<vtkVolume> volume;
		volume->SetMapper(volumeMapper);
		volume->SetProperty(volumeProperty);

		vtkNew<vtkRenderer> ren;
		ren->SetBackground(0.3, 0.4, 0.3);
		ren->AddVolume(volume);

		vtkNew<vtkRenderWindow> rw;
		rw->AddRenderer(ren);
		rw->SetSize(640, 480);
		rw->Render();
		rw->SetWindowName("VolumeRendering PipeLine");

		vtkNew<vtkRenderWindowInteractor> rwi;
		rwi->SetRenderWindow(rw);
		ren->ResetCamera();
		rw->Render();
		rwi->Start();
	}
};

注意:代码中没注意内存释放的情况;
在这里插入图片描述
  关闭颜色和不透明度后的图像;
在这里插入图片描述
调整不透明度和颜色对应表,显示效果

//设置不透明度
vtkNew<vtkPiecewiseFunction> compositeOpacity;
compositeOpacity->AddPoint(600, 0.00);
compositeOpacity->AddPoint(800, 0.40);
compositeOpacity->AddPoint(1000, 0.60);
compositeOpacity->AddPoint(1500, 1.0);
volumeProperty->SetScalarOpacity(compositeOpacity); //设置不透明度传输函数

vtkNew<vtkPiecewiseFunction> volumeGradientOpacity;
volumeGradientOpacity->AddPoint(10, 0.0);
volumeGradientOpacity->AddPoint(200, 0.5);
volumeGradientOpacity->AddPoint(300, 1.0);

vtkNew<vtkColorTransferFunction> color;
color->AddRGBPoint(0.000, 0.00, 0.00, 0.00);
color->AddRGBPoint(600.0, 1.00, 0.52, 0.30);
color->AddRGBPoint(1000., 1.00, 1.00, 1.00);
color->AddRGBPoint(1500, 0.20, 0.20, 0.20);
volumeProperty->SetColor(color);

在这里插入图片描述

参考资料

1.vtkImageData Class Reference

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑山老妖的笔记本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值