[C++] ITK读写RAW数据与像素遍历的方法

ITK版本:5.2

一、包含文件与自定义类型

1.需要包含的头文件如下:

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImportImageFilter.h"
#include "itkRawImageIO.h"

2.自定义类型名如下:

	const unsigned int ImgDim = 3;				//图像维度
	typedef itk::Image<unsigned short, ImgDim> ImageType;
	typedef itk::ImportImageFilter<unsigned short, ImgDim> ImportFilterType;
	typedef itk::RawImageIO<unsigned short, ImgDim> ImageIOType;
	typedef itk::ImageFileReader<ImageType> ImageRType;
	typedef itk::ImageFileWriter<ImageType> ImageWType;

二、参数的设置

给定图像的初始化参数,用于后续处理。

1.图像的尺寸与初值
	ImageType::SizeType size;
	size[0] = 256;
	size[1] = 256;
	size[2] = 128;
	size_t ElemCounts = size[0] * size[1] * size[2];
	ImageType::IndexType start;
	start.Fill(0);
	ImageType::RegionType region;
	region.SetSize(size);
	region.SetIndex(start);
2.IO参数设定
	ImageIOType::Pointer rawImgIO = ImageIOType::New();
	rawImgIO->SetFileTypeToBinary();						//设置二进制形式打开
	rawImgIO->SetFileDimensionality(ImgDim);				//设置图像维度
	rawImgIO->SetByteOrderToLittleEndian();					//设置小端序
	rawImgIO->SetDimensions(0, size[0]);
	rawImgIO->SetDimensions(1, size[1]);
	rawImgIO->SetDimensions(2, size[2]);
	rawImgIO->SetHeaderSize(0);								//文件头大小
	rawImgIO->SetNumberOfComponents(1);						//像素通道数(灰度为1,RGB为3)
	rawImgIO->SetPixelType(itk::ImageIOBase::SCALAR);		//设置标量类型,即灰度图
	rawImgIO->SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);//设置像素数值类型为ushort

三、本地数据的读取

1.创建缓存空间
	unsigned short* OriData = nullptr;
	OriData = new unsigned short[ElemCounts];
2.使用ImageFileReader类读取并拷贝数据

使用ITK读取数据需要创建一个ImageFileReader对象,加载上述的IO设定,通过GetBufferPointer()索引缓存数据,将数据进行拷贝到OriData中。

	ImageRType::Pointer reader = ImageRType::New();
	reader->SetFileName("./TestImgA 256x256x128 ushort.raw");
	reader->SetImageIO(rawImgIO);
	reader->Update();
	memcpy(OriData, reader->GetOutput()->GetBufferPointer(), sizeof(unsigned short) * ElemCounts);

对比一下C++ 的fread函数的读取方法。

	FILE* fpread = nullptr;
	fopen_s(&fpread, "./TestImgA 256x256x128 ushort.raw", "rb");
	if (fpread != nullptr)
	{
		fread(OriData, sizeof(unsigned short), ElemCounts, fpread);
		fclose(fpread);
	}

四、像素的遍历

针对读取图像的像素遍历赋值,有两种方式

1.方式一:直接对缓存数据进行遍历
	for (int p = 0; p < size[2]; p++)
	{
		for (int i = 0; i < size[0] * size[1]; i++)
		{
			OriData[p * size[0] * size[1] + i] *= (i / size[0] + p);
		}
	}

遍历处理之后,需要将缓存数据导入到itk::ImportImageFilter类进行后续处理。

	ImportFilterType::Pointer imageFilter01 = ImportFilterType::New();
	imageFilter01->SetRegion(region);
	imageFilter01->SetImportPointer(OriData, ElemCounts, false);
	imageFilter01->Update();
2.方式二:通过SetPixel的方式进行遍历
	for (int p = 0; p < size[2]; p++)
	{
		itk::Index<3> ind;
		ind[2] = p;
		for (int i = 0; i < size[0] * size[1]; i++)
		{
			ind[0] = i % size[0];
			ind[1] = i / size[0];
			unsigned short pixValue = imageFilter01->GetOutput()->GetPixel(ind);
			imageFilter01->GetOutput()->SetPixel(ind, pixValue / (p + 1));
		}
	}

五、图像的保存

与读取本地数据类似,使用ITK写入本地数据,需要创建一个ImageFileWriter对象,加载IO设置,然后保存到本地。

	ImageWType::Pointer writer = ImageWType::New();
	writer->SetFileName("./TestImgB.raw");
	writer->SetInput(imageFilter01->GetOutput());
	writer->SetImageIO(rawImgIO);
	writer->SetUseCompression(true);
	try
	{
		writer->Update();
	}
	catch (itk::ExceptionObject& e)
	{
		std::cerr << e << std::endl;
	}

对比C++的fwrite函数的写入方法。

	FILE* fpwrite = nullptr;
	fopen_s(&fpwrite, "./TestImgC.raw", "wb");
	if (fpwrite != nullptr)
	{
		fwrite(imageFilter01->GetOutput()->GetBufferPointer(), sizeof(unsigned short), ElemCounts, fpwrite);
		fclose(fpwrite);
	}
原始图像TestImgA
读取图像与保存图像对比

参考资料:https://blog.csdn.net/yunzhaoqiang/article/details/7905113

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值