[ITK-users] Writing a DICOM file while preserving input image properties

Matt McCormick matt.mccormick at kitware.com
Thu Mar 9 09:47:03 EST 2017


HI Sarthak,

The slice thickness is different from the spacing between slices. In
DICOM, slice thickness is related to the point spread function of the
imaging system and slice spacing is related to digital sampling.

Hope this helps,
Matt

On Thu, Mar 9, 2017 at 9:30 AM, Sarthak P <scapegoat.sarthak at gmail.com> wrote:
> Hi Matt,
>
> Thanks for the response.
>
> I don't think I am having issues with writing into the tags since I am able
> to read the correct information I am writing (for instance, the tag
> "0020|0032" is always populated with the physical coordinate of the specific
> slice in a correct manner both during writing and reading). In an example,
> the slice thickness should be "2" and the separation between the dicom
> slices is "2", which is correct. But when ITK is reading this collection, it
> keeps the slice thickness at "1". I am seeing the same behavior in other
> applications as well (ITK-SNAP, etc.).
>
> Could there be some tag I am missing to write? Since my last post, I tried
> writing only to the tag "0020|0032"; the output dictionary array gets
> populated properly but the file is still not written as expected. I am using
> ITK 4.11, BTW.
>
> Best,
> Sarthak
>
> On Thu, Mar 9, 2017 at 9:20 AM, Matt McCormick <matt.mccormick at kitware.com>
> wrote:
>>
>> Hi Sarthak,
>>
>> DICOM export requires improved typing to produce a valid set of tags.
>> This work has been started here:
>>
>>   https://github.com/KitwareMedical/ITKDICOM
>>
>> but the implementation is in initial stages. I would be happy to
>> provide guidance if you would like to move it forward.
>>
>> Thanks,
>> Matt
>>
>> On Wed, Mar 8, 2017 at 3:11 PM, Sarthak P <scapegoat.sarthak at gmail.com>
>> wrote:
>> > Hello All,
>> >
>> > I am trying to write a DICOM image but I want to preserve the properties
>> > from the input image (origin, direction, spacing, etc.). The ITK
>> > examples do
>> > not show how to do this properly and anything I have done with the dicom
>> > tags hasn't worked. Any help would be much appreciated.
>> >
>> > Here is what I have so far:
>> >
>> > //////////
>> >   const std::string dataDir = argv[1];
>> >   const std::string inputFile = dataDir + "/inputImage.nii.gz";
>> >   const std::string outputDir = dataDir + "/test/";
>> >
>> >   using ImageTypeToRead = itk::Image< float, 3 >;
>> >   using ImageTypeToWrite = itk::Image< short, 3 >;
>> >   auto inputImage = cbica::ReadImageWithOrientFix< itk::Image< float, 3
>> > >
>> >>(inputFile);
>> >   auto imageToWrite = inputImage;
>> >
>> >   auto dicomIO = itk::GDCMImageIO::New();
>> >
>> >   auto seriesWriter = itk::ImageSeriesWriter< ImageTypeToWrite,
>> > itk::Image<ImageTypeToWrite::PixelType, 2> >::New();
>> >
>> >   auto namesGenerator = itk::NumericSeriesFileNames::New();
>> >   auto start = imageToWrite->GetLargestPossibleRegion().GetIndex();
>> >   auto size = imageToWrite->GetLargestPossibleRegion().GetSize();
>> >   namesGenerator->SetSeriesFormat((outputDir +
>> > "/image%03d.dcm").c_str());
>> >   namesGenerator->SetStartIndex(start[2]);
>> >   namesGenerator->SetEndIndex(start[2] + size[2] - 1);
>> >   namesGenerator->SetIncrementIndex(1);
>> >
>> >   auto castFilter = itk::CastImageFilter<ImageTypeToRead,
>> > ImageTypeToWrite>::New();
>> >   castFilter->SetInput(imageToWrite);
>> >   castFilter->Update();
>> >
>> >   seriesWriter->SetInput(castFilter->GetOutput());
>> >   seriesWriter->SetImageIO(dicomIO);
>> >   seriesWriter->SetFileNames(namesGenerator->GetFileNames());
>> >
>> >   typename itk::ImageSeriesReader< ImageTypeToRead
>> > >::DictionaryArrayType
>> > outputArray;
>> >
>> >   // this doesn't work at all - was kind of hoping it would do the heavy
>> > lifting for me
>> >   //dicomIO->SetOrigin(0, imageToWrite->GetOrigin()[0]);
>> >   //dicomIO->SetOrigin(1, imageToWrite->GetOrigin()[1]);
>> >   //dicomIO->SetOrigin(2, imageToWrite->GetOrigin()[2]);
>> >   //dicomIO->SetSpacing(0, imageToWrite->GetSpacing()[0]);
>> >   //dicomIO->SetSpacing(1, imageToWrite->GetSpacing()[1]);
>> >   //dicomIO->SetSpacing(2, imageToWrite->GetSpacing()[2]);
>> >   //dicomIO->SetDimensions(0,
>> > imageToWrite->GetLargestPossibleRegion().GetSize()[0]);
>> >   //dicomIO->SetDimensions(1,
>> > imageToWrite->GetLargestPossibleRegion().GetSize()[1]);
>> >   //dicomIO->SetDimensions(2,
>> > imageToWrite->GetLargestPossibleRegion().GetSize()[2]);
>> >   // this doesn't work at all
>> >
>> >   for (size_t i = 0; i <
>> > imageToWrite->GetLargestPossibleRegion().GetSize()[2]; i++)
>> >   {
>> >     auto dict = new itk::ImageSeriesReader< ImageTypeToRead
>> >>::DictionaryType;
>> >     typename ImageTypeToWrite::PointType position;
>> >     typename ImageTypeToWrite::IndexType index;
>> >     index[0] = 0;
>> >     index[1] = 0;
>> >     index[2] = i;
>> >     imageToWrite->TransformIndexToPhysicalPoint(index, position);
>> >     // tags extracted from dicom lookup
>> > http://dicomlookup.com/lookup.asp
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0020|0032",
>> > std::to_string(position[0]) + "\\" + std::to_string(position[1]) + "\\"
>> > +
>> > std::to_string(position[2])); // patient position
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0018|5100",
>> > std::to_string(position[0]) + "\\" + std::to_string(position[1]) + "\\"
>> > +
>> > std::to_string(position[2]));
>> >     itk::EncapsulateMetaData<std::string>(*dict, "2020|0010",
>> > std::to_string(position[0]) + "\\" + std::to_string(position[1]) + "\\"
>> > +
>> > std::to_string(position[2]));
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0018|5101",
>> > std::to_string(position[0]) + "\\" + std::to_string(position[1]) + "\\"
>> > +
>> > std::to_string(position[2]));
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0018|0050",
>> > std::to_string(imageToWrite->GetSpacing()[2])); // Slice Thickness
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0018|0088",
>> > std::to_string(imageToWrite->GetSpacing()[2])); // Spacing Between
>> > Slices
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0008|0008",
>> > "DERIVED\\SECONDARY"); // Image Type
>> >     itk::EncapsulateMetaData<std::string>(*dict, "0008|0064", "DV"); //
>> > Conversion Type
>> >
>> >     outputArray.push_back(dict);
>> >   }
>> >
>> >   seriesWriter->SetMetaDataDictionaryArray(&outputArray); // no
>> > dictionary
>> > information present without seriesReader
>> >
>> >   try
>> >   {
>> >     seriesWriter->Write();
>> >   }
>> >   catch (itk::ExceptionObject &e)
>> >   {
>> >     std::cerr << "Error occurred while trying to write the image '" <<
>> > outputDir << "': " << e.what() << "\n";
>> >     exit(EXIT_FAILURE);
>> >   }
>> >
>> > //////////
>> >
>> > Thanks a ton,
>> > Sarthak
>> >
>> > _____________________________________
>> > Powered by www.kitware.com
>> >
>> > Visit other Kitware open-source projects at
>> > http://www.kitware.com/opensource/opensource.html
>> >
>> > Kitware offers ITK Training Courses, for more information visit:
>> > http://www.kitware.com/products/protraining.php
>> >
>> > Please keep messages on-topic and check the ITK FAQ at:
>> > http://www.itk.org/Wiki/ITK_FAQ
>> >
>> > Follow this link to subscribe/unsubscribe:
>> > http://public.kitware.com/mailman/listinfo/insight-users
>> >
>
>


More information about the Insight-users mailing list