Read and Print DICOM Tags#
Synopsis#
Example to read, search and print DICOM image metadata tags
Results#
0008|0000 = 406
0008|0005 = ISO_IR 100
0008|0008 = ORIGINAL\PRIMARY\OTHER
0008|0016 = 1.2.840.10008.5.1.4.1.1.4
0008|0018 = 1.2.840.113619.2.133.1762890640.1886.1055165016.76
0008|0020 = 20030625
0008|0021 = 20030625
0008|0022 = 20030625
0008|0023 = 20030625
0008|0030 = 152734
0008|0031 = 153128
0008|0032 = 153128
0008|0033 = 153128
0008|0050 =
0008|0060 = MR
0008|0070 = GE MEDICAL SYSTEMS
0008|0080 = crd
0008|0090 =
0008|1010 = sig3ow0
0008|1030 = Tech_1
0008|103e = head scan
0008|1070 = RPM
0008|1090 = GENESIS_SIGNA
0010|0000 = 82
0010|0010 = Wes Turner
0010|0020 = 1111
0010|0030 =
0010|0040 = O
0010|1010 = 000Y
0010|1030 = 68.039
0010|21b0 =
0018|0000 = 428
0018|0020 = GR
0018|0021 = SS\SP
0018|0022 = FC\VB_GEMS\VASCTOF_GEMS\PFF
0018|0023 = 3D
0018|0025 = N
0018|0050 = 1.6
0018|0080 = 23
0018|0081 = 10
0018|0083 = 1
0018|0084 = 6.38883e+08
0018|0085 = H1
0018|0086 = 1
0018|0087 = 15000
0018|0088 = 1.6
0018|0091 = 0
0018|0093 = 100
0018|0094 = 75
0018|0095 = 97.6562
0018|1000 = 0000018387rdmr3
0018|1020 = 09
0018|1050 = 1.14585
0018|1088 = 0
0018|1090 = 0
0018|1094 = 0
0018|1100 = 220
0018|1250 = HEAD
0018|1251 = HEAD
0018|1310 = 0\256\192\0
0018|1312 = ROW
0018|1314 = 25
0018|1315 = N
0018|1316 = 0.004169
0018|5100 = HFS
0020|0000 = 340
0020|000d = 1.2.840.113619.2.133.1762890640.1886.1055165015.961
0020|000e = 1.2.840.113619.2.133.1762890640.1886.1055165015.999
0020|0010 = 361
0020|0011 = 3
0020|0012 = 0
0020|0013 = 77
0020|0032 = -112\-18.8578\ 128.388
0020|0037 = 1\ 0\ 0\ 0\0.466651\ -0.884442
0020|0052 = 1.2.840.113619.2.133.1762890640.1910.1055164903.673
0020|0060 =
0020|0110 = 0
0020|1040 =
0020|1041 = -32.4746742249
0028|0000 = 148
0028|0002 = 1
0028|0004 = MONOCHROME2
0028|0010 = 256
0028|0011 = 256
0028|0030 = 0.85939\0.859375
0028|0100 = 16
0028|0101 = 16
0028|0102 = 15
0028|0103 = 1
0028|0120 = 0
0028|1050 = 86
0028|1051 = 173
7fe0|0000 = 131084
Patient's Name (0010|0010) is: Wes Turner
Code#
C++#
// This example illustrates how to read a DICOM series into a volume and then
// print most of the DICOM header information. The binary fields are skipped.
#include "itkImageSeriesReader.h"
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
int
main(int argc, char * argv[])
{
if (argc < 2)
{
std::cerr << "Usage: " << argv[0] << " DicomDirectory " << std::endl;
return EXIT_FAILURE;
}
// Next, we instantiate the type to be used for storing the image once it is
// read into memory.
using PixelType = signed short;
constexpr unsigned int Dimension = 3;
using ImageType = itk::Image<PixelType, Dimension>;
// We use the image type for instantiating the series reader type and then we
// construct one object of this class.
using ReaderType = itk::ImageSeriesReader<ImageType>;
auto reader = ReaderType::New();
// A GDCMImageIO object is created and assigned to the reader.
using ImageIOType = itk::GDCMImageIO;
auto dicomIO = ImageIOType::New();
reader->SetImageIO(dicomIO);
// A GDCMSeriesFileNames is declared in order to generate the names of DICOM
// slices. We specify the directory with the SetInputDirectory() method
// and, in this case, take the directory name from the command line arguments.
// You could have obtained the directory name from a file dialog in a GUI.
using NamesGeneratorType = itk::GDCMSeriesFileNames;
auto nameGenerator = NamesGeneratorType::New();
nameGenerator->SetInputDirectory(argv[1]);
// The list of files to read is obtained from the name generator by invoking
// the GetInputFileNames() method and receiving the results in a
// container of strings. The list of filenames is passed to the reader using
// the SetFileNames() method.
using FileNamesContainer = std::vector<std::string>;
FileNamesContainer fileNames = nameGenerator->GetInputFileNames();
reader->SetFileNames(fileNames);
// We trigger the reader by invoking the Update() method. This
// invocation should normally be done inside a try/catch block given
// that it may eventually throw exceptions.
try
{
reader->Update();
}
catch (const itk::ExceptionObject & ex)
{
std::cout << ex << std::endl;
return EXIT_FAILURE;
}
// ITK internally queries GDCM and obtains all the DICOM tags from the file
// headers. The tag values are stored in the MetaDataDictionary
// which is a general-purpose container for \{key,value\} pairs. The Metadata
// dictionary can be recovered from any ImageIO class by invoking the
// GetMetaDataDictionary() method.
using DictionaryType = itk::MetaDataDictionary;
const DictionaryType & dictionary = dicomIO->GetMetaDataDictionary();
// In this example, we are only interested in the DICOM tags that can be
// represented as strings. Therefore, we declare a MetaDataObject of
// string type in order to receive those particular values.
using MetaDataStringType = itk::MetaDataObject<std::string>;
// The metadata dictionary is organized as a container with its corresponding
// iterators. We can therefore visit all its entries by first getting access to
// its Begin() and End() methods.
auto itr = dictionary.Begin();
auto end = dictionary.End();
// We are now ready for walking through the list of DICOM tags. For this
// purpose we use the iterators that we just declared. At every entry we
// attempt to convert it into a string entry by using the dynamic_cast
// based on RTTI information. The
// dictionary is organized like a std::map structure, so we should use
// the first and second members of every entry in order
// to get access to the \{key,value\} pairs.
while (itr != end)
{
itk::MetaDataObjectBase::Pointer entry = itr->second;
MetaDataStringType::Pointer entryvalue = dynamic_cast<MetaDataStringType *>(entry.GetPointer());
if (entryvalue)
{
std::string tagkey = itr->first;
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
std::cout << tagkey << " = " << tagvalue << std::endl;
}
++itr;
}
// It is also possible to query for specific entries instead of reading all of
// them as we did above. In this case, the user must provide the tag
// identifier using the standard DICOM encoding. The identifier is stored in a
// string and used as key in the dictionary.
std::string entryId = "0010|0010";
auto tagItr = dictionary.Find(entryId);
if (tagItr == end)
{
std::cerr << "Tag " << entryId;
std::cerr << " not found in the DICOM header" << std::endl;
return EXIT_FAILURE;
}
// Since the entry may or may not be of string type we must again use a
// dynamic_cast in order to attempt to convert it to a string dictionary
// entry. If the conversion is successful, we can then print out its content.
MetaDataStringType::ConstPointer entryvalue = dynamic_cast<const MetaDataStringType *>(tagItr->second.GetPointer());
if (entryvalue)
{
std::string tagvalue = entryvalue->GetMetaDataObjectValue();
std::cout << "Patient's Name (" << entryId << ") ";
std::cout << " is: " << tagvalue << std::endl;
}
else
{
std::cerr << "Entry was not of string type" << std::endl;
return EXIT_FAILURE;
}
// This type of functionality will probably be more useful when provided
// through a graphical user interface. For a full description of the DICOM
// dictionary please look at the following file.
return EXIT_SUCCESS;
}
Python#
#!/usr/bin/env python
import sys
import itk
import argparse
parser = argparse.ArgumentParser(description="Read And Print DICOM Tags.")
parser.add_argument(
"dicom_directory",
nargs="?",
help="If DicomDirectory is not specified, current directory is used",
)
args = parser.parse_args()
# current directory by default
dirName = "."
if args.dicom_directory:
dirName = args.dicom_directory
# Setup the image readers with their type
PixelType = itk.ctype("signed short")
Dimension = 3
ImageType = itk.Image[PixelType, Dimension]
# Using GDCMSeriesFileNames to generate the names of
# DICOM files.
namesGenerator = itk.GDCMSeriesFileNames.New()
namesGenerator.SetUseSeriesDetails(True)
namesGenerator.SetDirectory(dirName)
# Get the names of files
fileNames = namesGenerator.GetInputFileNames()
# Setup the image series reader using GDCMImageIO
reader = itk.ImageSeriesReader[ImageType].New()
dicomIO = itk.GDCMImageIO.New()
dicomIO.LoadPrivateTagsOn()
reader.SetImageIO(dicomIO)
reader.SetFileNames(fileNames)
# Attempt to read the series, exit if unable to.
try:
reader.Update()
except:
print("Error occured while reading DICOMs in: " + dirName)
sys.exit(1)
# ITK internally queries GDCM and obtains all the DICOM tags from the file
# headers. The tag values are stored in the MetaDataDictionary
# which is a general-purpose container for \{key,value\} pairs. The Metadata
# dictionary can be recovered from any ImageIO class by invoking the
# GetMetaDataDictionary() method.
metadata = dicomIO.GetMetaDataDictionary()
# Print the key value pairs from the metadadictionary
tagkeys = metadata.GetKeys()
for tagkey in tagkeys:
# Note the [] operator for the key
try:
tagvalue = metadata[tagkey]
print(tagkey + "=" + str(tagvalue))
except RuntimeError:
# Cannot pass specialized values into metadata dictionary.
print("Cannot pass specialized value" + tagkey + "into metadadictionary")
# Illustrating use of getting a label given a tag here
entryID = "0010|0010"
if not metadata.HasKey(entryID):
print("tag: " + entryID + " not found in series")
else:
# The second parameter is mandatory in python to get the
# string label value
label = itk.GDCMImageIO.GetLabelFromTag(entryID, "")
tagvalue = metadata[entryID]
print(label[1] + " (" + entryID + ") is: " + str(tagvalue))
Classes demonstrated#
-
class GDCMImageIO : public itk::ImageIOBase
ImageIO class for reading and writing DICOM V3.0 and ACR/NEMA 1&2 uncompressed images. This class is only an adaptor to the GDCM library.
GDCM can be found at: http://sourceforge.net/projects/gdcm
To learn more about the revision shipped with ITK, call
git log Modules/ThirdParty/GDCM/src/
from an ITK Git checkout.
The compressors supported include “JPEG2000” (default), and “JPEG”. The compression level parameter is not supported.
- Warning
There are several restrictions to this current writer:
Even though during the writing process you pass in a DICOM file as input The output file may not contains ALL DICOM field from the input file. In particular:
The SeQuence DICOM field (SQ).
Fields from Private Dictionary.
Some very long (>0xfff) binary fields are not loaded (typically 0029|0010), you need to explicitly set the maximum length of elements to load to be bigger (see Get/SetMaxSizeLoadEntry).
In DICOM some fields are stored directly using their binary representation. When loaded into the MetaDataDictionary some fields are converted to ASCII (only VR: OB/OW/OF and UN are encoded as mime64).
- ITK Sphinx Examples: