2 //--------------------------------------------------------------------
3 template <class ImageType>
5 clitk::ExtractLymphStationsFilter<ImageType>::
6 ExtractStation_3A_SetDefaultValues()
8 SetFuzzyThreshold("3A", "Sternum", 0.5);
9 SetFuzzyThreshold("3A", "SubclavianArtery", 0.5);
11 //--------------------------------------------------------------------
14 //--------------------------------------------------------------------
15 template <class TImageType>
17 clitk::ExtractLymphStationsFilter<TImageType>::
20 if (!CheckForStation("3A")) return;
22 // Get the current support
23 StartNewStep("[Station 3A] Get the current 3A suppport");
24 m_Working_Support = m_ListOfSupports["S3A"];
25 m_ListOfStations["3A"] = m_Working_Support;
26 StopCurrentStep<MaskImageType>(m_Working_Support);
28 ExtractStation_3A_AntPost_S5();
29 ExtractStation_3A_AntPost_S6();
30 ExtractStation_3A_AntPost_Superiorly();
32 ExtractStation_3A_Remove_Structures();
34 Remove_Structures("3A", "Aorta");
35 Remove_Structures("3A", "SubclavianArteryLeft");
36 Remove_Structures("3A", "SubclavianArteryRight");
37 Remove_Structures("3A", "Thyroid");
38 Remove_Structures("3A", "CommonCarotidArteryLeft");
39 Remove_Structures("3A", "CommonCarotidArteryRight");
40 Remove_Structures("3A", "BrachioCephalicArtery");
41 // Remove_Structures("3A", "BrachioCephalicVein"); ?
44 // ExtractStation_3A_Ant_Limits(); --> No, already in support; to remove
45 // ExtractStation_3A_Post_Limits(); --> No, more complex, see Vessels etc
47 // Store image filenames into AFDB
48 writeImage<MaskImageType>(m_ListOfStations["3A"], "seg/Station3A.mhd");
49 GetAFDB()->SetImageFilename("Station3A", "seg/Station3A.mhd");
52 //--------------------------------------------------------------------
55 //--------------------------------------------------------------------
56 template <class ImageType>
58 clitk::ExtractLymphStationsFilter<ImageType>::
59 ExtractStation_3A_Ant_Limits()
61 StartNewStep("[Station 3A] Ant limits with Sternum");
63 // Get Sternum, keep posterior part.
64 MaskImagePointer Sternum = GetAFDB()->template GetImage<MaskImageType>("Sternum");
66 clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, Sternum, 2,
67 GetFuzzyThreshold("3A", "Sternum"), "PostTo",
68 false, 3, true, false);
69 StopCurrentStep<MaskImageType>(m_Working_Support);
70 m_ListOfStations["3A"] = m_Working_Support;
72 //--------------------------------------------------------------------
75 //--------------------------------------------------------------------
76 template <class ImageType>
78 clitk::ExtractLymphStationsFilter<ImageType>::
79 ExtractStation_3A_Post_Limits()
81 StartNewStep("[Station 3A] Post limits with SubclavianArtery");
83 // Get Sternum, keep posterior part.
84 MaskImagePointer SubclavianArteryLeft =
85 GetAFDB()->template GetImage<MaskImageType>("SubclavianArteryLeft");
86 MaskImagePointer SubclavianArteryRight =
87 GetAFDB()->template GetImage<MaskImageType>("SubclavianArteryRight");
90 clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, SubclavianArteryLeft, 2,
91 GetFuzzyThreshold("3A", "SubclavianArtery"), "AntTo",
92 false, 3, true, false);
94 clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, SubclavianArteryRight, 2,
95 GetFuzzyThreshold("3A", "SubclavianArtery"), "AntTo",
96 false, 3, true, false);
97 StopCurrentStep<MaskImageType>(m_Working_Support);
98 m_ListOfStations["3A"] = m_Working_Support;
100 //--------------------------------------------------------------------
103 //--------------------------------------------------------------------
104 template <class ImageType>
106 clitk::ExtractLymphStationsFilter<ImageType>::
107 ExtractStation_3A_AntPost_S5()
109 StartNewStep("[Station 3A] Post limits around S5");
111 // First remove post to SVC
112 MaskImagePointer SVC = GetAFDB()->template GetImage <MaskImageType>("SVC");
114 // Trial in 3D -> difficulties superiorly. Stay slice by slice.
116 typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> RelPosFilterType;
117 typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
118 relPosFilter->VerboseStepFlagOff();
119 relPosFilter->WriteStepFlagOff();
120 relPosFilter->SetBackgroundValue(GetBackgroundValue());
121 relPosFilter->SetInput(m_Working_Support);
122 relPosFilter->SetInputObject(SVC);
123 relPosFilter->AddOrientationTypeString("PostTo");
124 relPosFilter->SetInverseOrientationFlag(true);
125 relPosFilter->SetIntermediateSpacing(4);
126 relPosFilter->SetIntermediateSpacingFlag(false);
127 relPosFilter->SetFuzzyThreshold(0.5);
128 // relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop
129 relPosFilter->Update();
130 m_Working_Support = relPosFilter->GetOutput();
133 // Slice by slice not post to SVC. Use initial spacing
135 clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, SVC, 2,
136 GetFuzzyThreshold("3A", "SVC"),
138 SVC->GetSpacing()[0], false, false);
140 // Consider Aorta, remove Left/Post part ; only around S5
141 // Get S5 support and Aorta
142 MaskImagePointer S5 = m_ListOfSupports["S5"];
143 MaskImagePointer Aorta = GetAFDB()->template GetImage <MaskImageType>("Aorta");
144 Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, S5, GetBackgroundValue());
146 // Inferiorly, Aorta has two CCL that merge into a single one when
147 // S6 appears. Loop on Aorta slices, select the most ant one, detect
148 // the most ant point.
149 std::vector<MaskSlicePointer> slices;
150 clitk::ExtractSlices<MaskImageType>(Aorta, 2, slices);
151 std::vector<MaskImagePointType> points;
152 for(uint i=0; i<slices.size(); i++) {
153 // Select most ant CCL
154 slices[i] = clitk::Labelize<MaskSliceType>(slices[i], GetBackgroundValue(), false, 1);
155 std::vector<MaskSlicePointType> c;
156 clitk::ComputeCentroids<MaskSliceType>(slices[i], GetBackgroundValue(), c);
157 assert(c.size() == 3); // only 2 CCL
158 typename MaskSliceType::PixelType l;
159 if (c[1][1] > c[2][1]) { // We will remove the label=1
163 l = 2;// We will remove the label=2
165 slices[i] = clitk::SetBackground<MaskSliceType, MaskSliceType>(slices[i], slices[i], l,
166 GetBackgroundValue(), true);
168 // Detect the most ant point
169 MaskSlicePointType p;
170 MaskImagePointType pA;
171 clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices[i], GetBackgroundValue(), 1, true, p);
172 // Set the X coordinate to the X coordinate of the centroid
173 if (l==1) p[0] = c[2][0];
176 // Convert in 3D and store
177 clitk::PointsUtils<MaskImageType>::Convert2DTo3D(p, Aorta, i, pA);
178 points.push_back(pA);
182 // MaskImagePointer o = clitk::JoinSlices<MaskImageType>(slices, Aorta, 2);
183 // writeImage<MaskImageType>(o, "o.mhd");
184 // clitk::WriteListOfLandmarks<MaskImageType>(points, "Ant-Aorta.txt");
186 // Remove Post/Left to this point
188 clitk::SliceBySliceSetBackgroundFromPoints<MaskImageType>(m_Working_Support,
189 GetBackgroundValue(), 2,
191 true, // Set BG if X greater than point[x], and
192 true); // if Y greater than point[y]
194 StopCurrentStep<MaskImageType>(m_Working_Support);
195 m_ListOfStations["3A"] = m_Working_Support;
197 //--------------------------------------------------------------------
200 //--------------------------------------------------------------------
201 template <class ImageType>
203 clitk::ExtractLymphStationsFilter<ImageType>::
204 ExtractStation_3A_AntPost_S6()
206 StartNewStep("[Station 3A] Post limits around S6");
209 MaskImagePointer Aorta = GetAFDB()->template GetImage <MaskImageType>("Aorta");
211 // Limits the support to S6
212 MaskImagePointer S6 = m_ListOfSupports["S6"];
213 Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, S6, GetBackgroundValue());
215 // Extend 1cm anteriorly
216 MaskImagePointType radius; // in mm
219 radius[2] = 0; // required
220 Aorta = clitk::Dilate<MaskImageType>(Aorta, radius, GetBackgroundValue(), GetForegroundValue(), false);
224 clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, Aorta, 2,
225 GetFuzzyThreshold("3A", "Aorta"),
227 Aorta->GetSpacing()[0], false, false);
229 StopCurrentStep<MaskImageType>(m_Working_Support);
230 m_ListOfStations["3A"] = m_Working_Support;
232 //--------------------------------------------------------------------
235 //--------------------------------------------------------------------
236 template <class ImageType>
238 clitk::ExtractLymphStationsFilter<ImageType>::
239 ExtractStation_3A_AntPost_Superiorly()
241 StartNewStep("[Station 3A] Post limits superiorly");
244 MaskImagePointer BrachioCephalicVein = GetAFDB()->template GetImage <MaskImageType>("BrachioCephalicVein");
245 MaskImagePointer BrachioCephalicArtery = GetAFDB()->template GetImage <MaskImageType>("BrachioCephalicArtery");
246 MaskImagePointer CommonCarotidArteryLeft = GetAFDB()->template GetImage <MaskImageType>("CommonCarotidArteryLeft");
247 MaskImagePointer CommonCarotidArteryRight = GetAFDB()->template GetImage <MaskImageType>("CommonCarotidArteryRight");
248 MaskImagePointer SubclavianArteryLeft = GetAFDB()->template GetImage <MaskImageType>("SubclavianArteryLeft");
249 MaskImagePointer SubclavianArteryRight = GetAFDB()->template GetImage <MaskImageType>("SubclavianArteryRight");
252 #define RP(STRUCTURE) \
253 m_Working_Support = \
254 clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, STRUCTURE, 2, \
257 STRUCTURE->GetSpacing()[0], false, false);
259 // RP(BrachioCephalicVein);
260 RP(BrachioCephalicArtery);
261 RP(CommonCarotidArteryRight);
262 RP(CommonCarotidArteryLeft);
263 RP(SubclavianArteryRight);
264 RP(SubclavianArteryLeft);
267 // Get or compute the binary mask that separate Ant/Post part
268 // according to vessels
269 MaskImagePointer binarizedContour = FindAntPostVessels2();
270 binarizedContour = clitk::ResizeImageLike<MaskImageType>(binarizedContour,
272 GetBackgroundValue());
274 // remove from support
275 typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BoolFilterType;
276 typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
277 boolFilter->InPlaceOn();
278 boolFilter->SetInput1(m_Working_Support);
279 boolFilter->SetInput2(binarizedContour);
280 boolFilter->SetBackgroundValue1(GetBackgroundValue());
281 boolFilter->SetBackgroundValue2(GetBackgroundValue());
282 boolFilter->SetOperationType(BoolFilterType::AndNot);
283 boolFilter->Update();
284 m_Working_Support = boolFilter->GetOutput();
286 StopCurrentStep<MaskImageType>(m_Working_Support);
287 m_ListOfStations["3A"] = m_Working_Support;
289 //--------------------------------------------------------------------
292 //--------------------------------------------------------------------
293 template <class ImageType>
295 clitk::ExtractLymphStationsFilter<ImageType>::
296 ExtractStation_3A_Remove_Structures()
298 Remove_Structures("3A", "Aorta");
299 Remove_Structures("3A", "SubclavianArteryLeft");
300 Remove_Structures("3A", "SubclavianArteryRight");
301 Remove_Structures("3A", "Thyroid");
302 Remove_Structures("3A", "CommonCarotidArteryLeft");
303 Remove_Structures("3A", "CommonCarotidArteryRight");
304 Remove_Structures("3A", "BrachioCephalicArtery");
305 // Remove_Structures("3A", "BrachioCephalicVein"); ?
307 StartNewStep("[Station 3A] Remove part of BrachioCephalicVein");
308 // resize like support, extract slices
309 // while single CCL -> remove
310 // when two remove only the most post
311 BrachioCephalicVein = clitk::ResizeImageLike<MaskImageType>(BrachioCephalicVein,
313 GetBackgroundValue());
314 std::vector<MaskSlicePointer> slices;
315 std::vector<MaskSlicePointer> slices_BCV;
316 clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
317 clitk::ExtractSlices<MaskImageType>(BrachioCephalicVein, 2, slices_BCV);
318 for(uint i=0; i<slices.size(); i++) {
319 // Labelize slices_BCV
320 slices_BCV[i] = Labelize<MaskSliceType>(slices_BCV[i], 0, true, 1);
322 std::vector<typename MaskSliceType::PointType> centroids;
323 ComputeCentroids<MaskSliceType>(slices_BCV[i], GetBackgroundValue(), centroids);
324 if (centroids.size() > 1) {
325 // Only keep the one most post
326 typename MaskSliceType::PixelType label;
327 if (centroids[1][1] > centroids[2][1]) {
336 slices_BCV[i] = clitk::SetBackground<MaskSliceType>(slices_BCV[i], slices_BCV[i],
338 GetBackgroundValue(), true);
340 // Remove from the support
341 slices[i] = clitk::AndNot(slices[i], slices_BCV[i], GetBackgroundValue());
345 m_Working_Support = clitk::JoinSlices<MaskImageType>(slices, m_Working_Support, 2);
347 StopCurrentStep<MaskImageType>(m_Working_Support);
348 m_ListOfStations["3A"] = m_Working_Support;
350 //--------------------------------------------------------------------