背景:
在从零开始的二三维软件开发中, 需要加载CT的dicoms影像文件, 并将其序列化之后的数据,体素化
可惜..vtk的c#库,将其体素化的时候,竟然失败...
使用vtkDicomReader ,设置 Dicom文件夹读取,竟然不停的失败...从网上找了一些版本.也没啥可用的资料...
解决办法:
直接使用 fo-Dicoms库,读取每一张 Dicom影像后, 按照序列排序后, 然后一张张数据读取,接着将数据赋予VtkImageData后,创建vtkVolumActor.
关键代码分享:
// 根据DICOM数据类型分配适当的VTK数据类型
var pixelData = DicomPixelData.Create(firstDataset);
int bitsAllocated = pixelData.BitsAllocated;
bool isSigned = pixelData.PixelRepresentation == PixelRepresentation.Signed;
if (bitsAllocated == 16)
{
imageData.AllocateScalars(isSigned ? 4 : 8, 1);//8
}
else if (bitsAllocated == 8)
{
imageData.AllocateScalars(4, 1);//4
}
else
{
throw new NotSupportedException($"不支持的位深度: {bitsAllocated}");
}
// 获取数据范围以便正确映射
int[] extent = imageData.GetExtent();
// 遍历所有切片
for (int z = 0; z < depth; z++)
{
var dataset = dicomSeries[z].Dataset;
var currentPixelData = DicomPixelData.Create(dataset);
var frameData = currentPixelData.GetFrame(0);
byte[] byteData = frameData.Data;
// 根据数据类型处理像素数据
if (bitsAllocated == 16)
{
// 正确将byte[]转换为short[]
short[] pixels = new short[byteData.Length / 2];
Buffer.BlockCopy(byteData, 0, pixels, 0, byteData.Length);
// 如果需要考虑字节顺序
if (BitConverter.IsLittleEndian != dataset.TryGetSingleValue(DicomTag.HighBit, out ushort highBit) || highBit == 0)
{
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = IPAddress.NetworkToHostOrder(pixels[i]);
}
}
// 遍历当前切片的所有像素
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int index = y * width + x;
short pixelValue = pixels[index];
imageData.SetScalarComponentFromDouble(x, height - 1 - y, z, 0, pixelValue);
}
}
}
else if (bitsAllocated == 8)
{
// 直接使用byte数据
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int index = y * width + x;
byte pixelValue = byteData[index];
imageData.SetScalarComponentFromDouble(x, height - 1 - y, z, 0, pixelValue);
}
}
}
}