]> Creatis software - clitk.git/blob - segmentation/clitkExtractLymphStation_Supports.txx
Comment memory display
[clitk.git] / segmentation / clitkExtractLymphStation_Supports.txx
1
2 #include <itkBinaryDilateImageFilter.h>
3 #include <itkMirrorPadImageFilter.h>
4
5 //--------------------------------------------------------------------
6 template <class ImageType>
7 void 
8 clitk::ExtractLymphStationsFilter<ImageType>::
9 ExtractStationSupports()
10 {
11   // Get initial Mediastinum
12   m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
13
14   // Remove some computed structures
15   this->GetAFDB()->RemoveTag("CarinaZ");
16   this->GetAFDB()->RemoveTag("ApexOfTheChestZ");  
17
18   // Superior and inferior limits.
19   Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0); 
20   Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]); 
21
22   // Read all support limits in a file and apply them
23   ReadSupportLimits(GetSupportLimitsFilename());  
24   for(int i=0; i<m_ListOfSupportLimits.size(); i++) {
25     SupportLimitsType s = m_ListOfSupportLimits[i];
26     Support_SI_Limit(s.station_limit, s.station, s.structure_limit, 
27                      s.structure, s.offset*m_Working_Support->GetSpacing()[2]);
28   }
29
30   // S1RL
31   Support_LeftRight_S1R_S1L();
32
33   // S2RL
34   Support_LeftRight_S2R_S2L();
35
36   // S4RL
37   Support_LeftRight_S4R_S4L();
38   
39   // Post limits of S1,S2,S4
40   Support_Post_S2S4();
41
42   // S3P : "the anterior border is an imaginary horizontal line
43   // extending along the posterior wall of the trachea"
44   StartNewStep("[Support] Ant limits of S3P with trachea");
45   m_ListOfSupports["S3P"] = LimitsWithTrachea(m_ListOfSupports["S3P"], 1, 0, 10);
46
47   // S3A : "Posteriorly, the station is limited by station 2R and 2L,
48   // but excludes the great vessels. An imaginary line joins the
49   // midpoint of the vessel in the anterior to posterior plane. It is
50   // here that station 2 contacts station 3a" ===> here limit with
51   // trachea only
52   StartNewStep("[Support] Ant limits of S3A with trachea");
53   m_ListOfSupports["S3A"] = LimitsWithTrachea(m_ListOfSupports["S3A"], 1, 0, -10);
54
55   // S1RL - posterior limits when SI overlap with S3P
56   Support_Post_S1_S3P();
57   
58   // S1RL - posterior limits with S2RL above sternal notch
59   Support_Post_S1_Ant_S2RL();
60   
61   // I will do it later
62   // Below Carina S7,8,9,10
63   m_ListOfSupports["S7"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
64   m_ListOfSupports["S8"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
65   m_ListOfSupports["S9"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
66   m_ListOfSupports["S10"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
67   m_ListOfSupports["S11"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
68
69   // Store image filenames into AFDB 
70   WriteImageSupport("S1R"); WriteImageSupport("S1L");
71   WriteImageSupport("S2R"); WriteImageSupport("S2L");
72   WriteImageSupport("S3A"); WriteImageSupport("S3P");
73   WriteImageSupport("S4R"); WriteImageSupport("S4L");
74   WriteImageSupport("S5");
75   WriteImageSupport("S6");
76   WriteImageSupport("S7");
77   WriteImageSupport("S8");
78   WriteImageSupport("S9");
79   WriteImageSupport("S10");
80   WriteImageSupport("S11");
81   WriteAFDB();
82 }
83 //--------------------------------------------------------------------
84
85
86 //--------------------------------------------------------------------
87 template <class ImageType>
88 void 
89 clitk::ExtractLymphStationsFilter<ImageType>::
90 Support_SI_Limit(const std::string station_limit, const std::string station, 
91                  const std::string structure_limit, const std::string structure, 
92                  const double offset)
93 {
94   if (!GetCheckSupportFlag()) 
95     StartNewStep("[Support] "+station_limit+" limit of "+station+" is "+structure_limit+" limit of "+structure);
96
97   // Check
98   if ((station_limit != "superior") && (station_limit != "inferior")) {
99     clitkExceptionMacro("Error station_limit must be 'inferior' or 'superior', not '"<< station_limit);
100   }
101   if ((structure_limit != "superior") && (structure_limit != "inferior")) {
102     clitkExceptionMacro("Error structure_limit must be 'inferior' or 'superior', not '"<< structure_limit);
103   }
104
105   // Get current support
106   if (m_ListOfSupports.find(station) == m_ListOfSupports.end()) {
107     // std::cerr << "Warning: support " << station << " not initialized" << std::endl;
108     m_ListOfSupports[station] = m_Mediastinum;
109   }
110   m_Working_Support = m_ListOfSupports[station];
111   
112   // Get structure or structureZ
113   double z;
114   int found=0;
115   std::string file;
116
117   // Try to load structure and compute extrema point
118   if (this->GetAFDB()->TagExist(structure)) {
119     MaskImagePointer Structure = this->GetAFDB()->template GetImage <MaskImageType>(structure);
120     file = this->GetAFDB()->GetTagValue(structure);
121     MaskImagePointType p;
122     p[0] = p[1] = p[2] =  0.0; // to avoid warning
123     if (structure_limit == "superior") 
124       clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
125     else 
126       clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, true, p);
127     z = p[2];
128     found=1;
129   }
130
131   // Try to load structureZ
132   if ((found==0) && (this->GetAFDB()->TagExist(structure+"Z"))) {
133     z = this->GetAFDB()->GetDouble(structure+"Z");
134     found=2;
135   }
136   
137   // Try to load structurePoint
138   if ((found==0) && (this->GetAFDB()->TagExist(structure+"Point"))) {
139     MaskImagePointType p;
140     this->GetAFDB()->GetPoint3D(structure+"Point", p);
141     z = p[2];
142     found=3;
143   }
144
145   // Try to see if it is an already computed support
146   if (found==0) {
147     if (m_ListOfSupports.find(structure) != m_ListOfSupports.end()) {
148       MaskImagePointer Structure = m_ListOfSupports[structure];
149       MaskImagePointType p;
150       if (structure_limit == "superior") 
151         clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
152       else 
153         clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, true, p);
154       z = p[2];
155       found=4;
156     }
157   }
158   
159   // Try special case : "FindApexOfTheChest"
160   if (structure == "FindApexOfTheChest") {
161     z = FindApexOfTheChest();
162     found=5;
163   }
164   if (structure == "FindInferiorBorderOfAorticArch") {
165     z = FindInferiorBorderOfAorticArch();
166     found=6;
167   }
168   if (structure == "FindSuperiorBorderOfAorticArch") {
169     z = FindSuperiorBorderOfAorticArch();
170     found=6;
171   }
172
173   // If we find anything
174   if (found == 0) {
175     std::cerr << "ERROR : I could not find " << structure << " nor " << structure << "Z nor " 
176               << structure << "Point" << std::endl;
177     exit(EXIT_FAILURE);
178   }
179
180   // Apply offset
181   z += offset;
182
183   // Remove Lower or greater
184   if (station_limit == "inferior") {
185     m_Working_Support = 
186       clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
187   }
188   else {
189     m_Working_Support = 
190       clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
191   }
192   
193   // Check: if reference station is given, display information
194   if (GetCheckSupportFlag())  {
195     try {
196       MaskImagePointer Ref = this->GetAFDB()->template GetImage <MaskImageType>(station+"_Ref");
197       MaskImagePointType p_support;
198       MaskImagePointType p_ref;
199       if (station_limit == "superior") {
200         clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, false, p_ref);
201         clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, false, p_support);
202       }
203       else {
204         clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, true, p_ref);
205         clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, true, p_support);
206       }
207       std::ostringstream os;
208       os << "[Support] \t" << station << "\t" << station_limit << " "
209          << "Z = " << z << std::setprecision(2) << std::fixed
210          << "\tSupport = " << p_support[2]
211          << "\tRef = " << p_ref[2]
212          << "\tdiff = " << p_support[2]-p_ref[2] << "\t"
213          << structure << " " << structure_limit;
214       if (found==1) os << " (S "+file+")";
215       if (found==2) os << " (Z)";
216       if (found==3) os << " (P)";
217       if (found==4) os << " (p)";
218       if (found==5) os << " (Apex)";
219       if (found==6) os << " (AorticArch)";
220       StartNewStep(os.str());
221     } catch(clitk::ExceptionObject e) { }
222   }
223   
224   // Set support
225   m_ListOfSupports[station] = m_Working_Support;  
226   StopCurrentStep<MaskImageType>(m_Working_Support);  
227 }
228 //--------------------------------------------------------------------
229
230
231 //--------------------------------------------------------------------
232 template <class ImageType>
233 void 
234 clitk::ExtractLymphStationsFilter<ImageType>::
235 Support_LeftRight_S1R_S1L()
236 {
237   /*
238     Medially, station 1R and 1L are separated by the midline of the
239     trachea, whilst excluding the thyroid gland.
240   */
241
242   // Step S1RL : Left-Right
243   StartNewStep("[Support] Left-Right S1R S1L");
244   std::vector<ImagePointType> A;
245   std::vector<ImagePointType> B;
246   // Search for centroid positions of trachea
247   MaskImagePointer Trachea = this->GetAFDB()->template GetImage <MaskImageType>("Trachea");
248   MaskImagePointer S1RL = m_ListOfSupports["S1R"];
249   Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, S1RL, GetBackgroundValue());
250   std::vector<MaskSlicePointer> slices;
251   clitk::ExtractSlices<MaskImageType>(Trachea, 2, slices);
252   for(uint i=0; i<slices.size(); i++) {
253     slices[i] = Labelize<MaskSliceType>(slices[i], 0, false, 10);
254     std::vector<typename MaskSliceType::PointType> c;
255     clitk::ComputeCentroids<MaskSliceType>(slices[i], GetBackgroundValue(), c);
256     ImagePointType a,b;
257     clitk::PointsUtils<MaskImageType>::Convert2DTo3D(c[1], Trachea, i, a);
258     A.push_back(a);
259     b = a; 
260     b[1] += 50;
261     B.push_back(b);
262   }
263   clitk::WriteListOfLandmarks<MaskImageType>(A, "S1LR_A.txt");
264   clitk::WriteListOfLandmarks<MaskImageType>(B, "S1LR_B.txt");
265
266   // Clone support
267   MaskImagePointer S1R = clitk::Clone<MaskImageType>(S1RL);
268   MaskImagePointer S1L = clitk::Clone<MaskImageType>(S1RL);
269
270   // Right part
271   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B, 
272                                                                     GetBackgroundValue(), 0, -10);
273   S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
274   m_ListOfSupports["S1R"] = S1R;
275
276   // Left part
277   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B, 
278                                                                     GetBackgroundValue(), 0, 10);
279   S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
280   m_ListOfSupports["S1L"] = S1L;
281   StopCurrentStep<MaskImageType>(m_ListOfSupports["S1L"]);
282 }
283 //--------------------------------------------------------------------
284
285
286 //--------------------------------------------------------------------
287 template <class ImageType>
288 void 
289 clitk::ExtractLymphStationsFilter<ImageType>::
290 Support_LeftRight_S2R_S2L()
291 {
292   // ---------------------------------------------------------------------------
293   /* Step : S2RL LeftRight As for lymph node station 4R, 2R includes
294      nodes extending to the left lateral border of the trachea.
295
296      Rod says: "For station 2 there is a shift in the IASLC definition
297      dividing 2R from 2L, from the midline to the left lateral
298      tracheal border. This is represented in the atlas as a vertical
299      line passing tangentially along the left lateral tracheal border
300      "
301   */
302   StartNewStep("[Support] Separate 2R/2L according to Trachea");
303   MaskImagePointer S2R = m_ListOfSupports["S2R"];
304   MaskImagePointer S2L = m_ListOfSupports["S2L"];
305   S2R = LimitsWithTrachea(S2R, 0, 1, -10);
306   S2L = LimitsWithTrachea(S2L, 0, 1, 10);
307   S2R = clitk::AutoCrop<MaskImageType>(S2R, GetBackgroundValue());
308   S2L = clitk::AutoCrop<MaskImageType>(S2L, GetBackgroundValue());
309   m_ListOfSupports["S2R"] = S2R;
310   m_ListOfSupports["S2L"] = S2L;  
311   this->GetAFDB()->template ReleaseImage<MaskImageType>("Trachea");
312 }
313 //--------------------------------------------------------------------
314
315
316 //--------------------------------------------------------------------
317 template <class ImageType>
318 void 
319 clitk::ExtractLymphStationsFilter<ImageType>::
320 Support_LeftRight_S4R_S4L()
321 {
322   // ---------------------------------------------------------------------------
323   /*      
324           The medial border of station 4R is defined as an imaginary line
325           running vertically from the left lateral tracheal border. This is
326           the same medial border as was described for station 2R.
327   */
328   StartNewStep("[Support] Left Right separation of 4R/4L");
329
330   MaskImagePointer S4R = m_ListOfSupports["S4R"];
331   MaskImagePointer S4L = m_ListOfSupports["S4L"];
332   S4R = LimitsWithTrachea(S4R, 0, 1, -10);
333   S4L = LimitsWithTrachea(S4L, 0, 1, 10);
334   m_ListOfSupports["S4R"] = S4R;
335   m_ListOfSupports["S4L"] = S4L;
336 }
337 //--------------------------------------------------------------------
338
339
340 //--------------------------------------------------------------------
341 template <class ImageType>
342 typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
343 clitk::ExtractLymphStationsFilter<ImageType>::
344 LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection, 
345                   double offset) 
346 {
347   MaskImagePointType min, max;
348   GetMinMaxBoundary<MaskImageType>(input, min, max);
349   return LimitsWithTrachea(input, extremaDirection, lineDirection, offset, max[2]);
350 }
351 template <class ImageType>
352 typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
353 clitk::ExtractLymphStationsFilter<ImageType>::
354 LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection, 
355                   double offset, double maxSupPosition)
356 {
357   /*
358     Take the input mask, consider the trachea and limit according to
359     Left border of the trachea. Keep at Left or at Right according to
360     the offset
361   */
362   // Read the trachea
363   MaskImagePointer Trachea = this->GetAFDB()->template GetImage<MaskImageType>("Trachea");
364
365   // Find extrema post positions
366   std::vector<MaskImagePointType> tracheaLeftPositionsA;
367   std::vector<MaskImagePointType> tracheaLeftPositionsB;
368
369   // Crop Trachea only on the Sup-Inf axes, without autocrop
370   //  Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, input, GetBackgroundValue());
371   MaskImagePointType min, max;
372   GetMinMaxBoundary<MaskImageType>(input, min, max);
373   Trachea = clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2, min[2], max[2], 
374                                                         false, GetBackgroundValue()); 
375   
376   // Select the main CCL (because of bronchus)
377   Trachea = SliceBySliceKeepMainCCL<MaskImageType>(Trachea, GetBackgroundValue(), GetForegroundValue());
378
379   // Slice by slice, build the separation line 
380   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(Trachea, 
381                                                                                GetBackgroundValue(), 2, 
382                                                                                extremaDirection, false, // Left
383                                                                                lineDirection, // Vertical line 
384                                                                                -1, // margins 
385                                                                                tracheaLeftPositionsA, 
386                                                                                tracheaLeftPositionsB);
387   // Do not consider trachea above the limit
388   int indexMax=tracheaLeftPositionsA.size();
389   for(uint i=0; i<tracheaLeftPositionsA.size(); i++) {
390     if (tracheaLeftPositionsA[i][2] > maxSupPosition) {
391       indexMax = i;
392       i = tracheaLeftPositionsA.size(); // stop loop
393     }
394   }  
395   tracheaLeftPositionsA.erase(tracheaLeftPositionsA.begin()+indexMax, tracheaLeftPositionsA.end());
396   tracheaLeftPositionsB.erase(tracheaLeftPositionsB.begin()+indexMax, tracheaLeftPositionsB.end());
397
398   // Cut post to this line 
399   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(input, 
400                                                                     tracheaLeftPositionsA,
401                                                                     tracheaLeftPositionsB,
402                                                                     GetBackgroundValue(), 
403                                                                     extremaDirection, offset); 
404   MaskImagePointer output = clitk::AutoCrop<MaskImageType>(input, GetBackgroundValue());
405   return output;
406 }
407 //--------------------------------------------------------------------
408
409
410 //--------------------------------------------------------------------
411 template <class ImageType>
412 void
413 clitk::ExtractLymphStationsFilter<ImageType>::
414 Support_Post_S2S4()
415 {
416   StartNewStep("[Support] Post limits of S2RL, S4RL");
417   
418   double m_ApexOfTheChest = FindApexOfTheChest();
419   
420   // Post limits with Trachea 
421   // MaskImagePointer S1R = m_ListOfSupports["S1R"];
422   // MaskImagePointer S1L = m_ListOfSupports["S1L"];
423   MaskImagePointer S2R = m_ListOfSupports["S2R"];
424   MaskImagePointer S2L = m_ListOfSupports["S2L"];
425   MaskImagePointer S4R = m_ListOfSupports["S4R"];
426   MaskImagePointer S4L = m_ListOfSupports["S4L"];
427   // m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
428   // m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
429   m_ListOfSupports["S2R"] = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest);
430   m_ListOfSupports["S2L"] = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest);
431   m_ListOfSupports["S4R"] = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest);
432   m_ListOfSupports["S4L"] = LimitsWithTrachea(S4L, 1, 0, -10, m_ApexOfTheChest);
433 }
434 //--------------------------------------------------------------------
435
436
437 //--------------------------------------------------------------------
438 template <class ImageType>
439 void
440 clitk::ExtractLymphStationsFilter<ImageType>::
441 Support_Post_S1_S3P()
442 {
443   StartNewStep("[Support] If S1RL and S3P have Sup-Inf overlap, define S1RL posterior limits with S3P anterior limits (post wall trachea)");
444
445   // Get current supports
446   MaskImagePointer S1R = m_ListOfSupports["S1R"];
447   MaskImagePointer S1L = m_ListOfSupports["S1L"];
448
449   // Find extrema ant positions for 3P
450   std::vector<MaskImagePointType> A;
451   std::vector<MaskImagePointType> B;
452
453   // Crop S3P like S1R
454   MaskImagePointer S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
455   S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1R, GetBackgroundValue());
456
457   // Slice by slice, build the separation line 
458   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P, 
459                                                                                GetBackgroundValue(), 2, 
460                                                                                1, true, // Ant-Post
461                                                                                0, // Horizontal line 
462                                                                                0, // margins 
463                                                                                A, B);
464
465   // clitk::WriteListOfLandmarks<MaskImageType>(A, "A-S1S3P.txt");
466   // clitk::WriteListOfLandmarks<MaskImageType>(B, "B-S1S3P.txt");
467
468   // Cut post to this line 
469   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
470                                                                     GetBackgroundValue(), 
471                                                                     1, -10); 
472   
473   // Crop S3P like S1L  (Redo for S1L)
474   S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
475   S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1L, GetBackgroundValue());
476
477   // Slice by slice, build the separation line
478   A.clear();
479   B.clear();
480   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P, 
481                                                                                GetBackgroundValue(), 2, 
482                                                                                1, true, // Ant-Post
483                                                                                0, // Horizontal line 
484                                                                                0, // margins 
485                                                                                A, B);
486   // Cut post to this line 
487   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
488                                                                     GetBackgroundValue(), 
489                                                                     1, -10); 
490
491   // Crop both images
492   S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
493   S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
494
495   StopCurrentStep<MaskImageType>(S1R);
496   
497   m_ListOfSupports["S1R"] = S1R;
498   m_ListOfSupports["S1L"] = S1L;
499 }
500 //--------------------------------------------------------------------
501
502
503 //--------------------------------------------------------------------
504 template <class ImageType>
505 void
506 clitk::ExtractLymphStationsFilter<ImageType>::
507 Support_Post_S1_Ant_S2RL()
508 {
509   StartNewStep("[Support] Define S1RL posterior limits with S2RL anterior limits when overlap");
510
511   // Get RightLung
512   MaskImagePointer RightLung = this->GetAFDB()->template GetImage<MaskImageType>("RightLung");
513
514   // Find common area between S1 and S2
515   MaskImagePointType p_min;
516   MaskImagePointType p_max;
517   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2R"], 
518                                                           GetBackgroundValue(), 2, false, p_max);
519   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S1R"], 
520                                                           GetBackgroundValue(), 2, true, p_min);
521   p_min[2] -= RightLung->GetSpacing()[2]; // consider the slice below (remove lower or equal)
522   p_max[2] += RightLung->GetSpacing()[2]; // consider the slice abov  (remove greater or equal)
523   
524   if (p_min[2] > p_max[2]) {
525
526     // Crop RightLung
527     RightLung = clitk::Clone<MaskImageType>(RightLung);
528     RightLung = clitk::ResizeImageLike<MaskImageType>(RightLung, m_ListOfSupports["S1R"], GetBackgroundValue());
529     RightLung = clitk::CropImageRemoveLowerThan<MaskImageType>(RightLung, 2, p_min[2], true, GetBackgroundValue());
530     RightLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(RightLung, 2, p_max[2], true, GetBackgroundValue());
531
532     // Find extrema ant positions for RightLung
533     std::vector<MaskImagePointType> A;
534     std::vector<MaskImagePointType> B;
535     clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(RightLung, 
536                                                                                  GetBackgroundValue(), 2, 
537                                                                                  1, true, // Ant-Post
538                                                                                  0, // Horizontal line 
539                                                                                  0, // margins 
540                                                                                  A, B);
541     clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1R"],
542                                                                       A, B,
543                                                                       GetBackgroundValue(), 
544                                                                       1, -10); 
545     // I add one pixel to abupt S2R to S1R
546     for(int i=0; i<A.size(); i++) {
547       A[i][1] -= RightLung->GetSpacing()[1];
548       B[i][1] -= RightLung->GetSpacing()[1];
549     }
550     clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2R"],
551                                                                       A, B,
552                                                                       GetBackgroundValue(), 
553                                                                       1, 10);
554   }
555
556   // Get LeftLung, crop
557   MaskImagePointer LeftLung = this->GetAFDB()->template GetImage<MaskImageType>("LeftLung");
558   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2L"], 
559                                                           GetBackgroundValue(), 2, false, p_max);
560   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S1L"], 
561                                                           GetBackgroundValue(), 2, true, p_min);
562   p_min[2] -= LeftLung->GetSpacing()[2]; // consider the slice below (remove lower or equal)
563   p_max[2] += LeftLung->GetSpacing()[2]; // consider the slice abov  (remove greater or equal)  
564   
565   if (p_min[2] > p_max[2]) {
566     LeftLung = clitk::ResizeImageLike<MaskImageType>(LeftLung, m_ListOfSupports["S1L"], GetBackgroundValue());
567     LeftLung = clitk::CropImageRemoveLowerThan<MaskImageType>(LeftLung, 2, p_min[2], true, GetBackgroundValue());
568     LeftLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(LeftLung, 2, p_max[2], true, GetBackgroundValue());
569
570     // Find extrema ant positions for LeftLung
571     std::vector<MaskImagePointType> A;
572     std::vector<MaskImagePointType> B;
573     clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(LeftLung, 
574                                                                                  GetBackgroundValue(), 2, 
575                                                                                  1, true, // Ant-Post
576                                                                                  0, // Horizontal line 
577                                                                                  0, // margins 
578                                                                                  A, B);
579     clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1L"],
580                                                                       A, B,
581                                                                       GetBackgroundValue(), 
582                                                                       1, -10); 
583     // I add one pixel to abupt S2R to S1R
584     for(int i=0; i<A.size(); i++) {
585       A[i][1] -= LeftLung->GetSpacing()[1];
586       B[i][1] -= LeftLung->GetSpacing()[1];
587     }
588     clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2L"],
589                                                                       A, B,
590                                                                       GetBackgroundValue(), 
591                                                                       1, 10); 
592   }
593 }
594 //--------------------------------------------------------------------