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

Sarthak P scapegoat.sarthak at gmail.com
Thu Mar 9 10:54:06 EST 2017


Found recorded bugs related to this:

https://issues.itk.org/jira/browse/ITK-3176 (spacing)
https://issues.itk.org/jira/browse/ITK-3407 (origin)

Guess we wait and watch.

Thanks a ton for your help,
Sarthak

On Thu, Mar 9, 2017 at 10:26 AM, Sarthak P <scapegoat.sarthak at gmail.com>
wrote:

> So the thing is that even the origin isn't picked up when reading the
> DICOM image (it is always 0,0,0) so I am guessing I am doing something
> wrong when writing into the tag 0020|0032 itself. Once that is rectified,
> the spacing information (should) correct itself.
>
> Best,
> Sarthak
>
>
> On Thu, Mar 9, 2017 at 10:25 AM, Sarthak P <scapegoat.sarthak at gmail.com>
> wrote:
>
>> Hi Matt,
>>
>> Yes I do know that. I have tried to put the spacing information from the
>> itk::Image using various combinations with the tags 0018|0088 (slice
>> thickness) and 0018|0050 (spacing between slices) but to no avail.
>>
>> Thanks for your help,
>> Sarthak
>>
>> On Thu, Mar 9, 2017 at 9:47 AM, Matt McCormick <
>> matt.mccormick at kitware.com> wrote:
>>
>>> 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
>>> >> >
>>> >
>>> >
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/insight-users/attachments/20170309/7369d117/attachment.html>


More information about the Insight-users mailing list