- StartNewStep("[Station8] Ant limits with S7 above Carina");
- /*
- Anteriorly, it is in contact with Station 7 and the
- left main stem bronchus in its superior aspect (Fig. 3C–H) and
- with the heart more inferiorly.
-
- 1) line post wall bronchi (S7), till originRMLB
- - LUL bronchus : to detect in trachea. But not needed here ??
- 2) heart ! -> not delineated.
- ==> below S7, crop CT not to far away (ant), then try with threshold
-
- 1) ==> how to share with S7 ? Prepare both support at the same time !
- NEED vector of initial support for each station ? No -> map if it exist before, take it !!
-
- */
-
- // Ant limit from carina (start) to end of S7 = originRMLB
- // Get Trachea
- MaskImagePointer Trachea = GetAFDB()->template GetImage<MaskImageType>("Trachea");
-
- MaskImagePointer m_Working_Trachea =
- clitk::CropImageAbove<MaskImageType>(Trachea, 2, m_CarinaZ, true, // AutoCrop
- GetBackgroundValue());
-
- // Seprate into two main bronchi
- MaskImagePointer LeftBronchus;
- MaskImagePointer RightBronchus;
-
- // Labelize and consider the two first (main) labels
- m_Working_Trachea = Labelize<MaskImageType>(m_Working_Trachea, 0, true, 1);
-
- // Carina position must at the first slice that separate the two
- // main bronchus (not superiorly). We thus first check that the
- // upper slice is composed of at least two labels
- typedef itk::ImageSliceIteratorWithIndex<MaskImageType> SliceIteratorType;
- SliceIteratorType iter(m_Working_Trachea, m_Working_Trachea->GetLargestPossibleRegion());
- iter.SetFirstDirection(0);
- iter.SetSecondDirection(1);
- iter.GoToReverseBegin(); // Start from the end (because image is IS not SI)
- int maxLabel=0;
- while (!iter.IsAtReverseEndOfSlice()) {
- while (!iter.IsAtReverseEndOfLine()) {
- if (iter.Get() > maxLabel) maxLabel = iter.Get();
- --iter;
- }
- iter.PreviousLine();
- }
- if (maxLabel < 2) {
- clitkExceptionMacro("First slice form Carina does not seems to seperate the two main bronchus. Abort");
- }
-
- // Compute 3D centroids of both parts to identify the left from the
- // right bronchus
- std::vector<ImagePointType> c;
- clitk::ComputeCentroids<MaskImageType>(m_Working_Trachea, GetBackgroundValue(), c);
- ImagePointType C1 = c[1];
- ImagePointType C2 = c[2];
-
- ImagePixelType leftLabel;
- ImagePixelType rightLabel;
- if (C1[0] < C2[0]) { leftLabel = 1; rightLabel = 2; }
- else { leftLabel = 2; rightLabel = 1; }
-
- // Select LeftLabel (set one label to Backgroundvalue)
- LeftBronchus =
- SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea,
- rightLabel, GetBackgroundValue(), false);
- RightBronchus =
- SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea,
- leftLabel, GetBackgroundValue(), false);
- // Crop images
- LeftBronchus = clitk::AutoCrop<MaskImageType>(LeftBronchus, GetBackgroundValue());
- RightBronchus = clitk::AutoCrop<MaskImageType>(RightBronchus, GetBackgroundValue());
-
- // Insert int AFDB if need after
- GetAFDB()->template SetImage <MaskImageType>("LeftBronchus", "seg/leftBronchus.mhd",
- LeftBronchus, true);
- GetAFDB()->template SetImage <MaskImageType>("RightBronchus", "seg/rightBronchus.mhd",
- RightBronchus, true);
-
- // Now crop below OriginOfRightMiddleLobeBronchusZ
- // It is not done before to keep entire bronchi.
-
- MaskImagePointer OriginOfRightMiddleLobeBronchus =
- GetAFDB()->template GetImage<MaskImageType>("OriginOfRightMiddleLobeBronchus");
- std::vector<MaskImagePointType> centroids;
- clitk::ComputeCentroids<MaskImageType>(OriginOfRightMiddleLobeBronchus, GetBackgroundValue(), centroids);
- m_OriginOfRightMiddleLobeBronchusZ = centroids[1][2];
- // add one slice to include carina ?
- m_OriginOfRightMiddleLobeBronchusZ += LeftBronchus->GetSpacing()[2];
- // We dont need Carina structure from now
- OriginOfRightMiddleLobeBronchus->Delete();
-
- LeftBronchus =
- clitk::CropImageBelow<MaskImageType>(LeftBronchus, 2,
- m_OriginOfRightMiddleLobeBronchusZ,
- true, // AutoCrop
- GetBackgroundValue());
- RightBronchus =
- clitk::CropImageBelow<MaskImageType>(RightBronchus, 2,
- m_OriginOfRightMiddleLobeBronchusZ,
- true, // AutoCrop
- GetBackgroundValue());
-
- // Search for points that are the most left/post/ant and most
- // right/post/ant of the left and right bronchus
- // 15 = not 15 mm more distance than the middle point.
- FindExtremaPointsInBronchus(LeftBronchus, 0, 10, m_RightMostInLeftBronchus,
- m_AntMostInLeftBronchus, m_PostMostInLeftBronchus);
- FindExtremaPointsInBronchus(RightBronchus, 1, 10, m_LeftMostInRightBronchus,
- m_AntMostInRightBronchus, m_PostMostInRightBronchus);
-
- // DEBUG : write the list of points
- ListOfPointsType v;
- v.reserve(m_RightMostInLeftBronchus.size()+m_AntMostInLeftBronchus.size()+
- m_PostMostInLeftBronchus.size());
- v.insert(v.end(), m_RightMostInLeftBronchus.begin(), m_RightMostInLeftBronchus.end() );
- v.insert(v.end(), m_AntMostInLeftBronchus.begin(), m_AntMostInLeftBronchus.end() );
- v.insert(v.end(), m_PostMostInLeftBronchus.begin(), m_PostMostInLeftBronchus.end() );
- clitk::WriteListOfLandmarks<MaskImageType>(v, "LeftBronchusPoints.txt");
-
- v.clear();
- v.reserve(m_LeftMostInRightBronchus.size()+m_AntMostInRightBronchus.size()+
- m_PostMostInRightBronchus.size());
- v.insert(v.end(), m_LeftMostInRightBronchus.begin(), m_LeftMostInRightBronchus.end() );
- v.insert(v.end(), m_AntMostInRightBronchus.begin(), m_AntMostInRightBronchus.end() );
- v.insert(v.end(), m_PostMostInRightBronchus.begin(), m_PostMostInRightBronchus.end() );
- clitk::WriteListOfLandmarks<MaskImageType>(v, "RightBronchusPoints.txt");
-
-
- // Now uses these points to limit, slice by slice
- // line is mainly horizontal, so mainDirection=1
- writeImage<MaskImageType>(m_Working_Support, "before.mhd");
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
- m_PostMostInLeftBronchus,
- m_PostMostInRightBronchus,
- GetBackgroundValue(), 1, 10);
- writeImage<MaskImageType>(m_Working_Support, "after.mhd");
-
- // Keep main 3D CCL :
- m_Working_Support = Labelize<MaskImageType>(m_Working_Support, 0, false, 10);
- m_Working_Support = KeepLabels<MaskImageType>(m_Working_Support,
- GetBackgroundValue(),
- GetForegroundValue(), 1, 1, true);
-
- // Autocrop
- m_Working_Support = clitk::AutoCrop<MaskImageType>(m_Working_Support, GetBackgroundValue());
-
- // End of step
- StopCurrentStep<MaskImageType>(m_Working_Support);
- // m_ListOfStations["8"] = m_Working_Support;
-
-}
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_LR_Limits()
-{
-
- //--------------------------------------------------------------------
- StartNewStep("[Station8] Ant part (not post to Esophagus)");