[vtkusers] Why multi-frame dicom can not be rendered correctly by VTK?

heyuanlie heyuanlie at gmail.com
Sun Sep 23 22:56:05 EDT 2012


Hi everyone,

I use VTK to render the CT series (series dicom files) and SPECT multi-frame
(multi-frame in one dicom file) which came from the same study. The CT
series and SPECT multi-frame are belong to the same patient and the number
of slices are same.

The problem is the CT series can be rendered very well, but the SPECT
multi-frame can't be rendered correctly . The result of the SPECT
mutli-frame rendering just like all slices being squeezed together (compare
the CT and the SPECT rendering results blow).
<http://vtk.1045678.n5.nabble.com/file/n5716270/render.png> 

I've try the following methods:
vtkImageResample::SetAxisOutputSpacing
vtkImageResample::SetOutputSpacing
vtkImageResize::SetOutputSpacing
vtkImageResize::SetMagnificationFactors

But can't make any better.

Could you help me, please!

The following codes are used to render CT series:
int QtItkVtkViewMDI::volumeRenderCTSeriesNormal()
{
	if( directoryCTSeries.isEmpty()) // directoryCTSeries is a string
containing the path of the CT series.
		return false;

	int clip = 0;
	double frameRate = 2.0;
	const unsigned int Dimension = 3;
	double opacityWindow = 1500; // window width
	double opacityLevel = 450; // window level
	bool independentComponents=true;

	typedef signed short    PixelType;

	typedef itk::Image< PixelType, Dimension >         ImageType; // define
image type

	typedef itk::ImageSeriesReader< ImageType >        ReaderType; // define
reader type
	ReaderType::Pointer reader = ReaderType::New();
	
	typedef itk::GDCMImageIO       ImageIOType; // define itk::GDCMImageIO
object access the GDCM library for reading DICOM files
	ImageIOType::Pointer dicomIO = ImageIOType::New();

	reader->SetImageIO( dicomIO ); // connect the itk::GDCMImageIO object to
the reader
	
	typedef itk::GDCMSeriesFileNames NamesGeneratorType;
	NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();

	nameGenerator->SetDirectory( directoryCTSeries.toStdString() ); // set the
directory which contains the DICOM files
	
	try
	{
		typedef std::vector< std::string >    SeriesIdContainer;

		const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();

		std::string seriesIdentifier;

		seriesIdentifier = seriesUID.begin()->c_str();

		typedef std::vector< std::string >   FileNamesContainer;
		FileNamesContainer fileNames;

		fileNames = nameGenerator->GetFileNames( seriesIdentifier );

		reader->SetFileNames( fileNames );

		try
		{
			reader->Update();
		}
		catch (itk::ExceptionObject &ex)
		{
			//std::cout << ex << std::endl;
			return EXIT_FAILURE;
		}

    }
	catch (itk::ExceptionObject &ex)
    {
		//std::cout << ex << std::endl;
		return EXIT_FAILURE;
    }



	typedef itk::ImageToVTKImageFilter<ImageType>    ConnectorType;

	//ReaderType::Pointer reader = ReaderType::New();
	ConnectorType::Pointer connector = ConnectorType::New();
	connector->SetInput( reader->GetOutput() );

	vtkImageImport * readerImageImport = connector->GetImporter();

	vtkImageResample * resample = vtkImageResample::New();
	resample->SetInputConnection( readerImageImport->GetOutputPort() );

	// Create the renderer, render window and interactor
	vtkRenderer *renderer = vtkRenderer::New();
	vtkRenderWindow *renWin = vtkRenderWindow::New();

	interactor = vtkWin32RenderWindowInteractor::New();
	interactorStyle = vtkInteractorStyleTrackballCamera::New();
	interactor->SetInteractorStyle(interactorStyle);
	interactor->SetRenderWindow(renWin);
	interactor->SetDesiredUpdateRate(frameRate / (1+clip) );

	interactor->GetInteractorStyle()->SetDefaultRenderer(renderer);

	// Create our volume and mapper
	vtkVolume *volume = vtkVolume::New();
	vtkFixedPointVolumeRayCastMapper *mapper =
vtkFixedPointVolumeRayCastMapper::New();
	mapper->SetInputConnection( resample->GetOutputPort() );

	// Create our transfer function
	vtkColorTransferFunction *colorFun = vtkColorTransferFunction::New();
	vtkPiecewiseFunction *opacityFun = vtkPiecewiseFunction::New();

	// Create the property and attach the transfer functions
	vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();
	volumeProperty->SetIndependentComponents(independentComponents);
	volumeProperty->SetColor( colorFun );
	volumeProperty->SetScalarOpacity( opacityFun );
	volumeProperty->SetInterpolationTypeToLinear();

	// connect up the volume to the property and the mapper
	volume->SetProperty( volumeProperty );
	volume->SetMapper( mapper );

	// CT_Skin
    // Use compositing and functions set to highlight skin in CT data
    // Not for use on RGB data
	colorFun->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 );
	colorFun->AddRGBPoint( -1000, .62, .36, .18, 0.5, 0.0 );
	colorFun->AddRGBPoint( -500, .88, .60, .29, 0.33, 0.45 );
	colorFun->AddRGBPoint( 3071, .83, .66, 1, 0.5, 0.0 );

	opacityFun->AddPoint(-3024, 0, 0.5, 0.0 );
	opacityFun->AddPoint(-1000, 0, 0.5, 0.0 );
	opacityFun->AddPoint(-500, 1.0, 0.33, 0.45 );
	opacityFun->AddPoint(3071, 1.0, 0.5, 0.0);

	mapper->SetBlendModeToComposite();
	volumeProperty->ShadeOn();
	volumeProperty->SetAmbient(0.1);
	volumeProperty->SetDiffuse(0.9);
	volumeProperty->SetSpecular(0.2);
	volumeProperty->SetSpecularPower(10.0);
	volumeProperty->SetScalarOpacityUnitDistance(0.8919);

	// Add the volume to the scene
	renderer->AddVolume( volume );

	renderer->ResetCamera();

	// Set the default window size
	renWin->SetSize(512,512);

	renWin->AddRenderer(renderer);

	renWin->SetInteractor(interactor);

	QVTKWidget widget;
	widget.SetRenderWindow(renWin);
	widget.resize(512,512);

	QMdiSubWindow *subWindow = mdiArea->addSubWindow(&widget);
	subWindow->resize(512,512);
	subWindow->show();

	// interact with data
	renWin->Render();
	interactor->Start();

	return true;
}

