Vtk实现DCM转PNG

1 篇文章 0 订阅

namespace ImageDataToQimage
{
	// 限制输出像素值范围
	template<class F>
	inline F TP_LimitNum(F x, F xmin, F xmax)
	{
		x = (x > xmin ? x : xmin);
		x = (x < xmax ? x : xmax);
		return x;
	}

	//======================================
	// inPtr 输入数据指针,unsigned char类型
	// outPtr 输出数据指针,unsigned char类型,component size为4
	// ncols 图像列数(宽)
	// nrows 图像行数(高)
	// numComp 输入数据component size值,可以理解为通道数(R/G/B/A)
	//======================================
	inline void ConvertVtkImageToRGBA(const unsigned char *inPtr, unsigned char *outPtr, int ncols, int nrows, int numComp)
	{
		const int vmin = 0;
		const int vmax = 255;
		unsigned char alpha = 255;
		int inIncX = numComp;
		// loop through the data and copy it for the texture
		if (numComp == 1)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int val = inPtr[0];
					val = TP_LimitNum(val, vmin, vmax);
					unsigned char cval = static_cast<unsigned char>(val + 0.5);
					outPtr[0] = cval;
					outPtr[1] = cval;
					outPtr[2] = cval;
					outPtr[3] = alpha;
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
		else if (numComp == 2)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int val = inPtr[0];
					val = TP_LimitNum(val, vmin, vmax);
					unsigned char cval = static_cast<unsigned char>(val + 0.5);
					val = inPtr[1];
					val = TP_LimitNum(val, vmin, vmax);
					unsigned char aval = static_cast<unsigned char>(val + 0.5);
					outPtr[0] = cval;
					outPtr[1] = cval;
					outPtr[2] = cval;
					outPtr[3] = aval;
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
		else if (numComp == 3)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int r = inPtr[0];
					int g = inPtr[1];
					int b = inPtr[2];
					r = TP_LimitNum(r, vmin, vmax);
					g = TP_LimitNum(g, vmin, vmax);
					b = TP_LimitNum(b, vmin, vmax);
					outPtr[0] = static_cast<unsigned char>(r + 0.5);
					outPtr[1] = static_cast<unsigned char>(g + 0.5);
					outPtr[2] = static_cast<unsigned char>(b + 0.5);
					outPtr[3] = alpha;
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
		else // if (numComp == 4)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int r = inPtr[0];
					int g = inPtr[1];
					int b = inPtr[2];
					int a = inPtr[3];
					r = TP_LimitNum(r, vmin, vmax);
					g = TP_LimitNum(g, vmin, vmax);
					b = TP_LimitNum(b, vmin, vmax);
					a = TP_LimitNum(a, vmin, vmax);
					outPtr[0] = static_cast<unsigned char>(r + 0.5);
					outPtr[1] = static_cast<unsigned char>(g + 0.5);
					outPtr[2] = static_cast<unsigned char>(b + 0.5);
					outPtr[3] = static_cast<unsigned char>(a + 0.5);
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
	}
}

调用方式

//这里我自己的数据是从vtkImageViewer2中获取到的dcm文件数据,
//即image->GetInput 返回值类型vtkImageData *

vtkImageData *imageData = ...; // 源图像数据
int ncols = imageData->GetDimensions()[0]; // 图像列数(宽)
int nrows = imageData->GetDimensions()[1]; // 图像行数(高)

// 获取原图像数据的灰度值范围
// 如:CT值的单位是Hounsfield,简称为Hu,范围是-1024-3071。用于衡量人体组织对X射线的吸收率,设定水的吸收率为0Hu。
double range[2];
imageData->GetScalarRange(range); 

// 将原图像灰度值调节到0~255范围内,输出为unsigned char(0~255)类型数据(即调节窗宽窗位)
vtkImageShiftScale* shifter = vtkImageShiftScale::New();
shifter->SetShift(-1.0*range[0]); //减去最小值
shifter->SetScale(255.0 / (range[1] - range[0])); //调节比例,灰度换算公式:255*X/(range[1]-range[0])
shifter->SetOutputScalarTypeToUnsignedChar();
shifter->SetInputData(imageData);
shifter->Update();

// 获取原图像component size值,即通道数
int numComp = shifter->GetOutput()->GetScalarSize();

// 申请内存
unsigned char *inPtr = static_cast<unsigned char*>(shifter->GetOutput()->GetScalarPointer()); // 输入,从图像中获取数据指针
unsigned char *outPtr = new unsigned char[nrows * ncols * 4]; // 输出,RGBA共4通道,所以这里乘4
ConvertVtkImageToRGBA(inPtr, outPtr, ncols, nrows, numComp);

// 创建QImage,理论上可以用outPtr创建任意其它类型图像
QImage image = QImage(outPtr, ncols, nrows, QImage::Format_RGB32);
//实现QImage的缩放 公认比较好的方法是,先缩至缩略图4倍大小, 再进一步平滑缩放
QImage img = (*iamge).scaled(640, 480).scaled(200, 200, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

参考:原作者出处

软件介绍: DcmTransform是一款专用的医学格式换器,于对符合DICOM 3.0标准的医学图像文件。软件首先对DICOM文件中的数据进行解析,并将其以图像的样式显示。图像显示后,用户可以自定义地调节医学图像的窗位窗宽。由于医学图像数据的像素变化范围通常为0-4095或0-1023,不同于传统图像文件的0-255。而计算机所能显示的黑白像素范围是0-255,所以需要对医学图像进行像素值的映射处理,即调节医学图像的窗位窗宽。调节操作的作用在于改变显示图像的明暗度对比度。当用户调节好医学图像的窗位窗宽后,即可以对医学图像文件进行格式化。化的文件格式可设为BMP格式和JPG格式。用户亦可以根据自己的需要设置化图像的属性信息,如图像的质量,大小。对于CT,MRI断层图像来说,通常拍摄得到的是一系列DICOM文件,该系列文件通常在同一个文件夹目录下。对于某一系列文件,由于拍摄中设备参数设置不变,其像素的变化范围,图像的明暗度饱和度基本相同,所以在图像化操作中,用户可以调节好窗位窗宽后,一次性的将系列文件全部化。对于DSA血管减影造影图像,也是需要拍摄一系列的图像,该系列图像通常保存在同一DICOM文件中。它借助计算机对血管造影图像进行数字图像处理,以消除背景的干扰,突出医生感兴趣的血管部分的信息。医学关心的并不是原始拍摄的图像信息,而是减影成像后的图像。所以本软件即可以将原始图像数据化成普通图像文件,也可以化减影成像后的图像。DICOM文件是按照DICOM标准存储的医学文件,它不仅可以用来封装各种医学图像,也可以封装其它医学信息,如病人姓名,性别,拍摄单位、设备参数等。这类资料保存在DICOM文件的文件头中,DICOM文件头包含了标识数据集合的相关信息。DICOM文件一般由1个DICOM文件头和1个DICOM数据集合组成。在对DICOM文件处理过程序中,亦需要对其文件头进行解析,得到图像的相关信息。本软件可以将解析后的文件头保存为TXT文本文件,以便于查看。本软件还为用户提供了普通图像文件浏览的功能,以便于用户化完DICOM文件后,查看化效果。图像浏览时,先列出所有化后图像的缩略图,用户点击任意一幅缩略图即可打开该图像。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值