VTKを使用してDICOM(ctスキャン)イメージをポイントクラウドに変換する方法はありますか?VTKのDICOMとポイントクラウド
VTKでは、DICOMとDICOMシリーズとボリュームレンダリングを読み取ることができますが、一連のDICOM画像からポイントクラウドを生成することは可能ですか?
VTKでは不可能な場合は、この目的のために使用できる他のライブラリがありますか?
VTKを使用してDICOM(ctスキャン)イメージをポイントクラウドに変換する方法はありますか?VTKのDICOMとポイントクラウド
VTKでは、DICOMとDICOMシリーズとボリュームレンダリングを読み取ることができますが、一連のDICOM画像からポイントクラウドを生成することは可能ですか?
VTKでは不可能な場合は、この目的のために使用できる他のライブラリがありますか?
私は結局、方法を見つけたかもしれないと思います。まだ試していないが、理論的にはうまくいくはずだ。
最初に、DICOMイメージを.vtkに変換すると、VTKを使用して.vtk形式に変換する必要があります。その後、PCL(ポイントクラウドライブラリ)を使用して.pcd(ポイントクラウド形式)に変換できます。
ここに私が使っているソースがありますが、これは非常に単純なdicomディレクトリ構造でしか動作しません:(tbh私はVTKにもっと複雑なディレクトリを行う能力はないと思っています...)。しかし、それが役に立った場合:
pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);
//dicom read
vtkFileOutputWindow *outwin = vtkFileOutputWindow::New();
outwin->SetFileName("vtklog.txt");
outwin->SetInstance(outwin);
vtkSmartPointer<ErrorObserver> errorObserver = vtkSmartPointer<ErrorObserver>::New();
vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
reader->AddObserver(vtkCommand::WarningEvent, errorObserver);
vtkSmartPointer<vtkImageData> sliceData = vtkSmartPointer<vtkImageData>::New();
reader->SetDirectoryName(dicomDirectory.c_str());
reader->Update();
if (errorObserver->GetError() || errorObserver->GetWarning())
{
std::cout << "Failed DICOM file access" << std::endl;
return false;
}
sliceData = reader->GetOutput();
outwin->Delete();
//extracting pointcloud
int numberOfDims = sliceData->GetDataDimension();
int * dims = sliceData->GetDimensions();
std::cout << "Cloud dimensions: ";
int totalPoints = 1;
for (int i = 0; i < numberOfDims; i++)
{
std::cout << dims[i] << " , ";
totalPoints = totalPoints * dims[i];
}
std::cout << std::endl;
std::cout << "Number of dicom points: " << totalPoints << std::endl;
//generate pcl point cloud
double* dataRange = sliceData->GetScalarRange();
double* spacingData = reader->GetDataSpacing();
std::cout << "Data intensity bounds... min: " << dataRange[0] << ", max: " << dataRange[1] << std::endl;
if (numberOfDims != 3)
{
std::cout << "Incorrect number of dimensions in dicom file, generation failed..." << std::endl;
return false;
}
else
{
double xScale = spacingData[0];
double yScale = spacingData[1];
double zScale = spacingData[2];
std::cout << "x spacing: " << xScale << std::endl;
std::cout << "y spacing: " << yScale << std::endl;
std::cout << "z spacing: " << zScale << std::endl;
for (int z = 0; z < dims[2]; z++)
{
if (z % 50 == 0)
{
double percentageComplete = (double)z/(double)dims[2];
std::cout << "Dicom Read Progress: " << (int)(100.0 * percentageComplete) << "%" << std::endl;
}
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
pcl::PointXYZI tempPt = pcl::PointXYZI();
tempPt.x = x * xScale;
tempPt.y = y * yScale;
tempPt.z = z * zScale;
double tempIntensity = sliceData->GetScalarComponentAsDouble(x, y, z, 0);
if (!isinf(tempIntensity))
{
tempPt.intensity = tempIntensity;
}
else
{
tempPt.intensity = 0;
}
cloud->points.push_back(tempPt);
}
}
std::cout << reader->GetTransferSyntaxUID() << std::endl;
//std::cout << reader->get
}
}