[Insight-users] ExtractImageFilter & ChangeInformationImageFilter to keep slice origin

Antoine Leimgruber antoine.leimgruber at sokal.ch
Wed Jun 13 18:32:08 EDT 2007


Hello,

I have a 3D image and I am writing it slice by slice in the z direction using ExtractImageFilter. I use an ImageFileWriter and call my files 0001.dcm, 0002.dcm,....

What is the best way of not loosing the origin of the slice when writing it to 000i.dcm ?

This is what I tried

I first used ExtractImageFilter as in the ITK examples, but I noticed that every extracted slice had the origin [0 0] and also that there was no image position patient tag in the dicom file.

To have a 3D origin, I defined my "slice" as a Dimension=3 image and then I set the size[2] of the region to extract to 1. With that, every extracted slice had the origin [0 0 0].

I used then a ChangeInformationFilter to change the origin of the extracted slice. With the spacing and the slice index I thought that it was an easy solution.

However, at the end I do not see a "ImagePositionPatient" (0020,0032) tag in the header of my slices, so there is no origin at all.

Here is the code,

Thank you for your help

Antoine


/*
-----------------------------------------------------------------
	write dicom series from my volume
-----------------------------------------------------------------
*/	
	// declare a new Image type for the slice
	const unsigned int	SliceDimension = 3; // changed 2 to 3 to have a 3D origin
	typedef itk::Image< unsigned short, SliceDimension > SliceType;
	SliceType::Pointer slice = SliceType::New();

	// attempt to manually modify the origin
	typedef itk::ChangeInformationImageFilter<ImageType> ChangeFilterType4Slice;
	ChangeFilterType4Slice::Pointer sliceheaderfilter = ChangeFilterType4Slice::New();
	double neworigin [SliceDimension];
	neworigin[0]=0;
	neworigin[1]=0;
	neworigin[2]=0; // will be updated in loop for each slice

	// declare a new writer type for writing slices
	typedef itk::ImageFileWriter< SliceType > SliceWriterType;
	SliceWriterType::Pointer slicewriter = SliceWriterType::New();
	
	// declare an extract filter to extract slices
	typedef itk::ExtractImageFilter< ImageType, SliceType > ExtractSliceFilterType;
	ExtractSliceFilterType::Pointer  extractslicefilter = ExtractSliceFilterType::New();
	
	// connect the input of the filter to the output of the previous filter
	if (fR) {extractslicefilter->SetInput( samplfilter->GetOutput() );}
	else{extractslicefilter->SetInput( headerfilter->GetOutput() );}
	
	// define a region to extract from data coming out of previous filters
	ImageType::RegionType extractregion;
	if (fR) {extractregion = samplfilter->GetOutput()->GetLargestPossibleRegion();}
	else{extractregion = headerfilter->GetOutput()->GetLargestPossibleRegion();}
	
	// define that we want to extract a slice in the k direction
    ImageType::SizeType extractsize = extractregion.GetSize();
	extractsize[2] = 1; // I changed that when changing SliceDimension from 2 to 3
	
	// define the size of the slice
	ImageType::RegionType desiredRegion;
	desiredRegion.SetSize(  extractsize  );
	
	// set a variable indexing which slice will be extracted
	ImageType::IndexType extractstart;
	
	// initialize the indexing variable
	extractstart[0]=0; 
	extractstart[1]=0; 
	extractstart[2]=0;
	
	// create a name for the slices
	std::string SliceName;
	int SliceNumber;
	
	// when the loop will end
	const int smax = (extractregion.GetSize())[2];
	
	// for each slice
	for (int s = 0; s < smax; s++) 
	{
		
		// extract slice
		extractstart[2]=s; // redundant for k=0
		desiredRegion.SetIndex( extractstart );
		std::cout << "Extract     " <<extractstart << " into file ";
		extractslicefilter->SetExtractionRegion( desiredRegion );

		// build a file name (quick fix)
		char myBuf[20];
		SliceNumber=s+1;
		sprintf(myBuf, "%i", SliceNumber); 
		SliceName = "";
		if (SliceNumber < 10) {SliceName += "000";}
		else if (SliceNumber <100) {SliceName += "00";}
		else if (SliceNumber <1000) {SliceName += "0";}
		else if (SliceNumber <10000) {SliceName += "";}
		else {
				std::cout << "Too many slices !\n";
				return EXIT_FAILURE;
		}
		SliceName += myBuf;
		SliceName += ".dcm";
		std::cout << SliceName;
		
		
		slicewriter->SetFileName( SliceName );

		// change origin changeinformationfilter 
		sliceheaderfilter->SetInput( extractslicefilter->GetOutput() );
		neworigin[2]=s*spacing[2];
		sliceheaderfilter->SetOutputOrigin(neworigin);
		sliceheaderfilter->ChangeOriginOn();
		sliceheaderfilter->Update();
		slicewriter->SetInput( sliceheaderfilter->GetOutput() );
		

		try 
		{ 
		slicewriter->Update(); 
		} 
		catch( itk::ExceptionObject & err ) 
		{ 
		std::cerr << "ExceptionObject caught !" << std::endl; 
		std::cerr << err << std::endl; 
		return EXIT_FAILURE;
		} 
		std::cout << " with origin " << sliceheaderfilter->GetOutput()->GetOrigin() << std::endl;
		
	}



More information about the Insight-users mailing list