+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
+ p_LeftEso,p_LeftAorta,
+ GetBackgroundValue(), 0, -10);
+ // END
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["8"] = m_Working_Support;
+ return;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStation_8_LR_Limits()
+{
+
+ //--------------------------------------------------------------------
+ StartNewStep("[Station8] Left and Right limits arround esophagus with lines from VertebralBody-Aorta-Esophagus");
+
+ // Estract slices for current support for slice by slice processing
+ std::vector<typename MaskSliceType::Pointer> slices;
+ clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
+
+ // Dilate the Esophagus to consider a margins around
+ MaskImagePointType radiusInMM = GetEsophagusDiltationForAnt();
+ m_Esophagus = clitk::Dilate<MaskImageType>(m_Esophagus, radiusInMM,
+ GetBackgroundValue(), GetForegroundValue(), true);
+ // m_Esophagus = EnlargeEsophagusDilatationRadiusInferiorly(m_Esophagus);
+
+ // Remove what is outside the mediastinum in this enlarged Esophagus -> it allows to select
+ // 'better' extrema points (not too post).
+ MaskImagePointer Lungs = GetAFDB()->template GetImage<MaskImageType>("Lungs");
+ clitk::AndNot<MaskImageType>(m_Esophagus, Lungs, GetBackgroundValue());
+ GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
+
+ // Estract slices of Esophagus (resize like support before to have the same set of slices)
+ MaskImagePointer EsophagusForSlice = clitk::ResizeImageLike<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue());
+ std::vector<typename MaskSliceType::Pointer> eso_slices;
+ clitk::ExtractSlices<MaskImageType>(EsophagusForSlice, 2, eso_slices);
+
+ // Estract slices of Vertebral (resize like support before to have the same set of slices)
+ MaskImagePointer VertebralBody = GetAFDB()->template GetImage<MaskImageType>("VertebralBody");
+ VertebralBody = clitk::ResizeImageLike<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
+ std::vector<typename MaskSliceType::Pointer> vert_slices;
+ clitk::ExtractSlices<MaskImageType>(VertebralBody, 2, vert_slices);
+
+ // Estract slices of Aorta (resize like support before to have the same set of slices)
+ MaskImagePointer Aorta = GetAFDB()->template GetImage<MaskImageType>("Aorta");
+ Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, m_Working_Support, GetBackgroundValue());
+ std::vector<typename MaskSliceType::Pointer> aorta_slices;
+ clitk::ExtractSlices<MaskImageType>(Aorta, 2, aorta_slices);
+
+ // Extract slices of Mediastinum (resize like support before to have the same set of slices)
+ m_Mediastinum = GetAFDB()->template GetImage<MaskImageType>("Mediastinum");
+ m_Mediastinum = clitk::ResizeImageLike<MaskImageType>(m_Mediastinum, m_Working_Support, GetBackgroundValue());
+ std::vector<typename MaskSliceType::Pointer> mediast_slices;
+ clitk::ExtractSlices<MaskImageType>(m_Mediastinum, 2, mediast_slices);
+
+ // List of points
+ std::vector<MaskImagePointType> p_MostLeftVertebralBody;
+ std::vector<MaskImagePointType> p_MostRightVertebralBody;
+ std::vector<MaskImagePointType> p_MostLeftAorta;
+ std::vector<MaskImagePointType> p_MostLeftEsophagus;
+
+ /*
+ In the following, we search for the LeftRight limits. We search
+ for the most Right points in Esophagus and in VertebralBody and
+ consider a line between those to most right points. All points in
+ the support which are most right to this line are discarded. Same
+ for the left part. The underlying assumption is that the support
+ is concave between Eso/VertebralBody. Esophagus is a bit
+ dilatated. On VertebralBody we go right (or left) until we reach
+ the lung (but no more 20 mm).
+ */
+
+ // Temporary 3D point
+ MaskImagePointType p;
+
+ // Loop slices
+ for(uint i=0; i<slices.size() ; i++) {
+ // Declare all needed 2D points (sp = slice point)
+ typename MaskSliceType::PointType sp_MostRightVertebralBody;
+ typename MaskSliceType::PointType sp_MostLeftVertebralBody;
+ typename MaskSliceType::PointType sp_MostLeftAorta;
+ typename MaskSliceType::PointType sp_temp;
+ typename MaskSliceType::PointType sp_MostLeftEsophagus;
+
+ // Right is at left on screen, coordinate decrease
+ // Left is at right on screen, coordinate increase
+
+ /* -------------------------------------------------------------------------------------
+ Find most Left point in VertebralBody. Consider only the
+ horizontal line which is 'DistanceMaxToAnteriorPartOfTheSpine'
+ away from the most ant point.
+ */
+ typename MaskSliceType::PointType sp_MostAntVertebralBody;
+ bool found = false;
+ int j=i;
+ while (!found) {
+ found = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[j], GetBackgroundValue(), 1, true, sp_MostAntVertebralBody);
+ if (!found) {
+ // It should not happen ! But sometimes, a contour is missing or
+ // the VertebralBody is not delineated enough inferiorly ... in
+ // those cases, we consider the first found slice.
+ std::cerr << "No foreground pixels in this VertebralBody slices !?? I try with the previous/next slice" << std::endl;
+ j++;
+ }
+ }
+ sp_MostAntVertebralBody[1] += GetDistanceMaxToAnteriorPartOfTheSpine(); // Consider offset
+
+ // Crop the vertebralbody below this most post line
+ vert_slices[j] =
+ clitk::CropImageAbove<MaskSliceType>(vert_slices[j], 1, sp_MostAntVertebralBody[1], false, GetBackgroundValue());
+ vert_slices[j] =
+ clitk::ResizeImageLike<MaskSliceType>(vert_slices[j], aorta_slices[i], GetBackgroundValue());
+ // writeImage<MaskSliceType>(vert_slices[i], "vert-slice-"+toString(i)+".mhd");
+
+ // Find first point not in mediastinum
+ clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[j], GetBackgroundValue(), 0, false, sp_MostLeftVertebralBody);
+ sp_MostLeftVertebralBody = clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, false, sp_MostLeftVertebralBody, GetBackgroundValue(), 30);
+ sp_MostLeftVertebralBody[0] += 2; // 2mm margin
+ clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[j], GetBackgroundValue(), 0, true, sp_MostRightVertebralBody);
+ sp_MostRightVertebralBody = clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, true, sp_MostRightVertebralBody, GetBackgroundValue(),30);
+ sp_MostRightVertebralBody[0] -= 2; // 2 mm margin
+
+ // Convert 2D points into 3D
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostRightVertebralBody, VertebralBody, i, p);
+ p_MostRightVertebralBody.push_back(p);
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
+ p_MostLeftVertebralBody.push_back(p);
+
+ /* -------------------------------------------------------------------------------------
+ Find most Left point in Esophagus
+ */
+ found = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftEsophagus);
+ if (!found) { // No more Esophagus, I remove the previous point
+
+ // if (p_MostLeftEsophagus.size() < 1) {
+ p_MostLeftVertebralBody.pop_back();
+ // }
+ // else {
+ // // Consider the previous point
+ // p = p_MostLeftEsophagus.back();
+ // p_MostLeftEsophagus.push_back(p);
+ // sp_MostLeftEsophagus = sp_temp; // Retrieve previous 2D position
+ // found = true;
+ // }
+ }
+ else {
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftEsophagus, EsophagusForSlice, i, p);
+ p_MostLeftEsophagus.push_back(p);
+ // sp_temp = sp_MostLeftEsophagus; // Store previous 2D position
+ }
+
+ /* -------------------------------------------------------------------------------------
+ Find most Left point in Aorta
+ */
+ if (found) {
+ clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftAorta);
+ sp_MostLeftAorta = clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, false, sp_MostLeftAorta, GetBackgroundValue(), 10);
+ typename MaskSliceType::PointType temp=sp_MostLeftEsophagus;
+ temp[0] -= 10;
+ if (clitk::IsOnTheSameLineSide(sp_MostLeftAorta, sp_MostLeftVertebralBody, sp_MostLeftEsophagus, temp)) {
+ // sp_MostLeftAorta is on the same side than temp (at Right) -> ignore Aorta
+ sp_MostLeftAorta = sp_MostLeftEsophagus;
+ }
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftAorta, Aorta, i, p);
+ p_MostLeftAorta.push_back(p);
+ }
+
+ } // End of slice loop
+
+ clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftVertebralBody, "S8-MostLeft-VB-points.txt");
+ clitk::WriteListOfLandmarks<MaskImageType>(p_MostRightVertebralBody, "S8-MostRight-VB-points.txt");
+ clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftAorta, "S8-MostLeft-Aorta-points.txt");
+ clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftEsophagus, "S8-MostLeft-eso-points.txt");
+
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
+ p_MostLeftVertebralBody, p_MostLeftAorta,
+ GetBackgroundValue(), 0, -10);
+
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
+ p_MostLeftAorta, p_MostLeftEsophagus,
+ GetBackgroundValue(), 0, -10);
+
+ // END
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["8"] = m_Working_Support;
+ return;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStation_8_Remove_Structures()
+{
+
+ //--------------------------------------------------------------------
+ StartNewStep("[Station8] remove some structures");
+
+ Remove_Structures("Aorta");
+ Remove_Structures("Esophagus");
+