[ITK-users] Writing a DICOM file while preserving input image properties
Matt McCormick
matt.mccormick at kitware.com
Thu Mar 9 09:20:49 EST 2017
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