The following codes are used to render SPECT frames:
int QtItkVtkViewMDI::volumeRenderSPECTFramesNormal()
{
	if( fileNameSPECTFrames.isEmpty()) // fileNameSPECTFrames is a string
containing the file name of the SPECT multi-frame dicom.
		return false;

	int clip = 3;
	double frameRate = 1.0;
	const unsigned int Dimension = 3;
	double opacityWindow = 353; // window width
	double opacityLevel = 176; // window level
	bool independentComponents=true;

	typedef signed short    PixelType;

	typedef itk::Image< PixelType, Dimension >         ImageType; // define
image type

	typedef itk::ImageFileReader<ImageType>          ReaderType; // define
reader type
	ReaderType::Pointer reader = ReaderType::New();
	reader->SetFileName(fileNameSPECTFrames.toStdString()); // whether
multi-frames or not, ITK can read it.

	typedef itk::ImageToVTKImageFilter<ImageType>    ConnectorType;

	//ReaderType::Pointer reader = ReaderType::New();
	ConnectorType::Pointer connector = ConnectorType::New();
	connector->SetInput( reader->GetOutput() );

	vtkImageImport * readerImageImport = connector->GetImporter();

	vtkImageResample * resample = vtkImageResample::New();
	resample->SetInputConnection( readerImageImport->GetOutputPort() );
	
	// Create the renderer, render window and interactor
	vtkRenderer *renderer = vtkRenderer::New();
	vtkRenderWindow *renWin = vtkRenderWindow::New();

	interactor = vtkWin32RenderWindowInteractor::New();
	interactorStyle = vtkInteractorStyleTrackballCamera::New();
	interactor->SetInteractorStyle(interactorStyle);
	interactor->SetRenderWindow(renWin);
	interactor->SetDesiredUpdateRate(frameRate / (1+clip) );

	interactor->GetInteractorStyle()->SetDefaultRenderer(renderer);

	// Create our volume and mapper
	vtkVolume *volume = vtkVolume::New();
	vtkFixedPointVolumeRayCastMapper *mapper =
vtkFixedPointVolumeRayCastMapper::New();
	mapper->SetInputConnection( resample->GetOutputPort() );

	// Create our transfer function
	vtkColorTransferFunction *colorFun = vtkColorTransferFunction::New();
	vtkPiecewiseFunction *opacityFun = vtkPiecewiseFunction::New();

	// Create the property and attach the transfer functions
	vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New();
	volumeProperty->SetIndependentComponents(independentComponents);
	volumeProperty->SetColor( colorFun );
	volumeProperty->SetScalarOpacity( opacityFun );
	volumeProperty->SetInterpolationTypeToLinear();

	// connect up the volume to the property and the mapper
	volume->SetProperty( volumeProperty );
	volume->SetMapper( mapper );

    // MIP ( Maximum Intensity Projection )
    // Create an opacity ramp from the window and level values.
    // Color is white. Blending is MIP.
	colorFun->AddRGBSegment(0.0, 1.0, 1.0, 1.0, 255.0, 1.0, 1.0, 1.0 );
	opacityFun->AddSegment( opacityLevel - 0.5*opacityWindow, 0.0,
							opacityLevel + 0.5*opacityWindow, 1.0 );
	mapper->SetBlendModeToMaximumIntensity();
   
	// Add the volume to the scene
	renderer->AddVolume( volume );

	renderer->ResetCamera();

	// Set the default window size
	renWin->SetSize(512,512);

	renWin->AddRenderer(renderer);

	renWin->SetInteractor(interactor);

	QVTKWidget widget;
	widget.SetRenderWindow(renWin);
	widget.resize(512,512);

	QMdiSubWindow *subWindow = mdiArea->addSubWindow(&widget);
	subWindow->resize(512,512);
	subWindow->show();

	// interact with data
	renWin->Render();
	interactor->Start();

	return true;
}



--
View this message in context: http://vtk.1045678.n5.nabble.com/Why-multi-frame-dicom-can-not-be-rendered-correctly-by-VTK-tp5716270.html
Sent from the VTK - Users mailing list archive at Nabble.com.



More information about the vtkusers mailing list