一组效果不错的三维重建DICOM的参数

August 01, 2016

先上效果:

左边是这份代码体绘制的,右边是使用软件重建的。

需要注意的是 vtk 默认读取 DICOM 的类并不支持所有 DICOM 文件,只支持未经压缩处理的。

这份代码缺点是渲染速度比较慢,改用 vtkGPUVolumeRayCastMapper 的话速度会提升,骨骼效果也更好,但是外面有层类似云雾的东西,还需要调参优化。

#include <vtkSmartPointer.h>
#include <vtkCamera.h>
#include <vtkFiniteDifferenceGradientEstimator.h>
#include <vtkImageClip.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkStructuredPoints.h>
#include <vtkStructuredPointsReader.h>
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#include <vtkColorTransferFunction.h>
#include <vtkImageCast.h>
#include <vtkDICOMImageReader.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkSmartVolumeMapper.h>
int main()
{

	// Create the renderers, render window, and interactor
	vtkSmartPointer<vtkRenderWindow> renWin =
		vtkSmartPointer<vtkRenderWindow>::New();
	vtkSmartPointer<vtkRenderWindowInteractor> iren =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	iren->SetRenderWindow(renWin);
	vtkSmartPointer<vtkRenderer> ren =
		vtkSmartPointer<vtkRenderer>::New();
	renWin->AddRenderer(ren);

	// Read data
	vtkSmartPointer<vtkDICOMImageReader> reader =
		vtkSmartPointer<vtkDICOMImageReader>::New();
	reader->SetDirectoryName("C:\\Examples\\sample_data\\3Dircadb2.2\\PATIENT_DICOM");
	reader->Update();

	vtkSmartPointer<vtkImageCast> cast = vtkSmartPointer<vtkImageCast>::New();
	cast->SetInputConnection(reader->GetOutputPort());
	cast->SetOutputScalarTypeToUnsignedShort();
	cast->Update();

	vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
	volumeProperty->SetInterpolationTypeToLinear();
	volumeProperty->ShadeOn();
	volumeProperty->SetAmbient(.5);
	volumeProperty->SetDiffuse(1.0);
	volumeProperty->SetSpecular(.5);
	volumeProperty->SetSpecularPower(25);
	volumeProperty->SetInterpolationTypeToLinear();

	vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
	compositeOpacity->AddPoint(-3024, 0, 0.5, 0.0);
	compositeOpacity->AddPoint(-220, 0, .49, .61);
	compositeOpacity->AddPoint(625, .71, .5, 0.0);
	compositeOpacity->AddPoint(3071, 0.0, 0.5, 0.0);
	volumeProperty->SetScalarOpacity(compositeOpacity);

	vtkSmartPointer<vtkColorTransferFunction> color =
		vtkSmartPointer<vtkColorTransferFunction>::New();
	color->AddRGBPoint(-3024, 0, 0, 0, 0.5, 0.0);
	color->AddRGBPoint(-200, 0.73, 0.25, 0.30, 0.49, .61);
	color->AddRGBPoint(641, .90, .82, .56, .5, 0.0);
	color->AddRGBPoint(3071, 1, 1, 1, .5, 0.0);
	volumeProperty->SetColor(color);


	vtkSmartPointer<vtkPiecewiseFunction> volumeGradientOpacity =
		vtkSmartPointer<vtkPiecewiseFunction>::New();
	volumeGradientOpacity->AddPoint(0, 2.0);
	volumeGradientOpacity->AddPoint(500, 2.0);
	volumeGradientOpacity->AddSegment(600, 0.73, 900, 0.9);
	volumeGradientOpacity->AddPoint(1300, 0.1);
	volumeProperty->SetGradientOpacity(volumeGradientOpacity);


	vtkSmartPointer<vtkFixedPointVolumeRayCastMapper> volumeMapper = vtkSmartPointer<vtkFixedPointVolumeRayCastMapper>::New();
	volumeMapper->SetInputConnection(cast->GetOutputPort());
	volumeMapper->SetSampleDistance(0.5f);


	vtkSmartPointer<vtkVolume>volume = vtkSmartPointer<vtkVolume>::New();
	volume->SetMapper(volumeMapper);
	volume->SetProperty(volumeProperty);

	ren->AddViewProp(volume);
	renWin->Render();
	iren->Start();

	return EXIT_SUCCESS;
}

Profile picture

Written by Armin Li , a venture capitalist. [Weibo] [Subscribe]