[Insight-users] reading a dicom series to a volume

Luis Ibanez luis.ibanez at kitware.com
Sat Feb 7 12:55:00 EST 2009


Hi Shoosh,

Apparently you don't have enough RAM memory for reading this image.

Please let us know:


     A) What is the total size of the DICOM file on Disk ?
     B) How much RAM do you have in your computer ?
     C) What is your operating system ?
     D) Is it a 32bits machine or a 64bits machine ?


   Thanks


       Luis



------------------
shoosh moosh wrote:
> I'm trying to read a Dicom series as a volume. I'm getting this error 
> during the reading process (during execution of reader->Update() ):
>  
> itk::ExceptionObject (0xb7c006a8)
> Location: "TElement* itk::ImportImageContainer<TElementIdentifier, 
> TElement>::AllocateElements(TElementIdentifier) const [with 
> TElementIdentifier = long unsigned int, TElement = short int]"
> File: /home/shaza/Insight/Code/Common/itkImportImageContainer.txx
> Line: 194
> Description: Failed to allocate memory for image.
>  
> I attached the source file.
> I don't understand what could have caused such an error.
> 
> ------------------------------------------------------------------------
> check out the rest of the Windows Live™. More than mail–Windows Live™ 
> goes way beyond your inbox. More than messages 
> <http://www.microsoft.com/windows/windowslive/>
> 
> 
> ------------------------------------------------------------------------
> 
> #include "itkOrientedImage.h"
> #include "itkGDCMImageIO.h"
> #include "itkGDCMSeriesFileNames.h"
> #include "itkImageSeriesReader.h"
> #include "itkImageFileWriter.h"
> 
> int main( int argc, char* argv[] )
> {
> 
>   if( argc < 3 )
>     {
>     std::cerr << "Usage: " << std::endl;
>     std::cerr << argv[0] << " DicomDirectory  outputFileName  [seriesName]" 
>               << std::endl;
>     return EXIT_FAILURE;
>     }
> 
> // We define the pixel type and dimension of the image to be read.
> // We also choose to use the \doxygen{OrientedImage} in order to make sure
> // that the image orientation information contained in the direction cosines
> // of the DICOM header are read in and passed correctly down the image processing
> // pipeline.
> 
>   typedef signed short	  PixelType;
>   const unsigned int      Dimension = 3;
> 
>   typedef itk::OrientedImage< PixelType, Dimension >         ImageType;
> 
>   typedef itk::ImageSeriesReader< ImageType >        ReaderType;
>   ReaderType::Pointer reader = ReaderType::New();
> 
>   typedef itk::GDCMImageIO       ImageIOType;
>   ImageIOType::Pointer dicomIO = ImageIOType::New();
>   
>   reader->SetImageIO( dicomIO );
> 
> // Now we face one of the main challenges of the process of reading a DICOM
> // series. That is, to identify from a given directory the set of filenames
> // that belong together to the same volumetric image. Fortunately for us, GDCM
> // offers functionalities for solving this problem and we just need to invoke
> // those functionalities through an ITK class that encapsulates a communication
> // with GDCM classes. This ITK object is the GDCMSeriesFileNames. Conveniently
> // for us, we only need to pass to this class the name of the directory where
> // the DICOM slices are stored. This is done with the \code{SetDirectory()}
> // method. The GDCMSeriesFileNames object will explore the directory and will
> // generate a sequence of filenames for DICOM files for one study/series. 
> // In this example, we also call the \code{SetUseSeriesDetails(true)} function
> // that tells the GDCMSereiesFileNames object to use additional DICOM 
> // information to distinguish unique volumes within the directory.  This is
> // useful, for example, if a DICOM device assigns the same SeriesID to 
> // a scout scan and its 3D volume; by using additional DICOM information
> // the scout scan will not be included as part of the 3D volume.  Note that
> // \code{SetUseSeriesDetails(true)} must be called prior to calling
> // \code{SetDirectory()}. By default \code{SetUseSeriesDetails(true)} will use
> // the following DICOM tags to sub-refine a set of files into multiple series:
> // * 0020 0011 Series Number
> // * 0018 0024 Sequence Name
> // * 0018 0050 Slice Thickness
> // * 0028 0010 Rows
> // * 0028 0011 Columns
> // If this is not enough for your specific case you can always add some more
> // restrictions using the \code{AddSeriesRestriction()} method. In this example we will use
> // the DICOM Tag: 0008 0021 DA 1 Series Date, to sub-refine each series. The format
> // for passing the argument is a string containing first the group then the element
> // of the DICOM tag, separed by a pipe (|) sign.
> 
>   typedef itk::GDCMSeriesFileNames NamesGeneratorType;
>   NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
> 
>   nameGenerator->SetUseSeriesDetails( true );
>   nameGenerator->AddSeriesRestriction("0008|0021" );
> 
>   nameGenerator->SetDirectory( argv[1] );
>   
>   try
>     {
>     std::cout << std::endl << "The directory: " << std::endl;
>     std::cout << std::endl << argv[1] << std::endl << std::endl;
>     std::cout << "Contains the following DICOM Series: ";
>     std::cout << std::endl << std::endl;
> 
> 
> // The GDCMSeriesFileNames object first identifies the list of DICOM series
> // that are present in the given directory. We receive that list in a reference
> // to a container of strings and then we can do things like printing out all
> // the series identifiers that the generator had found. Since the process of
> // finding the series identifiers can potentially throw exceptions, it is
> // wise to put this code inside a try/catch block.
> 
>     typedef std::vector< std::string >    SeriesIdContainer;
>     
>     const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();
>     
>     SeriesIdContainer::const_iterator seriesItr = seriesUID.begin();
>     SeriesIdContainer::const_iterator seriesEnd = seriesUID.end();
>     while( seriesItr != seriesEnd )
>       {
>       std::cout << seriesItr->c_str() << std::endl;
>       seriesItr++;
>       }
> 
> // Given that it is common to find multiple DICOM series in the same directory,
> // we must tell the GDCM classes what specific series do we want to read. In
> // this example we do this by checking first if the user has provided a series
> // identifier in the command line arguments. If no series identifier has been
> // passed, then we simply use the first series found during the exploration of
> // the directory.
> 
>     std::string seriesIdentifier;
> 
>     if( argc > 3 ) // If no optional series identifier
>       {
>       seriesIdentifier = argv[3];
>       }
>     else
>       {
>       seriesIdentifier = seriesUID.begin()->c_str();
>       }
> 
>     std::cout << std::endl << std::endl;
>     std::cout << "Now reading series: " << std::endl << std::endl;
>     std::cout << seriesIdentifier << std::endl;
>     std::cout << std::endl << std::endl;
> 
>  
> // We pass the series identifier to the name generator and ask for all the
> // filenames associated to that series. This list is returned in a container of
> // strings by the \code{GetFileNames()} method. 
> //
> // \index{itk::GDCMSeriesFileNames!GetFileNames()}
> 
>     typedef std::vector< std::string >   FileNamesContainer;
>     FileNamesContainer fileNames;
> 
>     fileNames = nameGenerator->GetFileNames( seriesIdentifier );
> 
> // The list of filenames can now be passed to the \doxygen{ImageSeriesReader}
> // using the \code{SetFileNames()} method.
> //  
> //  \index{itk::ImageSeriesReader!SetFileNames()}
> 
>     reader->SetFileNames( fileNames );
> 
> // Finally we can trigger the reading process by invoking the \code{Update()}
> // method in the reader. This call as usual is placed inside a \code{try/catch}
> // block.
>     try
>       {
>       reader->Update();
>       }
>     catch (itk::ExceptionObject &ex)
>       {
>       std::cout << ex << std::endl;
>       return EXIT_FAILURE;
>       }
> 
> // At this point, we have a volumetric image in memory that we can access by
> // invoking the \code{GetOutput()} method of the reader.
> 
> // We proceed now to save the volumetric image in another file, as specified by
> // the user in the command line arguments of this program. Thanks to the
> // ImageIO factory mechanism, only the filename extension is needed to identify
> // the file format in this case.
>    
>     typedef itk::ImageFileWriter< ImageType > WriterType;
>     WriterType::Pointer writer = WriterType::New();
>     
>     writer->SetFileName( argv[2] );
> 
>     writer->SetInput( reader->GetOutput() );
> 
>     std::cout  << "Writing the image as " << std::endl << std::endl;
>     std::cout  << argv[2] << std::endl << std::endl;
> 
> // The process of writing the image is initiated by invoking the
> // \code{Update()} method of the writer.
> 
>   try
>       {  
>       writer->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;
>     }
> 
> // Note that in addition to writing the volumetric image to a file we could
> // have used it as the input for any 3D processing pipeline. Keep in mind that
> // DICOM is simply a file format and a network protocol. Once the image data
> // has been loaded into memory, it behaves as any other volumetric dataset that
> // you could have loaded from any other file format. 
> 
>   return EXIT_SUCCESS;
> }
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk.org
> http://www.itk.org/mailman/listinfo/insight-users


More information about the Insight-users mailing list