Mercurial > hg > orthanc-stone
comparison OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp @ 1746:4bedae500652
Automatically compute SliceThickness from
GridFrameOffsetVector when SliceThickness
is not present in the DICOM tags
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Fri, 12 Feb 2021 10:41:17 +0100 |
parents | 9ac2a65d4172 |
children | 5f74ebe2516b |
comparison
equal
deleted
inserted
replaced
1745:04019fd631aa | 1746:4bedae500652 |
---|---|
46 | 46 |
47 if (dicom.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false)) | 47 if (dicom.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false)) |
48 { | 48 { |
49 Orthanc::Toolbox::ToUpperCase(increment); | 49 Orthanc::Toolbox::ToUpperCase(increment); |
50 | 50 |
51 // This is the "Grid Frame Offset Vector" tag (DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) | 51 // We only support volumes where the FrameIncrementPointer (0028,0009) (required) contains |
52 // the "Grid Frame Offset Vector" tag (DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) | |
52 if (increment != "3004,000C") | 53 if (increment != "3004,000C") |
53 { | 54 { |
54 LOG(WARNING) << "Bad value for the FrameIncrementPointer tags in a multiframe image"; | 55 LOG(WARNING) << "Bad value for the FrameIncrementPointer tags in a multiframe image"; |
55 target.resize(0); | 56 target.resize(0); |
56 return; | 57 return; |
58 } | 59 } |
59 | 60 |
60 if (!LinearAlgebra::ParseVector(target, dicom, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) || | 61 if (!LinearAlgebra::ParseVector(target, dicom, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) || |
61 target.size() != numberOfFrames) | 62 target.size() != numberOfFrames) |
62 { | 63 { |
63 LOG(INFO) << "The frame offset information is missing in a multiframe image"; | 64 LOG(ERROR) << "The frame offset information (GridFrameOffsetVector (3004,000C)) is missing in a multiframe image"; |
64 | 65 |
65 // DO NOT use ".clear()" here, as the "Vector" class doesn't behave like std::vector! | 66 // DO NOT use ".clear()" here, as the "Vector" class doesn't behave like std::vector! |
66 target.resize(0); | 67 target.resize(0); |
67 } | 68 } |
68 } | 69 } |
107 !dicom.GetValue(Orthanc::DICOM_TAG_ROWS).ParseFirstUnsignedInteger(height_)) | 108 !dicom.GetValue(Orthanc::DICOM_TAG_ROWS).ParseFirstUnsignedInteger(height_)) |
108 { | 109 { |
109 height_ = 0; | 110 height_ = 0; |
110 } | 111 } |
111 | 112 |
113 | |
114 bool sliceThicknessPresent = true; | |
112 if (!dicom.ParseDouble(sliceThickness_, Orthanc::DICOM_TAG_SLICE_THICKNESS)) | 115 if (!dicom.ParseDouble(sliceThickness_, Orthanc::DICOM_TAG_SLICE_THICKNESS)) |
113 { | 116 { |
117 LOG(INFO) << "The (non-madatory) slice thickness information is missing in a multiframe image"; | |
114 sliceThickness_ = 100.0 * std::numeric_limits<double>::epsilon(); | 118 sliceThickness_ = 100.0 * std::numeric_limits<double>::epsilon(); |
119 sliceThicknessPresent = false; | |
115 } | 120 } |
116 | 121 |
117 GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dicom); | 122 GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dicom); |
118 | 123 |
119 std::string position, orientation; | 124 std::string position, orientation; |
125 | 130 |
126 // Must be AFTER setting "numberOfFrames_" | 131 // Must be AFTER setting "numberOfFrames_" |
127 if (numberOfFrames_ > 1) | 132 if (numberOfFrames_ > 1) |
128 { | 133 { |
129 ExtractFrameOffsets(frameOffsets_, dicom, numberOfFrames_); | 134 ExtractFrameOffsets(frameOffsets_, dicom, numberOfFrames_); |
135 | |
136 // if the slice thickness is unknown, we try to infer it from the sequence of grid frame offsets | |
137 // this only works if: | |
138 // - the first offset is 0.0 (case (a) of http://dicom.nema.org/medical/Dicom/2017c/output/chtml/part03/sect_C.8.8.3.2.html) | |
139 // - the offsets are all equal, to some small tolerance | |
140 // - the offsets is positive (increasing throughout the frames) | |
141 if (!sliceThicknessPresent) | |
142 { | |
143 if (frameOffsets_.size() >= 2) | |
144 { | |
145 double sliceThickness = frameOffsets_[1] - frameOffsets_[0]; | |
146 bool sameSized = true; | |
147 if (sliceThickness > 0) | |
148 { | |
149 for (size_t i = 2; i < frameOffsets_.size(); ++i) | |
150 { | |
151 double currentThickness = frameOffsets_[i] - frameOffsets_[i-1]; | |
152 if (!LinearAlgebra::IsNear(sliceThickness, currentThickness)) | |
153 { | |
154 LOG(ERROR) << "Unable to extract slice thickness from GridFrameOffsetVector (3004,000C) (reason: varying spacing)"; | |
155 sameSized = false; | |
156 break; | |
157 } | |
158 } | |
159 if (sameSized) | |
160 { | |
161 sliceThickness_ = sliceThickness; | |
162 LOG(INFO) << "SliceThickness was not specified in the Dicom but was inferred from GridFrameOffsetVector (3004,000C)."; | |
163 } | |
164 } | |
165 } | |
166 else | |
167 { | |
168 LOG(ERROR) << "Unable to extract slice thickness from GridFrameOffsetVector (3004,000C) (reason: GridFrameOffsetVector not present or too small)"; | |
169 } | |
170 } | |
130 } | 171 } |
131 else | 172 else |
132 { | 173 { |
133 frameOffsets_.resize(0); | 174 frameOffsets_.resize(0); |
134 } | 175 } |