I am using dcmtk
to read a dicom. This dicom file contains 100 image. Each image has a PatientPosition
. How can I get these 100 PatientPosition
?
If DicomImage
can provide the 100 PatientPosition
?
If findAndGetSequenceItem
can provide the 100 PatientPosition
?
Hope some c++ code to fetch 100 PatientPosition
.
I assume that you are referring to an enhanced DICOM object (e.g. Enhanced CT Image, Enhanced MR Image or the like). In this case the frame-specific tags can be found in the Per-Frame Functional Group Sequence (the link show the reference for an Enhanced MR Image). Each item of the sequence refers to a separate frame.
I also assume that by PatientPosition
you actually mean PatientPositionPatient
, which would be the related tag for MR, CT and a few other types of images, but the handling of frame-specific tags is the same regardless of the tag. Each frame-specific tag is embedded into another sequence, which groups together related tags - in the case of PatientPositionPatient
this is the Plane Position Sequence. As dcmtk allows to search for tags recursively in sub-sequences, you even don't have to know that - it is enough to search for the tag in the relevant sequence item:
auto dcmFile = new DcmFileFormat;
auto cond = dcmFile->loadFile(filePath);
if (cond.good()) {
// load the dataset from the DICOM file
auto* dataset = dcmFile->getDataset();
DcmSequenceOfItems* sequence;
// search for the per-frame functional groups sequence
OFResult result = dataset->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, sequence);
if (result.good() && sequence && !sequence->isEmpty()) {
// iterate over all items until none remains
// this will correspond to the number of frames
for (int frameNr = 0;; ++frameNr) {
auto* item = sequence->getItem(frame);
if (!item) { // could instead get NumberOfFrames first
break;
}
// Image Position Patient is inside the Plane Position Sequence
DcmSequenceOfItems* planePositionSequence;
result = item->findAndGetSequence(DCM_PlanePositionSequence, planePositionSequence);
if (result.good() && planePositionSequence && !planePositionSequence->isEmpty()) {
// Plane Position Sequence has only one item
auto* firstItem = planePositionSequence->getItem(0);
// Image Position Patient has 3 components
double pos[3];
for (i = 0; i < 3; ++i) {
// findAndGetFloat64 automatically converts the strings to double
if (!firstItem->findAndGetFloat64(DCM_ImagePositionPatient, pos[i], i).good()) {
// do some error handling here
}
}
// do something sensible with the result
std::cout << "Position: " << pos[0] << ", " << pos[1] << ", " << pos[2];
}
}
}
}
Note that this is just out of my head and may contain errors. In reality, you need to add some error handling, and of course save the position somewhere sensible.