[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