From e213f9d30797737c2aa451d54cb5cb64d16e580a Mon Sep 17 00:00:00 2001 From: David Sarrut Date: Fri, 3 Feb 2012 08:06:43 +0100 Subject: [PATCH] Moved from repository clitk to clitk.private/tests_dav --- segmentation/clitkExtractLymphStation_1RL.txx | 185 -- segmentation/clitkExtractLymphStation_2RL.txx | 196 --- segmentation/clitkExtractLymphStation_3A.txx | 261 --- segmentation/clitkExtractLymphStation_3P.txx | 282 ---- segmentation/clitkExtractLymphStation_4RL.txx | 157 -- segmentation/clitkExtractLymphStation_5.txx | 94 -- segmentation/clitkExtractLymphStation_6.txx | 54 - segmentation/clitkExtractLymphStation_7.txx | 566 ------- segmentation/clitkExtractLymphStation_8.txx | 549 ------ .../clitkExtractLymphStation_Supports.txx | 594 ------- segmentation/clitkExtractLymphStations.cxx | 46 - segmentation/clitkExtractLymphStations.ggo | 48 - .../clitkExtractLymphStationsFilter.h | 325 ---- .../clitkExtractLymphStationsFilter.txx | 1481 ----------------- .../clitkExtractLymphStationsGenericFilter.h | 80 - ...clitkExtractLymphStationsGenericFilter.txx | 169 -- 16 files changed, 5087 deletions(-) delete mode 100644 segmentation/clitkExtractLymphStation_1RL.txx delete mode 100644 segmentation/clitkExtractLymphStation_2RL.txx delete mode 100644 segmentation/clitkExtractLymphStation_3A.txx delete mode 100644 segmentation/clitkExtractLymphStation_3P.txx delete mode 100644 segmentation/clitkExtractLymphStation_4RL.txx delete mode 100644 segmentation/clitkExtractLymphStation_5.txx delete mode 100644 segmentation/clitkExtractLymphStation_6.txx delete mode 100644 segmentation/clitkExtractLymphStation_7.txx delete mode 100644 segmentation/clitkExtractLymphStation_8.txx delete mode 100644 segmentation/clitkExtractLymphStation_Supports.txx delete mode 100644 segmentation/clitkExtractLymphStations.cxx delete mode 100644 segmentation/clitkExtractLymphStations.ggo delete mode 100644 segmentation/clitkExtractLymphStationsFilter.h delete mode 100644 segmentation/clitkExtractLymphStationsFilter.txx delete mode 100644 segmentation/clitkExtractLymphStationsGenericFilter.h delete mode 100644 segmentation/clitkExtractLymphStationsGenericFilter.txx diff --git a/segmentation/clitkExtractLymphStation_1RL.txx b/segmentation/clitkExtractLymphStation_1RL.txx deleted file mode 100644 index 6758ab8..0000000 --- a/segmentation/clitkExtractLymphStation_1RL.txx +++ /dev/null @@ -1,185 +0,0 @@ - - -// vtk -#include -#include -#include - -// clitk -#include "clitkMeshToBinaryImageFilter.h" - -// itk -#include - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_1RL_SetDefaultValues() -{ - -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_1RL() -{ - if ((!CheckForStation("1R")) && (!CheckForStation("1L"))) return; - - StartNewStep("Stations 1RL"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 1RL] Get the current 1RL suppport"); - m_ListOfStations["1R"] = m_ListOfSupports["S1R"]; - m_ListOfStations["1L"] = m_ListOfSupports["S1L"]; - StopCurrentStep(m_ListOfStations["1R"]); - - // Specific processes - ExtractStation_1RL_Ant_Limits(); - ExtractStation_1RL_Post_Limits(); - m_Working_Support = m_ListOfStations["1R"]; - Remove_Structures(" 1R", "ScaleneMuscleAnt"); - Remove_Structures(" 1R", "RightCommonCarotidArtery"); - m_Working_Support = m_ListOfStations["1L"]; - Remove_Structures(" 1L", "ScaleneMuscleAnt"); - Remove_Structures(" 1L", "LeftCommonCarotidArtery"); - - // Generic RelativePosition processes - m_ListOfStations["1R"] = this->ApplyRelativePositionList("Station_1R", m_ListOfStations["1R"]); - m_ListOfStations["1L"] = this->ApplyRelativePositionList("Station_1L", m_ListOfStations["1L"]); - - // Store image filenames into AFDB - writeImage(m_ListOfStations["1R"], "seg/Station1R.mhd"); - writeImage(m_ListOfStations["1L"], "seg/Station1L.mhd"); - GetAFDB()->SetImageFilename("Station1R", "seg/Station1R.mhd"); - GetAFDB()->SetImageFilename("Station1L", "seg/Station1L.mhd"); - WriteAFDB(); - StopSubStep(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_1RL_Ant_Limits() -{ - // ----------------------------------------------------- - StartNewStep("[Station 1RL] anterior limits with Trachea and Thyroid"); - - /* - The idea here it to consider the most anterior points int the - Trachea or the Thyroid and cut all parts anterior to it. This is - an heuristic, not written explicitely in the articles. - */ - - MaskImagePointer Trachea = GetAFDB()->template GetImage("Trachea"); - MaskImagePointer Thyroid = GetAFDB()->template GetImage("Thyroid"); - MaskImagePointer S1R = m_ListOfStations["1R"]; - MaskImagePointer S1L = m_ListOfStations["1L"]; - MaskImagePointer support = m_ListOfSupports["S1RL"]; - - // Resize like S1R. Warning: for Thyroid, only Right part is thus - // taken into account - Trachea = clitk::ResizeImageLike(Trachea, S1R, GetBackgroundValue()); - Thyroid = clitk::ResizeImageLike(Thyroid, S1R, GetBackgroundValue()); - - // Search for most Ant point, slice by slice, between Trachea and Thyroid - std::vector Trachea_slices; - clitk::ExtractSlices(Trachea, 2, Trachea_slices); - std::vector Thyroid_slices; - clitk::ExtractSlices(Thyroid, 2, Thyroid_slices); - std::vector A; - std::vector B; - for(uint i=0; i(Trachea_slices[i], - GetBackgroundValue(), - 1, true, p); - FindExtremaPointInAGivenDirection(Thyroid_slices[i], - GetBackgroundValue(), - 1, true, q); - if (q[1] < p[1]) p = q; // Now p is the most ant. - // Add a little margin, 3mm - p[1] -= 3; - // Convert in 3D - ImagePointType x; //dummy - A.push_back(x); - B.push_back(x); - clitk::PointsUtils::Convert2DTo3D(p, Trachea, i, A[i]); - p[0] += 10; - clitk::PointsUtils::Convert2DTo3D(p, Trachea, i, B[i]); - } - - // Remove anterior to this line (keep +10 offset) - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1R, A, B, - GetBackgroundValue(), 1, +10); - m_ListOfStations["1R"] = S1R; - - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1L, A, B, - GetBackgroundValue(), 1, +10); - StopCurrentStep(S1L); - m_ListOfStations["1L"] = S1L; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_1RL_Post_Limits() -{ - // ----------------------------------------------------- - StartNewStep("[Station 1RL] Posterior limits with VertebralArtery"); - - MaskImagePointer VertebralArtery = GetAFDB()->template GetImage("VertebralArtery"); - MaskImagePointer S1R = m_ListOfStations["1R"]; - MaskImagePointer S1L = m_ListOfStations["1L"]; - - // Resize like S1R. - VertebralArtery = clitk::ResizeImageLike(VertebralArtery, S1R, GetBackgroundValue()); - - // Search for most Ant point - std::vector VertebralArtery_slices; - clitk::ExtractSlices(VertebralArtery, 2, VertebralArtery_slices); - std::vector A; - std::vector B; - for(uint i=0; i(VertebralArtery_slices[i], - GetBackgroundValue(), - 1, false, p); - // Add a little margin ? No. - //p[1] += 0; - //DD(p); - // Convert in 3D - ImagePointType x; //dummy - A.push_back(x); - B.push_back(x); - clitk::PointsUtils::Convert2DTo3D(p, VertebralArtery, i, A[i]); - p[0] += 10; - clitk::PointsUtils::Convert2DTo3D(p, VertebralArtery, i, B[i]); - } - - // Remove anterior to this line (keep -10 offset) - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1R, A, B, - GetBackgroundValue(), 1, -10); - m_ListOfStations["1R"] = S1R; - - // Remove anterior to this line (keep -10 offset) - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1L, A, B, - GetBackgroundValue(), 1, -10); - StopCurrentStep(S1L); - m_ListOfStations["1L"] = S1L; -} -//-------------------------------------------------------------------- - - diff --git a/segmentation/clitkExtractLymphStation_2RL.txx b/segmentation/clitkExtractLymphStation_2RL.txx deleted file mode 100644 index 7332dee..0000000 --- a/segmentation/clitkExtractLymphStation_2RL.txx +++ /dev/null @@ -1,196 +0,0 @@ - - -// vtk -#include -#include -#include - -// clitk -#include "clitkMeshToBinaryImageFilter.h" - -// itk -#include - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_2RL_SetDefaultValues() -{ -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_2RL() -{ - if ((!CheckForStation("2R")) && (!CheckForStation("2L"))) return; - - StartNewStep("Stations 2RL"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 2RL] Get the current 2RL suppport"); - m_ListOfStations["2R"] = m_ListOfSupports["S2R"]; - m_ListOfStations["2L"] = m_ListOfSupports["S2L"]; - StopCurrentStep(m_ListOfStations["2R"]); - - // Do the same limits for R & L - m_Working_Support = m_ListOfStations["2R"]; - ExtractStation_2RL_Ant_Limits("2R"); - ExtractStation_2RL_Remove_Structures(" 2R"); - m_ListOfStations["2R"] = m_Working_Support; - - m_Working_Support = m_ListOfStations["2L"]; - ExtractStation_2RL_Ant_Limits("2L"); - ExtractStation_2RL_Remove_Structures(" 2L"); - m_ListOfStations["2L"] = m_Working_Support; - - // Remove superior part to BrachioCephalicVein (used then by RelPos) - ExtractStation_2RL_Cut_BrachioCephalicVein_superiorly_when_it_split(); - - // Generic RelativePosition processes - m_ListOfStations["2R"] = this->ApplyRelativePositionList("Station_2R", m_ListOfStations["2R"]); - m_ListOfStations["2L"] = this->ApplyRelativePositionList("Station_2L", m_ListOfStations["2L"]); - - // Store image filenames into AFDB - writeImage(m_ListOfStations["2R"], "seg/Station2R.mhd"); - writeImage(m_ListOfStations["2L"], "seg/Station2L.mhd"); - GetAFDB()->SetImageFilename("Station2R", "seg/Station2R.mhd"); - GetAFDB()->SetImageFilename("Station2L", "seg/Station2L.mhd"); - WriteAFDB(); - StopSubStep(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_2RL_Ant_Limits(std::string s) -{ - // ----------------------------------------------------- - StartNewStep("[Station "+s+"] Ant limits with vessels centroids"); - - // WARNING, as I used "And" after, empty slice in binarizedContour - // lead to remove part of the support, although we want to keep - // unchanged. So we decide to ResizeImageLike but pad with - // ForegroundValue instead of BG - - // Get or compute the binary mask that separate Ant/Post part - // according to vessels - MaskImagePointer binarizedContour = FindAntPostVessels2(); - binarizedContour = clitk::ResizeImageLike(binarizedContour, - m_Working_Support, - GetForegroundValue()); - // remove from support - typedef clitk::BooleanOperatorLabelImageFilter BoolFilterType; - typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); - boolFilter->InPlaceOn(); - boolFilter->SetInput1(m_Working_Support); - boolFilter->SetInput2(binarizedContour); - boolFilter->SetBackgroundValue1(GetBackgroundValue()); - boolFilter->SetBackgroundValue2(GetBackgroundValue()); - boolFilter->SetOperationType(BoolFilterType::And); - boolFilter->Update(); - m_Working_Support = boolFilter->GetOutput(); - - // End - StopCurrentStep(m_Working_Support); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_2RL_Cut_BrachioCephalicVein_superiorly_when_it_split() -{ - // ----------------------------------------------------- - StartNewStep("[Station 2RL] Cut BrachioCephalicVein superiorly (when it split)"); - - // Get BrachioCephalicVein - MaskImagePointer BrachioCephalicVein = GetAFDB()->template GetImage("BrachioCephalicVein"); - - // Remove the part superior to the slice where BrachioCephalicVein - // divide in two CCL - std::vector BCV_slices; - clitk::ExtractSlices(BrachioCephalicVein, 2, BCV_slices); - bool stop = false; - uint i=0; - while (!stop) { - // Count the number of CCL - int nb; - clitk::LabelizeAndCountNumberOfObjects(BCV_slices[i], GetBackgroundValue(), true, 1, nb); - if (nb>1) stop = true; - i++; - } - // Convert slice into coordinate - MaskImagePointType p; - MaskImageIndexType index; - index[0] = index[1] = 0; - index[2] = i; - BrachioCephalicVein->TransformIndexToPhysicalPoint(index, p); - BrachioCephalicVein = - clitk::CropImageRemoveGreaterThan(BrachioCephalicVein, 2, - p[2], true, - GetBackgroundValue()); - - // Now, insert this image in the AFDB (but do not store on disk) - GetAFDB()->template SetImage("BrachioCephalicVein_ForS2RL", "bidon", - BrachioCephalicVein, false); - // End - StopCurrentStep(BrachioCephalicVein); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -// Build a vtk mesh from a list of slice number/closed-contours -template -vtkSmartPointer -clitk::ExtractLymphStationsFilter:: -Build3DMeshFrom2DContour(const std::vector & points) -{ - // create a contour, polydata. - vtkSmartPointer mesh = vtkSmartPointer::New(); - mesh->Allocate(); //for cell structures - mesh->SetPoints(vtkPoints::New()); - vtkIdType ids[2]; - int point_number = points.size(); - for (unsigned int i=0; iGetPoints()->InsertNextPoint(points[i][0],points[i][1],points[i][2]); - ids[0]=i; - ids[1]=(ids[0]+1)%point_number; //0-1,1-2,...,n-1-0 - mesh->GetLines()->InsertNextCell(2,ids); - } - // Return - return mesh; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_2RL_Remove_Structures(std::string s) -{ - // m_Working_Support must be set - Remove_Structures(s, "BrachioCephalicVein"); - Remove_Structures(s, "BrachioCephalicArtery"); - Remove_Structures(s, "LeftCommonCarotidArtery"); - Remove_Structures(s, "RightCommonCarotidArtery"); - Remove_Structures(s, "LeftSubclavianArtery"); - Remove_Structures(s, "RightSubclavianArtery"); - Remove_Structures(s, "Thyroid"); - Remove_Structures(s, "Aorta"); -} -//-------------------------------------------------------------------- - - diff --git a/segmentation/clitkExtractLymphStation_3A.txx b/segmentation/clitkExtractLymphStation_3A.txx deleted file mode 100644 index 50e3948..0000000 --- a/segmentation/clitkExtractLymphStation_3A.txx +++ /dev/null @@ -1,261 +0,0 @@ - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_SetDefaultValues() -{ -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3A() -{ - if (!CheckForStation("3A")) return; - - StartNewStep("Station 3A"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 3A] Get the current 3A suppport"); - m_Working_Support = m_ListOfSupports["S3A"]; - m_ListOfStations["3A"] = m_Working_Support; - StopCurrentStep(m_Working_Support); - - ExtractStation_3A_Post_Left_Limits_With_Aorta_S5_Support(); - ExtractStation_3A_Post_Limits_With_Dilated_Aorta_S6_Support(); - ExtractStation_3A_AntPost_Superiorly(); - ExtractStation_3A_Remove_Structures(); - - // Generic RelativePosition processes - m_ListOfStations["3A"] = this->ApplyRelativePositionList("Station_3A", m_ListOfStations["3A"]); - - // Keep a single CCL - m_ListOfStations["3A"] = - clitk::SliceBySliceKeepMainCCL(m_ListOfStations["3A"], - GetBackgroundValue(), - GetForegroundValue()); - - // Store image filenames into AFDB - writeImage(m_ListOfStations["3A"], "seg/Station3A.mhd"); - GetAFDB()->SetImageFilename("Station3A", "seg/Station3A.mhd"); - WriteAFDB(); - StopSubStep(); -} -//-------------------------------------------------------------------- - - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_Post_Left_Limits_With_Aorta_S5_Support() -{ - StartNewStep("[Station 3A] Post limits in S5 support according to Aorta"); - - // Consider Aorta, remove Left/Post part ; only around S5 - // Get S5 support and Aorta - MaskImagePointer S5 = m_ListOfSupports["S5"]; - MaskImagePointer Aorta = GetAFDB()->template GetImage ("Aorta"); - Aorta = clitk::ResizeImageLike(Aorta, S5, GetBackgroundValue()); - - // Inferiorly, Aorta has two CCL that merge into a single one when - // S6 appears. Loop on Aorta slices, select the most ant one, detect - // the most ant point. - - - - // ====> TO BE CHANGED USING AscendingAorta and DescendingAorta - - - - std::vector slices; - clitk::ExtractSlices(Aorta, 2, slices); - std::vector points; - for(uint i=0; i(slices[i], GetBackgroundValue(), false, 1); - std::vector c; - clitk::ComputeCentroids(slices[i], GetBackgroundValue(), c); - assert(c.size() == 3); // only 2 CCL - typename MaskSliceType::PixelType l; - if (c[1][1] > c[2][1]) { // We will remove the label=1 - l = 1; - } - else { - l = 2;// We will remove the label=2 - } - slices[i] = clitk::SetBackground(slices[i], slices[i], l, - GetBackgroundValue(), true); - - // Detect the most ant point - MaskSlicePointType p; - MaskImagePointType pA; - clitk::FindExtremaPointInAGivenDirection(slices[i], GetBackgroundValue(), 1, true, p); - // Set the X coordinate to the X coordinate of the centroid - if (l==1) p[0] = c[2][0]; - else p[0] = c[1][0]; - - // Convert in 3D and store - clitk::PointsUtils::Convert2DTo3D(p, Aorta, i, pA); - points.push_back(pA); - } - - // DEBUG - // MaskImagePointer o = clitk::JoinSlices(slices, Aorta, 2); - // writeImage(o, "o.mhd"); - // clitk::WriteListOfLandmarks(points, "Ant-Aorta.txt"); - - // Remove Post/Left to this point - m_Working_Support = - clitk::SliceBySliceSetBackgroundFromPoints(m_Working_Support, - GetBackgroundValue(), 2, - points, - true, // Set BG if X greater than point[x], and - true); // if Y greater than point[y] - - StopCurrentStep(m_Working_Support); - m_ListOfStations["3A"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_Post_Limits_With_Dilated_Aorta_S6_Support() -{ - StartNewStep("[Station 3A] Post limits with dilated Aorta"); - - // Consider Aorta - MaskImagePointer Aorta = GetAFDB()->template GetImage ("Aorta"); - - // Limits the support to S6 - MaskImagePointer S6 = m_ListOfSupports["S6"]; - Aorta = clitk::ResizeImageLike(Aorta, S6, GetBackgroundValue()); - - // Extend 1cm anteriorly - MaskImagePointType radius; // in mm - radius[0] = 10; - radius[1] = 10; - radius[2] = 0; // required - Aorta = clitk::Dilate(Aorta, radius, GetBackgroundValue(), GetForegroundValue(), false); - - // Now, insert this image in the AFDB (but do not store on disk) - GetAFDB()->template SetImage("Aorta_Dilated_Anteriorly", "seg/Aorta_Dilated_Anteriorly.mha", Aorta, false); - writeImage(Aorta, "seg/Aorta_Dilated_Anteriorly.mha"); - GetAFDB()->Write(); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["3A"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_AntPost_Superiorly() -{ - StartNewStep("[Station 3A] Post limits superiorly"); - - // Get or compute the binary mask that separate Ant/Post part - // according to vessels - MaskImagePointer binarizedContour = FindAntPostVessels2(); - binarizedContour = clitk::ResizeImageLike(binarizedContour, - m_Working_Support, - GetBackgroundValue()); - - // remove from support - typedef clitk::BooleanOperatorLabelImageFilter BoolFilterType; - typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); - boolFilter->InPlaceOn(); - boolFilter->SetInput1(m_Working_Support); - boolFilter->SetInput2(binarizedContour); - boolFilter->SetBackgroundValue1(GetBackgroundValue()); - boolFilter->SetBackgroundValue2(GetBackgroundValue()); - boolFilter->SetOperationType(BoolFilterType::AndNot); - boolFilter->Update(); - m_Working_Support = boolFilter->GetOutput(); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["3A"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_Remove_Structures() -{ - Remove_Structures(" 3A", "Aorta"); - Remove_Structures(" 3A", "LeftSubclavianArtery"); - Remove_Structures(" 3A", "RightSubclavianArtery"); - Remove_Structures(" 3A", "Thyroid"); - Remove_Structures(" 3A", "LeftCommonCarotidArtery"); - Remove_Structures(" 3A", "RightCommonCarotidArtery"); - Remove_Structures(" 3A", "BrachioCephalicArtery"); - // Remove_Structures("3A", "Bones"); --> should be in extractmediastinum - // Remove_Structures("3A", "BrachioCephalicVein"); ? - - StartNewStep("[Station 3A] Remove part of BrachioCephalicVein"); - // resize like support, extract slices - // while single CCL -> remove - // when two remove only the most post - MaskImagePointer BrachioCephalicVein = - GetAFDB()->template GetImage ("BrachioCephalicVein"); - BrachioCephalicVein = clitk::ResizeImageLike(BrachioCephalicVein, - m_Working_Support, - GetBackgroundValue()); - std::vector slices; - std::vector slices_BCV; - clitk::ExtractSlices(m_Working_Support, 2, slices); - clitk::ExtractSlices(BrachioCephalicVein, 2, slices_BCV); - for(uint i=0; i(slices_BCV[i], 0, true, 1); - - // Compute centroids - std::vector centroids; - ComputeCentroids(slices_BCV[i], GetBackgroundValue(), centroids); - - // If several centroid, select the one most anterior - if (centroids.size() > 2) { - // Only keep the one most post - typename MaskSliceType::PixelType label; - if (centroids[1][1] > centroids[2][1]) { - label = 2; - } - else { - label = 1; - } - // "remove" the CCL - slices_BCV[i] = clitk::SetBackground(slices_BCV[i], - slices_BCV[i], - label, - GetBackgroundValue(), - true); - } - - // Remove from the support - clitk::AndNot(slices[i], slices_BCV[i], GetBackgroundValue()); - } - - // Joint - m_Working_Support = clitk::JoinSlices(slices, m_Working_Support, 2); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["3A"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - diff --git a/segmentation/clitkExtractLymphStation_3P.txx b/segmentation/clitkExtractLymphStation_3P.txx deleted file mode 100644 index 274fc86..0000000 --- a/segmentation/clitkExtractLymphStation_3P.txx +++ /dev/null @@ -1,282 +0,0 @@ - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3P_SetDefaultValues() -{ -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3P() -{ - if (!CheckForStation("3P")) return; - - StartNewStep("Station 3P"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 3P] Get the current 3P suppport"); - m_Working_Support = m_ListOfSupports["S3P"]; - m_ListOfStations["3P"] = m_Working_Support; - StopCurrentStep(m_Working_Support); - - // Generic RelativePosition processes - m_ListOfStations["3P"] = this->ApplyRelativePositionList("Station_3P", m_ListOfStations["3P"]); - m_Working_Support = m_ListOfStations["3P"]; - ExtractStation_8_Single_CCL_Limits(); // YES 8 ! - ExtractStation_3P_Remove_Structures(); // after CCL - m_ListOfStations["3P"] = m_Working_Support; - - // Old stuff - // LR limits superiorly => not here for the moment because not clear in the def - // ExtractStation_3P_LR_sup_Limits_2(); //TODO - // ExtractStation_3P_LR_sup_Limits(); // old version to change - // ExtractStation_3P_LR_inf_Limits(); // <-- done in RelPosList - - // Store image filenames into AFDB - writeImage(m_ListOfStations["3P"], "seg/Station3P.mhd"); - GetAFDB()->SetImageFilename("Station3P", "seg/Station3P.mhd"); - WriteAFDB(); - StopSubStep(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3P_Remove_Structures() -{ - StartNewStep("[Station 3P] Remove some structures."); - Remove_Structures("3P", "Esophagus"); - Remove_Structures("3P", "Thyroid"); - Remove_Structures("3P", "VertebralArtery"); // (inside the station) - StopCurrentStep(m_Working_Support); - m_ListOfStations["3P"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3P_LR_sup_Limits() -{ - /* - "On the right side, the limit is defined by the air–soft-tissue - interface. On the left side, it is defined by the air–tissue - interface superiorly (Fig. 2A–C) and the aorta inferiorly - (Figs. 2D–I and 3A–C)." - - sup : - Resizelike support : Trachea, SubclavianArtery - Trachea, slice by slice, get centroid trachea - SubclavianArtery, slice by slice, CCL - prendre la 1ère à L et R, not at Left - - */ - StartNewStep("[Station 3P] Left/Right limits (superior part) "); - - // Load structures - MaskImagePointer Trachea = GetAFDB()->template GetImage("Trachea"); - MaskImagePointer SubclavianArtery = GetAFDB()->template GetImage("SubclavianArtery"); - - // Crop like current support - Trachea = clitk::ResizeImageLike(Trachea, m_Working_Support, GetBackgroundValue()); - SubclavianArtery = clitk::ResizeImageLike(SubclavianArtery, m_Working_Support, GetBackgroundValue()); - - // writeImage(Trachea, "tr.mhd"); - // writeImage(SubclavianArtery, "sca.mhd"); - - // Get list of slices - std::vector slices_support; - std::vector slices_trachea; - std::vector slices_subclavianartery; - clitk::ExtractSlices(m_Working_Support, 2, slices_support); - clitk::ExtractSlices(Trachea, 2, slices_trachea); - clitk::ExtractSlices(SubclavianArtery, 2, slices_subclavianartery); - - // Loop on slices - std::vector points; - MaskImagePointType p; - for(uint i=0; i centroids; - typename MaskSliceType::PointType c; - ComputeCentroids(slices_trachea[i], GetBackgroundValue(), centroids); - c = centroids[1]; - - // [debug] Store point - clitk::PointsUtils::Convert2DTo3D(centroids[1], Trachea, i, p); - points.push_back(p); - - // Get Right and Left CCL in SubclavianArtery - slices_subclavianartery[i] = Labelize(slices_subclavianartery[i], 0, true, 10); - ComputeCentroids(slices_subclavianartery[i], GetBackgroundValue(), centroids); - - if (centroids.size() > 1) { - // Determine the one at Right/Left -> first after Trachea - // centroid - typename MaskSliceType::PointType right; - typename MaskSliceType::PointType left; - int label_right=-1; - int label_left=-1; - right[0] = c[0]-100; - left[0] = c[0]+100; - for(uint j=1; j= right[0]) { - right = centroids[j]; - label_right = j; - } - } - if (centroids[j][0] > c[0]) { // At Left of Trachea centroid - if (centroids[j][0] <= left[0]) { - left = centroids[j]; - label_left = j; - } - } - } - - if (label_right != -1) { - - // Debug points - clitk::PointsUtils::Convert2DTo3D(centroids[label_right], SubclavianArtery, i, p); - points.push_back(p); - - // Set Background and ForegroundValue according to label_right - MaskSlicePointer object = - clitk::Binarize(slices_subclavianartery[i], label_right, label_right, - GetBackgroundValue(), GetForegroundValue()); - - // Relative Position : not at Right - typedef clitk::AddRelativePositionConstraintToLabelImageFilter RelPosFilterType; - typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); - relPosFilter->VerboseStepFlagOff(); - relPosFilter->WriteStepFlagOff(); - relPosFilter->SetBackgroundValue(GetBackgroundValue()); - relPosFilter->SetInput(slices_support[i]); - relPosFilter->SetInputObject(object); - relPosFilter->AddOrientationTypeString("RightTo"); - relPosFilter->SetInverseOrientationFlag(true); - // relPosFilter->SetIntermediateSpacing(3); - relPosFilter->SetIntermediateSpacingFlag(false); - relPosFilter->SetFuzzyThreshold(0.7); - relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop - relPosFilter->Update(); - slices_support[i] = relPosFilter->GetOutput(); - - // Relative Position : not Anterior - relPosFilter = RelPosFilterType::New(); - relPosFilter->VerboseStepFlagOff(); - relPosFilter->WriteStepFlagOff(); - relPosFilter->SetBackgroundValue(GetBackgroundValue()); - relPosFilter->SetInput(slices_support[i]); - relPosFilter->SetInputObject(object); - relPosFilter->AddOrientationTypeString("AntTo"); - relPosFilter->SetInverseOrientationFlag(true); - // relPosFilter->SetIntermediateSpacing(3); - relPosFilter->SetIntermediateSpacingFlag(false); - relPosFilter->SetFuzzyThreshold(0.7); - relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop - relPosFilter->Update(); - slices_support[i] = relPosFilter->GetOutput(); - - } // End RelativePosition for Right - - - if (label_left != -1) { - - // Debug points - clitk::PointsUtils::Convert2DTo3D(centroids[label_left], SubclavianArtery, i, p); - points.push_back(p); - - // Set Background and ForegroundValue according to label_right - MaskSlicePointer object = - clitk::Binarize(slices_subclavianartery[i], label_left, label_left, - GetBackgroundValue(), GetForegroundValue()); - - // Relative Position : not at Right - typedef clitk::AddRelativePositionConstraintToLabelImageFilter RelPosFilterType; - typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); - relPosFilter->VerboseStepFlagOff(); - relPosFilter->WriteStepFlagOff(); - relPosFilter->SetBackgroundValue(GetBackgroundValue()); - relPosFilter->SetInput(slices_support[i]); - relPosFilter->SetInputObject(object); - relPosFilter->AddOrientationTypeString("L"); - relPosFilter->SetInverseOrientationFlag(true); - // relPosFilter->SetIntermediateSpacing(3); - relPosFilter->SetIntermediateSpacingFlag(false); - relPosFilter->SetFuzzyThreshold(0.7); - relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop - relPosFilter->Update(); - slices_support[i] = relPosFilter->GetOutput(); - - // Relative Position : not Anterior - relPosFilter = RelPosFilterType::New(); - relPosFilter->VerboseStepFlagOff(); - relPosFilter->WriteStepFlagOff(); - relPosFilter->SetBackgroundValue(GetBackgroundValue()); - relPosFilter->SetInput(slices_support[i]); - relPosFilter->SetInputObject(object); - relPosFilter->AddOrientationTypeString("A"); - relPosFilter->SetInverseOrientationFlag(true); - // relPosFilter->SetIntermediateSpacing(3); - relPosFilter->SetIntermediateSpacingFlag(false); - relPosFilter->SetFuzzyThreshold(0.7); - relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop - relPosFilter->Update(); - slices_support[i] = relPosFilter->GetOutput(); - - } - - - } // if centroids.size > 1 - } // End loop slices - - // Joint slices - m_Working_Support = clitk::JoinSlices(slices_support, m_Working_Support, 2); - - // Save list points - clitk::WriteListOfLandmarks(points, "subcl-lr.txt"); - - - StopCurrentStep(m_Working_Support); - m_ListOfStations["3P"] = m_Working_Support; -} -//-------------------------------------------------------------------- - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_3P_LR_sup_Limits_2() -{ - /* - "On the right side, the limit is defined by the air–soft-tissue - interface. On the left side, it is defined by the air–tissue - interface superiorly (Fig. 2A–C) and the aorta inferiorly - (Figs. 2D–I and 3A–C)." - - sup : - Resizelike support : Trachea, SubclavianArtery - Trachea, slice by slice, get centroid trachea - SubclavianArtery, slice by slice, CCL - prendre la 1ère à L et R, not at Left - - */ - // StartNewStep("[Station 3P] Left/Right limits (superior part) "); - - -} -//-------------------------------------------------------------------- - diff --git a/segmentation/clitkExtractLymphStation_4RL.txx b/segmentation/clitkExtractLymphStation_4RL.txx deleted file mode 100644 index 8eb1fbd..0000000 --- a/segmentation/clitkExtractLymphStation_4RL.txx +++ /dev/null @@ -1,157 +0,0 @@ - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_4RL_SetDefaultValues() -{ -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_4R() { - if (!CheckForStation("4R")) return; - StartNewStep("Stations 4R"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 4R] Get the current 4RL suppport"); - m_ListOfStations["4R"] = m_ListOfSupports["S4R"]; - StopCurrentStep(m_ListOfStations["4R"]); - - // Generic RelativePosition processes - m_ListOfStations["4R"] = this->ApplyRelativePositionList("Station_4R", m_ListOfStations["4R"]); - - // Store image filenames into AFDB - WriteImageStation("4R"); - StopSubStep(); - ComputeOverlapWithRef("4R"); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_4L() { - if (!CheckForStation("4L")) return; - StartNewStep("Stations 4L"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 4L] Get the current 4RL suppport"); - m_ListOfStations["4L"] = m_ListOfSupports["S4L"]; - StopCurrentStep(m_ListOfStations["4L"]); - - // Generic RelativePosition processes - m_ListOfStations["4L"] = this->ApplyRelativePositionList("Station_4L", m_ListOfStations["4L"]); - - // Separation Ant/Post - m_Working_Support = m_ListOfStations["4L"]; - ExtractStation_S4L_S5_Limits_Aorta_LeftPulmonaryArtery(10); - m_ListOfStations["4L"] = m_Working_Support; - - // Keep only one single CCL by slice - StartNewStep("[Station 4L] Keep only one CCL by slice"); - m_ListOfStations["4L"] = SliceBySliceKeepMainCCL(m_ListOfStations["4L"], - GetBackgroundValue(), - GetForegroundValue()); - StopCurrentStep(m_ListOfStations["4L"]); - - // Store image filenames into AFDB - WriteImageStation("4L"); - StopSubStep(); - ComputeOverlapWithRef("4L"); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_S4L_S5_Limits_Aorta_LeftPulmonaryArtery(int KeepPoint) -{ - // ---------------------------------------------------------- - StartNewStep("[Station 4L] Limits between Asc and Desc Aorta, and with LeftPulmonaryArtery "); - - // Separate Aorta into DescendingAorta AscendingAorta - MaskImagePointer AscendingAorta = GetAFDB()->template GetImage("AscendingAorta"); - MaskImagePointer DescendingAorta = GetAFDB()->template GetImage("DescendingAorta"); - - // Crop like support (inferiorly) - m_Working_Support = clitk::AutoCrop(m_Working_Support, GetBackgroundValue()); - AscendingAorta = - clitk::ResizeImageLike(AscendingAorta, m_Working_Support, GetBackgroundValue()); - DescendingAorta = - clitk::ResizeImageLike(DescendingAorta, m_Working_Support, GetBackgroundValue()); - - // Crop superior part (when AscendingAorta and DescendingAorta join) - MaskImagePointType p; - clitk::FindExtremaPointInAGivenDirection(AscendingAorta, - GetBackgroundValue(), 2, false, p); - double max = p[2]+AscendingAorta->GetSpacing()[2]; - AscendingAorta = - clitk::CropImageRemoveGreaterThan(AscendingAorta, 2, max, false, GetBackgroundValue()); - DescendingAorta = - clitk::CropImageRemoveGreaterThan(DescendingAorta, 2, max, false, GetBackgroundValue()); - - // Crop inferior part, where LeftPulmonaryArtery start - MaskImagePointer AscendingAortaCopy = clitk::Clone(AscendingAorta); - MaskImagePointer LeftPulmonaryArtery = GetAFDB()->template GetImage("LeftPulmonaryArtery"); - clitk::FindExtremaPointInAGivenDirection(LeftPulmonaryArtery, - GetBackgroundValue(), 2, false, p); - max = p[2]+LeftPulmonaryArtery->GetSpacing()[2]; - AscendingAorta = - clitk::CropImageRemoveLowerThan(AscendingAorta, 2, max, false, GetBackgroundValue()); - DescendingAorta = - clitk::CropImageRemoveLowerThan(DescendingAorta, 2, max, false, GetBackgroundValue()); - - // Find closest points - std::vector A; - std::vector B; - clitk::SliceBySliceBuildLineSegmentAccordingToMinimalDistanceBetweenStructures(AscendingAorta, - DescendingAorta, - GetBackgroundValue(), - 2, A, B); - // Separate according to AB lines - // clitk::WriteListOfLandmarks(A, "A.txt"); - // clitk::WriteListOfLandmarks(B, "B.txt"); - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_Working_Support, A, B, - GetBackgroundValue(), - 1, KeepPoint); // Keep point along axis 1 - - // Now, same principle between AscendingAorta and LeftPulmonaryArtery - AscendingAorta = - clitk::ResizeImageLike(AscendingAortaCopy, m_Working_Support, GetBackgroundValue()); - LeftPulmonaryArtery = - clitk::ResizeImageLike(LeftPulmonaryArtery, m_Working_Support, GetBackgroundValue()); - AscendingAorta = - clitk::CropImageRemoveGreaterThan(AscendingAorta, 2, max, false, GetBackgroundValue()); - LeftPulmonaryArtery = - clitk::CropImageRemoveGreaterThan(LeftPulmonaryArtery, 2, max, false, GetBackgroundValue()); - A.clear(); - B.clear(); - clitk::SliceBySliceBuildLineSegmentAccordingToMinimalDistanceBetweenStructures(AscendingAorta, - LeftPulmonaryArtery, - GetBackgroundValue(), - 2, A, B); - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_Working_Support, A, B, - GetBackgroundValue(), - 1, KeepPoint); // Keep point along axis 1 - - // AutoCrop - m_Working_Support = clitk::AutoCrop(m_Working_Support, GetBackgroundValue()); - - // End - StopCurrentStep(m_Working_Support); -} -//-------------------------------------------------------------------- - - diff --git a/segmentation/clitkExtractLymphStation_5.txx b/segmentation/clitkExtractLymphStation_5.txx deleted file mode 100644 index 0a5ea17..0000000 --- a/segmentation/clitkExtractLymphStation_5.txx +++ /dev/null @@ -1,94 +0,0 @@ - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_5_SetDefaultValues() -{ -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_5() { - if ((!CheckForStation("5")) && (!CheckForStation("5"))) return; - - StartNewStep("Stations 5"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 5] Get the current 5 suppport"); - m_ListOfStations["5"] = m_ListOfSupports["S5"]; - StopCurrentStep(m_ListOfStations["5"]); - - // Generic RelativePosition processes - m_ListOfStations["5"] = this->ApplyRelativePositionList("Station_5", m_ListOfStations["5"]); - - // Separation Ant/Post -> Like 4SL ! - m_Working_Support = m_ListOfStations["5"]; - ExtractStation_S4L_S5_Limits_Aorta_LeftPulmonaryArtery(-10); - m_ListOfStations["5"] = m_Working_Support; - - // Ant limit - m_Working_Support = m_ListOfStations["5"]; - ExtractStation_5_Limits_AscendingAorta_Ant(); - m_ListOfStations["5"] = m_Working_Support; - - // Keep only one single CCL by slice - StartNewStep("[Station 5] Keep only one CCL by slice"); - m_ListOfStations["5"] = SliceBySliceKeepMainCCL(m_ListOfStations["5"], - GetBackgroundValue(), - GetForegroundValue()); - - // AutoCrop - m_ListOfStations["5"] = clitk::AutoCrop(m_ListOfStations["5"], GetBackgroundValue()); - StopCurrentStep(m_ListOfStations["5"]); - - // Store image filenames into AFDB - writeImage(m_ListOfStations["5"], "seg/Station5.mhd"); - GetAFDB()->SetImageFilename("Station5", "seg/Station5.mhd"); - WriteAFDB(); - StopSubStep(); - -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_5_Limits_AscendingAorta_Ant() -{ - // ---------------------------------------------------------- - StartNewStep("[Station 5] Limits with Ant part of AscendingAorta"); - - // Get AscendingAorta - MaskImagePointer AscendingAorta = GetAFDB()->template GetImage("AscendingAorta"); - - // Crop and select most Ant points - AscendingAorta = - clitk::ResizeImageLike(AscendingAorta, m_Working_Support, GetBackgroundValue()); - std::vector A; - std::vector B; - clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(AscendingAorta, - GetBackgroundValue(), - 2, 1, true, 0, -1, A, B); - //1 mm margin - - // Separate according to AB lines - // clitk::WriteListOfLandmarks(A, "A.txt"); - // clitk::WriteListOfLandmarks(B, "B.txt"); - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_Working_Support, A, B, - GetBackgroundValue(), - 1, 10); // Keep point along axis 1 - // End - StopCurrentStep(m_Working_Support); -} -//-------------------------------------------------------------------- - - diff --git a/segmentation/clitkExtractLymphStation_6.txx b/segmentation/clitkExtractLymphStation_6.txx deleted file mode 100644 index 65c458e..0000000 --- a/segmentation/clitkExtractLymphStation_6.txx +++ /dev/null @@ -1,54 +0,0 @@ - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_6_SetDefaultValues() -{ -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_6() { - if ((!CheckForStation("6")) && (!CheckForStation("6"))) return; - - StartNewStep("Stations 6"); - StartSubStep(); - - // Get the current support - StartNewStep("[Station 6] Get the current 6 suppport"); - m_ListOfStations["6"] = m_ListOfSupports["S6"]; - StopCurrentStep(m_ListOfStations["6"]); - - // Generic RelativePosition processes - m_ListOfStations["6"] = this->ApplyRelativePositionList("Station_6", m_ListOfStations["6"]); - - // Remove some structures - m_Working_Support = m_ListOfStations["6"]; - Remove_Structures(" 6", "Aorta"); - Remove_Structures(" 6", "SVC"); - Remove_Structures(" 6", "BrachioCephalicVein"); - m_ListOfStations["6"] = m_Working_Support; - - // Keep only one single CCL by slice - StartNewStep("[Station 6] Keep only one CCL by slice"); - m_ListOfStations["6"] = SliceBySliceKeepMainCCL(m_ListOfStations["6"], - GetBackgroundValue(), - GetForegroundValue()); - StopCurrentStep(m_ListOfStations["6"]); - - // Store image filenames into AFDB - writeImage(m_ListOfStations["6"], "seg/Station6.mhd"); - GetAFDB()->SetImageFilename("Station6", "seg/Station6.mhd"); - WriteAFDB(); - StopSubStep(); - -} -//-------------------------------------------------------------------- - - diff --git a/segmentation/clitkExtractLymphStation_7.txx b/segmentation/clitkExtractLymphStation_7.txx deleted file mode 100644 index d6df428..0000000 --- a/segmentation/clitkExtractLymphStation_7.txx +++ /dev/null @@ -1,566 +0,0 @@ - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7_SetDefaultValues() -{ - SetFuzzyThreshold("7", "Bronchi", 0.1); - SetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein", 0.3); - SetFuzzyThreshold("7", "RightSuperiorPulmonaryVein", 0.2); - SetFuzzyThreshold("7", "RightPulmonaryArtery", 0.3); - SetFuzzyThreshold("7", "LeftPulmonaryArtery", 0.5); - SetFuzzyThreshold("7", "SVC", 0.2); - SetS7_UseMostInferiorPartOnlyFlag(false); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7() { - if (CheckForStation("7")) { - ExtractStation_7_SI_Limits(); - ExtractStation_7_RL_Interior_Limits(); - - // ExtractStation_7_Posterior_Limits(); - ExtractStation_8_Single_CCL_Limits(); - ExtractStation_7_Remove_Structures(); - // Store image filenames into AFDB - writeImage(m_ListOfStations["7"], "seg/Station7.mhd"); - GetAFDB()->SetImageFilename("Station7", "seg/Station7.mhd"); - WriteAFDB(); - } -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7_SI_Limits() -{ - StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLL-RMLBronchus"); - // Get Inputs - MaskImagePointer Trachea = GetAFDB()->template GetImage ("Trachea"); - - // Create line from A to B with - // A = upper border of LLL at left - // B = lower border of bronchus intermedius (BI) or RightMiddleLobeBronchus - ImagePointType A; - ImagePointType B; - FindLineForS7S8Separation(A, B); - - // // if option -> replace A[0] with B[0] - // if (GetS7_UseMostInferiorPartOnlyFlag()) { - // A[0] = B[0]; - // } - - // Use line to remove the inferior part - m_Working_Support = - SliceBySliceSetBackgroundFromSingleLine(m_Working_Support, GetBackgroundValue(), - A, B, 2, 0, false); - - // Get the CarinaZ position - double m_CarinaZ = FindCarina(); - - // Crop support - m_Working_Support = - clitk::CropImageAlongOneAxis(m_Working_Support, 2, - A[2], m_CarinaZ, true, - GetBackgroundValue()); - // Crop trachea - m_Working_Trachea = - clitk::CropImageAlongOneAxis(Trachea, 2, - A[2], m_CarinaZ, true, - GetBackgroundValue()); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["7"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7_RL_Interior_Limits() -{ - // ---------------------------------------------------------------- - StartNewStep("[Station7] RL limits with bronchi"); - - /* - Slice by Slice, consider most Left point of the Right - bronchus. Remove the Ant/Right corner - */ - - // First consider bronchi - FindLeftAndRightBronchi(); - m_RightBronchus = GetAFDB()->template GetImage ("RightBronchus"); - m_LeftBronchus = GetAFDB()->template GetImage ("LeftBronchus"); - - // Resize like m_Working_Support - m_LeftBronchus = - clitk::ResizeImageLike(m_LeftBronchus, m_Working_Support, GetBackgroundValue()); - m_RightBronchus = - clitk::ResizeImageLike(m_RightBronchus, m_Working_Support, GetBackgroundValue()); - - // Extract slices, Label, compute centroid, keep most central connected component - std::vector slices_leftbronchus; - std::vector slices_rightbronchus; - std::vector slices_support; - clitk::ExtractSlices(m_LeftBronchus, 2, slices_leftbronchus); - clitk::ExtractSlices(m_RightBronchus, 2, slices_rightbronchus); - clitk::ExtractSlices(m_Working_Support, 2, slices_support); - - // Keep only the CCL of the bronchus with the closest to the center - // Loop on slices for left bronchus - for(uint i=0; i(slices_leftbronchus[i], 0, false, 10); - std::vector c; - clitk::ComputeCentroids(slices_leftbronchus[i], GetBackgroundValue(), c); - if (c.size() > 1) { - double most_at_left = c[1][0]; - int most_at_left_index=1; - for(uint j=1; j(slices_leftbronchus[i], most_at_left_index, - most_at_left_index, GetBackgroundValue(), GetForegroundValue()); - } // end c.size - } - - // Loop on slices for right bronchus - for(uint i=0; i(slices_rightbronchus[i], 0, false, 10); - std::vector c; - clitk::ComputeCentroids(slices_rightbronchus[i], GetBackgroundValue(), c); - if (c.size() > 1) { - double most_at_right = c[1][0]; - int most_at_right_index=1; - for(uint j=1; j most_at_right) { - most_at_right = c[j][0]; - most_at_right_index = j; - } - } - // Put all other CCL to Background - slices_rightbronchus[i] = - clitk::Binarize(slices_rightbronchus[i], most_at_right_index, - most_at_right_index, GetBackgroundValue(), GetForegroundValue()); - } // end c.size - } - - // Joint slices - m_LeftBronchus = clitk::JoinSlices(slices_leftbronchus, m_LeftBronchus, 2); - m_RightBronchus = clitk::JoinSlices(slices_rightbronchus, m_RightBronchus, 2); - - // For Right bronchus, Find most Left point. Remove corner Ant/Right corner - for(uint i=0; i(slices_rightbronchus[i], GetBackgroundValue(), 0, false, p_left); - if (b) { - b = clitk::FindExtremaPointInAGivenDirection(slices_rightbronchus[i], GetBackgroundValue(), 1, false, p_post); - } - if (b) { - MaskSlicePointType p = p_left; - p[1] = p_post[1]; - MaskSliceIndexType pi; - slices_rightbronchus[i]->TransformPhysicalPointToIndex(p, pi); - - // Build region to remove - MaskSliceRegionType region = slices_rightbronchus[i]->GetLargestPossibleRegion(); - MaskSliceIndexType index = region.GetIndex(); - MaskSliceSizeType size = region.GetSize(); - size[0] = pi[0] - index[0]; - size[1] = pi[1] - index[1]; - region.SetSize(size); - - // Fill region with Background value - clitk::FillRegionWithValue(slices_support[i], GetBackgroundValue(), region); - } - } - - // For Left bronchus, Find most Right point. Remove corner Ant/Left corner - for(uint i=0; i(slices_leftbronchus[i], GetBackgroundValue(), 0, true, p_right); - if (b) { - b = clitk::FindExtremaPointInAGivenDirection(slices_rightbronchus[i], GetBackgroundValue(), 1, false, p_post); - } - if (b) { - MaskSlicePointType p = p_right; - p[1] = p_post[1]; - MaskSliceIndexType pi; - slices_leftbronchus[i]->TransformPhysicalPointToIndex(p, pi); - - /* typedef itk::ImageRegionIterator IteratorType; - IteratorType iter(input, region); - iter.GoToBegin(); - while (!iter.IsAtEnd()) { - MaskSliceIndexType index = iter.GetIndex(); - if (index[0] > pi[0]) && (index[1] > pi[1]) iter.Set(GetBackgroundValue()); - - ++iter; - } - */ - - - // Build region to remove - MaskSliceRegionType region = slices_leftbronchus[i]->GetLargestPossibleRegion(); - MaskSliceIndexType index = region.GetIndex(); - MaskSliceSizeType size = region.GetSize(); - index[0] = pi[0]; - size[0] = slices_leftbronchus[i]->GetLargestPossibleRegion().GetSize()[0] - pi[0]; - size[1] = pi[1] - index[1]; - region.SetSize(size); - region.SetIndex(index); - - // Fill region with Background value - clitk::FillRegionWithValue(slices_support[i], GetBackgroundValue(), region); - } - } - - m_Working_Support = clitk::JoinSlices(slices_support, m_Working_Support, 2); - - // Also remove what is at right of the Right bronchus (left respectively) - m_Working_Support = - clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, - GetFuzzyThreshold("7", "Bronchi"), "NotLeftTo", - false, 3, false); - m_Working_Support = - clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, - GetFuzzyThreshold("7", "Bronchi"), "NotRightTo", - false, 3, false); - - // SECOND PART - - StopCurrentStep(m_Working_Support); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7_RL_Limits_OLD() -{ - // ---------------------------------------------------------------- - StartNewStep("[Station7] Limits with bronchus : RightTo the left bronchus"); - - // First consider bronchus and keep the main CCL by slice - m_RightBronchus = GetAFDB()->template GetImage ("RightBronchus"); - m_LeftBronchus = GetAFDB()->template GetImage ("LeftBronchus"); - - // Extract slices, Label, compute centroid, keep most central connected component - std::vector slices_leftbronchus; - std::vector slices_rightbronchus; - clitk::ExtractSlices(m_LeftBronchus, 2, slices_leftbronchus); - clitk::ExtractSlices(m_RightBronchus, 2, slices_rightbronchus); - - // Version #1 with limit = centroid of the bronchus (OUTDATED) - // Step1 = keep only the CCL of the bronchus with the closest to the center - // Step2 = SliceBySlice Rel pos to both bronchi - - // Loop on slices - for(uint i=0; i(slices_leftbronchus[i], 0, false, 10); - std::vector c; - clitk::ComputeCentroids(slices_leftbronchus[i], GetBackgroundValue(), c); - if (c.size() > 1) { - double most_at_left = c[1][0]; - int most_at_left_index=1; - for(uint j=1; j(slices_leftbronchus[i], most_at_left_index, - most_at_left_index, GetBackgroundValue(), GetForegroundValue()); - } // end c.size - } - - for(uint i=0; i(slices_rightbronchus[i], 0, false, 10); - std::vector c; - clitk::ComputeCentroids(slices_rightbronchus[i], GetBackgroundValue(), c); - if (c.size() > 1) { - double most_at_right = c[1][0]; - int most_at_right_index=1; - for(uint j=1; j most_at_right) { - most_at_right = c[j][0]; - most_at_right_index = j; - } - } - // Put all other CCL to Background - slices_rightbronchus[i] = - clitk::Binarize(slices_rightbronchus[i], most_at_right_index, - most_at_right_index, GetBackgroundValue(), GetForegroundValue()); - } // end c.size - } - - // Joint slices - m_LeftBronchus = clitk::JoinSlices(slices_leftbronchus, m_LeftBronchus, 2); - m_RightBronchus = clitk::JoinSlices(slices_rightbronchus, m_RightBronchus, 2); - - writeImage(m_LeftBronchus, "step-left.mhd"); - writeImage(m_RightBronchus, "step-right.mhd"); - - m_Working_Support = - clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, - GetFuzzyThreshold("7", "Bronchi"), "RightTo", - false, 3, false); - StopCurrentStep(m_Working_Support); - - - // ---------------------------------------------------------------- - StartNewStep("[Station7] Limits with bronchus : LeftTo the right bronchus"); - m_Working_Support = - clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, - GetFuzzyThreshold("7", "Bronchi"), "LeftTo", - false, 3, false); - StopCurrentStep(m_Working_Support); - - - // ---------------------------------------------------------------- - StartNewStep("[Station7] Limits with LeftSuperiorPulmonaryVein"); - try { - MaskImagePointer LeftSuperiorPulmonaryVein = GetAFDB()->template GetImage("LeftSuperiorPulmonaryVein"); - typedef SliceBySliceRelativePositionFilter SliceRelPosFilterType; - typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); - sliceRelPosFilter->SetInput(m_Working_Support); - sliceRelPosFilter->SetInputObject(LeftSuperiorPulmonaryVein); - sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein")); - sliceRelPosFilter->AddOrientationTypeString("NotLeftTo"); - sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); - sliceRelPosFilter->SetIntermediateSpacingFlag(true); - sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); - sliceRelPosFilter->SetAutoCropFlag(false); - sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); - sliceRelPosFilter->Update(); - m_Working_Support = sliceRelPosFilter->GetOutput(); - StopCurrentStep(m_Working_Support); - } - catch (clitk::ExceptionObject e) { - std::cout << "Not LeftSuperiorPulmonaryVein, skip" << std::endl; - } - - // ---------------------------------------------------------------- - StartNewStep("[Station7] Limits with RightSuperiorPulmonaryVein"); - try { - MaskImagePointer RightSuperiorPulmonaryVein = GetAFDB()->template GetImage("RightSuperiorPulmonaryVein"); - typedef SliceBySliceRelativePositionFilter SliceRelPosFilterType; - typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); - sliceRelPosFilter->SetInput(m_Working_Support); - sliceRelPosFilter->SetInputObject(RightSuperiorPulmonaryVein); - sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "RightSuperiorPulmonaryVein")); - sliceRelPosFilter->AddOrientationTypeString("NotRightTo"); - sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); - sliceRelPosFilter->AddOrientationTypeString("NotPostTo"); - sliceRelPosFilter->SetIntermediateSpacingFlag(true); - sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); - sliceRelPosFilter->SetAutoCropFlag(false); - sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); - sliceRelPosFilter->Update(); - m_Working_Support = sliceRelPosFilter->GetOutput(); - StopCurrentStep(m_Working_Support); - } - catch (clitk::ExceptionObject e) { - std::cout << "Not RightSuperiorPulmonaryVein, skip" << std::endl; - } - - // ---------------------------------------------------------------- - StartNewStep("[Station7] Limits with RightPulmonaryArtery"); - MaskImagePointer RightPulmonaryArtery = GetAFDB()->template GetImage("RightPulmonaryArtery"); - typedef SliceBySliceRelativePositionFilter SliceRelPosFilterType; - typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); - sliceRelPosFilter->SetInput(m_Working_Support); - sliceRelPosFilter->SetInputObject(RightPulmonaryArtery); - sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "RightPulmonaryArtery")); - sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); - sliceRelPosFilter->SetIntermediateSpacingFlag(true); - sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); - sliceRelPosFilter->SetAutoCropFlag(false); - sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); - sliceRelPosFilter->Update(); - m_Working_Support = sliceRelPosFilter->GetOutput(); - StopCurrentStep(m_Working_Support); - - // ---------------------------------------------------------------- - StartNewStep("[Station7] Limits with LeftPulmonaryArtery"); - MaskImagePointer LeftPulmonaryArtery = GetAFDB()->template GetImage("LeftPulmonaryArtery"); - sliceRelPosFilter = SliceRelPosFilterType::New(); - sliceRelPosFilter->SetInput(m_Working_Support); - sliceRelPosFilter->SetInputObject(LeftPulmonaryArtery); - sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "LeftPulmonaryArtery")); - sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); - sliceRelPosFilter->SetIntermediateSpacingFlag(true); - sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); - sliceRelPosFilter->SetAutoCropFlag(false); - sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); - sliceRelPosFilter->Update(); - m_Working_Support = sliceRelPosFilter->GetOutput(); - StopCurrentStep(m_Working_Support); - - StartNewStep("[Station7] Limits with SVC"); - MaskImagePointer SVC = GetAFDB()->template GetImage("SVC"); - sliceRelPosFilter = SliceRelPosFilterType::New(); - sliceRelPosFilter->SetInput(m_Working_Support); - sliceRelPosFilter->SetInputObject(SVC); - sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "SVC")); - sliceRelPosFilter->AddOrientationTypeString("NotRightTo"); - sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); - sliceRelPosFilter->SetIntermediateSpacingFlag(true); - sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); - sliceRelPosFilter->SetAutoCropFlag(true); - sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); - sliceRelPosFilter->Update(); - m_Working_Support = sliceRelPosFilter->GetOutput(); - StopCurrentStep(m_Working_Support); - - // End - m_ListOfStations["7"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7_Posterior_Limits() -{ - StartNewStep("[Station7] Posterior limits -> must be AntTo post wall of the bronchi (OLD CLASSIF)"); - - // Search for points that are the most left/post/ant and most - // right/post/ant of the left and right bronchus - - // extract, loop slices, label/keep, find extrema x 3 - /* FindExtremaPointsInBronchus(m_LeftBronchus, 0, 15, m_RightMostInLeftBronchus, - m_AntMostInLeftBronchus, m_PostMostInLeftBronchus); - FindExtremaPointsInBronchus(m_RightBronchus, 1, 15, m_LeftMostInRightBronchus, - m_AntMostInRightBronchus, m_PostMostInRightBronchus); - */ - - // First cut bronchus to the correct sup/inf support - MaskImagePointer RightBronchus = clitk::ResizeImageLike(m_RightBronchus, m_Working_Support, GetBackgroundValue()); - MaskImagePointer LeftBronchus = clitk::ResizeImageLike(m_LeftBronchus, m_Working_Support, GetBackgroundValue()); - - // Find extrema points - FindExtremaPointsInBronchus(RightBronchus, 0, 10, m_LeftMostInRightBronchus, - m_AntMostInRightBronchus, m_PostMostInRightBronchus); - - FindExtremaPointsInBronchus(LeftBronchus, 1, 10, m_RightMostInLeftBronchus, - m_AntMostInLeftBronchus, m_PostMostInLeftBronchus); - - - - // DEBUG - std::ofstream osrl; openFileForWriting(osrl, "osrl.txt"); osrl << "LANDMARKS1" << std::endl; - std::ofstream osal; openFileForWriting(osal, "osal.txt"); osal << "LANDMARKS1" << std::endl; - std::ofstream ospl; openFileForWriting(ospl, "ospl.txt"); ospl << "LANDMARKS1" << std::endl; - std::ofstream osrr; openFileForWriting(osrr, "osrr.txt"); osrr << "LANDMARKS1" << std::endl; - std::ofstream osar; openFileForWriting(osar, "osar.txt"); osar << "LANDMARKS1" << std::endl; - std::ofstream ospr; openFileForWriting(ospr, "ospr.txt"); ospr << "LANDMARKS1" << std::endl; - - for(uint i=0; i(m_Working_Support, - m_PostMostInRightBronchus, - m_PostMostInLeftBronchus, - GetBackgroundValue(), 1, -10); - // If needed -> can do the same with AntMost. - - // End - StopCurrentStep(m_Working_Support); - m_ListOfStations["7"] = m_Working_Support; -} -//-------------------------------------------------------------------- - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_7_Remove_Structures() -{ - - //-------------------------------------------------------------------- - StartNewStep("[Station7] remove some structures"); - - Remove_Structures("7", "AzygousVein"); - Remove_Structures("7", "Aorta"); - Remove_Structures("7", "RightPulmonaryArtery"); - Remove_Structures("7", "LeftPulmonaryArtery"); - Remove_Structures("7", "LeftSuperiorPulmonaryVein"); - Remove_Structures("7", "PulmonaryTrunk"); - Remove_Structures("7", "VertebralBody"); - - // Keep only one CCL by slice (before removing Esophagus) - // DD("SliceBySliceKeepMainCCL"); - - // TODO -> replace by keep the one that contains point at the middle of the line between the bronchus - // -> new function "keep/select" the ccl that contains this point (2D) - - //m_Working_Support = clitk::SliceBySliceKeepMainCCL(m_Working_Support, GetBackgroundValue(), GetForegroundValue()); - - Remove_Structures("7", "Esophagus"); - - // END - StopCurrentStep(m_Working_Support); - m_ListOfStations["7"] = m_Working_Support; - return; -} -//-------------------------------------------------------------------- - - - diff --git a/segmentation/clitkExtractLymphStation_8.txx b/segmentation/clitkExtractLymphStation_8.txx deleted file mode 100644 index d4bbfc3..0000000 --- a/segmentation/clitkExtractLymphStation_8.txx +++ /dev/null @@ -1,549 +0,0 @@ - -#include -#include - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_SetDefaultValues() -{ - MaskImagePointType p; - p[0] = 15; p[1] = 2; p[2] = 1; - SetEsophagusDiltationForAnt(p); - p[0] = 5; p[1] = 10; p[2] = 1; - SetEsophagusDiltationForRight(p); - SetFuzzyThreshold("8", "Esophagus", 0.5); - SetInjectedThresholdForS8(150); -} -//-------------------------------------------------------------------- - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8() -{ - if (!CheckForStation("8")) return; - - StartNewStep("Station 8"); - StartSubStep(); - ExtractStation_8_SI_Limits(); // OK, validated - ExtractStation_8_Ant_Limits(); // OK, validated - ExtractStation_8_Left_Sup_Limits(); // OK, validated - ExtractStation_8_Left_Inf_Limits(); // OK, validated - ExtractStation_8_Single_CCL_Limits(); // OK, validated - ExtractStation_8_Remove_Structures(); // OK, validated - - // Store image filenames into AFDB - writeImage(m_ListOfStations["8"], "seg/Station8.mhd"); - GetAFDB()->SetImageFilename("Station8", "seg/Station8.mhd"); - WriteAFDB(); - StopSubStep(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_SI_Limits() -{ - /* - Station 8: paraeosphageal nodes - - "Superiorly, Station 8 begins at the level of the carina and, - therefore, abuts Station 3P (Fig. 3C). Inferiorly, the lower limit - of Station 8 was not specified in the Mountain and Dresler - classification (1). We delineate this volume until it reaches the - gastroesphogeal junction. " - - => new classification IASCL 2009: - - "Lower border: the diaphragm" - - "Upper border: the upper border of the lower lobe bronchus on the - left; the lower border of the bronchus intermedius on the right" - - */ - StartNewStep("[Station8] Sup/Inf limits with LeftLower/RightMiddle Lobe and diaphragm"); - - /* ----------------------------------------------- - NEW SUPERIOR LIMIT = LeftLowerLobeBronchus / - RightMiddleLobeBronchus See FindLineForS7S8Separation - ----------------------------------------------- - */ - ImagePointType A; - ImagePointType B; - FindLineForS7S8Separation(A, B); - - // add one slice to be adjacent to Station7 - B[2] += m_Working_Support->GetSpacing()[2]; - A[2] += m_Working_Support->GetSpacing()[2]; - - // Use the line to remove the inferior part - m_Working_Support = - SliceBySliceSetBackgroundFromSingleLine(m_Working_Support, - GetBackgroundValue(), A, B, 2, 0, true); - - /* ----------------------------------------------- - INFERIOR LIMIT = Diaphragm - ----------------------------------------------- - */ - - // Found most inferior part of the lung - MaskImagePointer Lungs = GetAFDB()->template GetImage("Lungs"); - // It should be already croped, so I took the origin and add 10mm above - m_DiaphragmInferiorLimit = Lungs->GetOrigin()[2]+10; - GetAFDB()->template ReleaseImage("Lungs"); - - m_Working_Support = - clitk::CropImageAlongOneAxis(m_Working_Support, 2, - m_DiaphragmInferiorLimit, - B[2], true, - GetBackgroundValue()); - // Done. - StopCurrentStep(m_Working_Support); - m_ListOfStations["8"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_Ant_Limits() -{ - //-------------------------------------------------------------------- - StartNewStep("[Station8] Ant part: not post to Esophagus"); - /* - Consider Esophagus, dilate it and remove ant part. It remains part - on L & R, than can be partly removed by cutting what remains at - right of vertebral body. - */ - - // Get Esophagus - m_Esophagus = GetAFDB()->template GetImage("Esophagus"); - - // In images from the original article, Atlas – UM, the oesophagus - //was included in nodal stations 3p and 8. Having said that, in the - //description for station 8, it indicates that “the delineation of - //station 8 is limited to the soft tissues surrounding the - //oesophagus”. In the recent article, The IASLC Lung Cancer Staging - //Project (J Thorac Oncol 4:5, 568-77), the images drawn by - //Dr. Aletta Frasier exclude this structure. From an oncological - //prospective, the oesophagus should be excluded from these nodal - //stations. - - // Resize Esophagus like current support - m_Esophagus = - clitk::ResizeImageLike(m_Esophagus, m_Working_Support, GetBackgroundValue()); // Needed ? - - // Dilate to keep only not Anterior positions - MaskImagePointType radiusInMM = GetEsophagusDiltationForAnt(); - m_Esophagus = clitk::Dilate(m_Esophagus, - radiusInMM, - GetBackgroundValue(), - GetForegroundValue(), true); - // Keep what is Posterior to Esophagus - typedef clitk::SliceBySliceRelativePositionFilter RelPosFilterType; - typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); - relPosFilter->VerboseStepFlagOff(); - relPosFilter->WriteStepFlagOff(); - relPosFilter->SetInput(m_Working_Support); - relPosFilter->SetInputObject(m_Esophagus); - relPosFilter->AddOrientationTypeString("PostTo"); - // relPosFilter->InverseOrientationFlagOff(); - relPosFilter->SetDirection(2); // Z axis - relPosFilter->UniqueConnectedComponentBySliceFlagOff(); - relPosFilter->SetIntermediateSpacing(3); - relPosFilter->IntermediateSpacingFlagOn(); - relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("8", "Esophagus")); - relPosFilter->RemoveObjectFlagOff(); // Do not exclude here because it is dilated - relPosFilter->CombineWithOrFlagOff(); // NO ! - relPosFilter->IgnoreEmptySliceObjectFlagOn(); - relPosFilter->Update(); - m_Working_Support = relPosFilter->GetOutput(); - - // AutoCrop (OR SbS ?) - m_Working_Support = clitk::AutoCrop(m_Working_Support, GetBackgroundValue()); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["8"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_Left_Sup_Limits() -{ - //-------------------------------------------------------------------- - StartNewStep("[Station8] Left limits: remove Left to line from Aorta to PulmonaryTrunk"); - - /* - We consider a line from Left part of Aorta to left part of - PulmonaryTrunk and remove what is at Left. - */ - - // Load the structures - MaskImagePointer Aorta = GetAFDB()->template GetImage("Aorta"); - MaskImagePointer PulmonaryTrunk = GetAFDB()->template GetImage("PulmonaryTrunk"); - - // Resize like the PT and define the slices - MaskImagePointType min, max; - clitk::GetMinMaxPointPosition(PulmonaryTrunk, min, max); - Aorta = clitk::CropImageAlongOneAxis(Aorta, 2, min[2], max[2], false, GetBackgroundValue()); - std::vector slices_aorta; - clitk::ExtractSlices(Aorta, 2, slices_aorta); - std::vector slices_PT; - clitk::ExtractSlices(PulmonaryTrunk, 2, slices_PT); - - // Find the points at left - std::vector p_A; - std::vector p_B; - MaskImagePointType pA; - MaskImagePointType pB; - for(uint i=0; i(slices_aorta[i], GetBackgroundValue(), 0, false, ps); - clitk::PointsUtils::Convert2DTo3D(ps, Aorta, i, pA); - - if (found) { - // In PT : generally 2 CCL, we keep the most at left - found = - clitk::FindExtremaPointInAGivenDirection(slices_PT[i], GetBackgroundValue(), 0, false, ps); - clitk::PointsUtils::Convert2DTo3D(ps, PulmonaryTrunk, i, pB); - } - - if (found) { - p_A.push_back(pA); - p_B.push_back(pB); - } - } - clitk::WriteListOfLandmarks(p_A, "S8-Aorta-Left-points.txt"); - clitk::WriteListOfLandmarks(p_B, "S8-PT-Left-points.txt"); - - // Remove part at Left - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_Working_Support, - p_A, p_B, - GetBackgroundValue(), - 0, -10); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["8"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_Single_CCL_Limits() -{ - //-------------------------------------------------------------------- - StartNewStep("[Station8 or 3P] Slice by slice, keep a single CCL (the closest to VertebralBody)"); - - // Consider slices - std::vector slices; - std::vector slices_vb; - clitk::ExtractSlices(m_Working_Support, 2, slices); - MaskImagePointer VertebralBody = - GetAFDB()->template GetImage ("VertebralBody"); - VertebralBody = clitk::ResizeImageLike(VertebralBody, m_Working_Support, GetBackgroundValue()); - clitk::ExtractSlices(VertebralBody, 2, slices_vb); - - for(uint i=0; i(slices[i], 0, true, 100); - // Compute centroids coordinate - std::vector centroids; - std::vector c; - clitk::ComputeCentroids(slices[i], GetBackgroundValue(), centroids); - clitk::ComputeCentroids(slices_vb[i], GetBackgroundValue(), c); - if ((c.size() > 1) && (centroids.size() > 1)) { - // keep the one which is the closer to vertebralbody centroid - double distance=1000000; - int index=0; - for(uint j=1; j(slices[i], GetBackgroundValue(), - GetForegroundValue(), index, index, true); - } - } - m_Working_Support = clitk::JoinSlices(slices, m_Working_Support, 2); - - StopCurrentStep(m_Working_Support); - m_ListOfStations["8"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_Left_Inf_Limits() -{ - //-------------------------------------------------------------------- - StartNewStep("[Station8] Left limits around esophagus with lines from VertebralBody-Aorta-Esophagus"); - - // Estract slices for current support for slice by slice processing - std::vector slices; - clitk::ExtractSlices(m_Working_Support, 2, slices); - - // 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("Lungs"); - clitk::AndNot(m_Esophagus, Lungs, GetBackgroundValue()); - GetAFDB()->template ReleaseImage("Lungs"); - - // Estract slices of Esophagus (resize like support before to have the same set of slices) - MaskImagePointer EsophagusForSlice = - clitk::ResizeImageLike(m_Esophagus, m_Working_Support, GetBackgroundValue()); - std::vector eso_slices; - clitk::ExtractSlices(EsophagusForSlice, 2, eso_slices); - - // Estract slices of Vertebral (resize like support before to have the same set of slices) - MaskImagePointer VertebralBody = GetAFDB()->template GetImage("VertebralBody"); - VertebralBody = clitk::ResizeImageLike(VertebralBody, m_Working_Support, GetBackgroundValue()); - // Remove what is outside the support to not consider what is to - // posterior in the VertebralBody (post the horizontal line) - clitk::And(VertebralBody, m_Working_Support, GetBackgroundValue()); - // writeImage(VertebralBody, "vb.mhd"); - std::vector vert_slices; - clitk::ExtractSlices(VertebralBody, 2, vert_slices); - - // Estract slices of Aorta (resize like support before to have the same set of slices) - MaskImagePointer Aorta = GetAFDB()->template GetImage("Aorta"); - Aorta = clitk::ResizeImageLike(Aorta, m_Working_Support, GetBackgroundValue()); - std::vector aorta_slices; - clitk::ExtractSlices(Aorta, 2, aorta_slices); - - // Extract slices of Mediastinum (resize like support before to have the same set of slices) - m_Mediastinum = GetAFDB()->template GetImage("Mediastinum"); - m_Mediastinum = clitk::ResizeImageLike(m_Mediastinum, m_Working_Support, GetBackgroundValue()); - std::vector mediast_slices; - clitk::ExtractSlices(m_Mediastinum, 2, mediast_slices); - - // List of points - std::vector p_MostLeftVertebralBody; - std::vector p_MostRightVertebralBody; - std::vector p_MostLeftAorta; - std::vector 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; - - typename MaskSliceType::PointType minSlicePoint; - typename MaskSliceType::PointType maxSlicePoint; - clitk::GetMinMaxPointPosition(vert_slices[0], minSlicePoint, maxSlicePoint); - - // Loop slices - for(uint i=0; i(vert_slices[i], GetBackgroundValue(), - 0, false, sp_MostLeftVertebralBody); - // clitk::PointsUtils::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p); - // DD(p); - - sp_MostLeftVertebralBody = - clitk::FindExtremaPointInAGivenLine(mediast_slices[i], 0, false, - sp_MostLeftVertebralBody, GetBackgroundValue(), 30); - // clitk::PointsUtils::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p); - // DD(p); - - sp_MostLeftVertebralBody[0] += 2; // 2mm margin - // clitk::PointsUtils::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p); - // DD(p); - - // Convert 2D points into 3D - clitk::PointsUtils::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p); - p_MostLeftVertebralBody.push_back(p); - - /* ------------------------------------------------------------------------------------- - Find first point not in mediastinum at RIGHT. Not used yet. - clitk::FindExtremaPointInAGivenDirection(vert_slices[i], GetBackgroundValue(), - 0, true, sp_MostRightVertebralBody); - sp_MostRightVertebralBody = - clitk::FindExtremaPointInAGivenLine(mediast_slices[i], 0, true, - sp_MostRightVertebralBody, GetBackgroundValue(),30); - sp_MostRightVertebralBody[0] -= 2; // 2 mm margin - - // Convert 2D points into 3D - clitk::PointsUtils::Convert2DTo3D(sp_MostRightVertebralBody, VertebralBody, i, p); - p_MostRightVertebralBody.push_back(p); - */ - - - /* ------------------------------------------------------------------------------------- - Find most Left point in Esophagus - */ - bool found = clitk::FindExtremaPointInAGivenDirection(eso_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftEsophagus); - if (!found) { // No more Esophagus, I remove the previous point - //DD("no eso pop back"); - p_MostLeftVertebralBody.pop_back(); - } - else { - clitk::PointsUtils::Convert2DTo3D(sp_MostLeftEsophagus, EsophagusForSlice, i, p); - p_MostLeftEsophagus.push_back(p); - } - - /* ------------------------------------------------------------------------------------- - Find most Left point in Aorta - */ - if (found) { - clitk::FindExtremaPointInAGivenDirection(aorta_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftAorta); - sp_MostLeftAorta = clitk::FindExtremaPointInAGivenLine(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::Convert2DTo3D(sp_MostLeftAorta, Aorta, i, p); - p_MostLeftAorta.push_back(p); - } - - } // End of slice loop - - clitk::WriteListOfLandmarks(p_MostLeftVertebralBody, "S8-MostLeft-VB-points.txt"); - // clitk::WriteListOfLandmarks(p_MostRightVertebralBody, "S8-MostRight-VB-points.txt"); - clitk::WriteListOfLandmarks(p_MostLeftAorta, "S8-MostLeft-Aorta-points.txt"); - clitk::WriteListOfLandmarks(p_MostLeftEsophagus, "S8-MostLeft-eso-points.txt"); - - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_Working_Support, - p_MostLeftVertebralBody, p_MostLeftAorta, - GetBackgroundValue(), 0, -10); - - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_Working_Support, - p_MostLeftAorta, p_MostLeftEsophagus, - GetBackgroundValue(), 0, -10); - // END - StopCurrentStep(m_Working_Support); - m_ListOfStations["8"] = m_Working_Support; - return; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStation_8_Remove_Structures() -{ - //-------------------------------------------------------------------- - Remove_Structures("8", "Aorta"); - Remove_Structures("8", "Esophagus"); - Remove_Structures("8", "VertebralBody"); - - // END - StopCurrentStep(m_Working_Support); - m_ListOfStations["8"] = m_Working_Support; - return; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -FindExtremaPointsInBronchus(MaskImagePointer input, - int direction, - double distance_max_from_center_point, - ListOfPointsType & LR, - ListOfPointsType & Ant, - ListOfPointsType & Post) -{ - - // Other solution ==> with auto bounding box ! (but pb to prevent to - // be too distant from the center point - - // Extract slices - std::vector slices; - clitk::ExtractSlices(input, 2, slices); - - // Loop on slices - bool found; - for(uint i=0; i(slices[i], 0, true, 10); - slices[i] = KeepLabels(slices[i], - GetBackgroundValue(), - GetForegroundValue(), 1, 1, true); - */ - - // ------- Find rightmost or leftmost point ------- - MaskSliceType::PointType LRMost; - found = - clitk::FindExtremaPointInAGivenDirection(slices[i], - GetBackgroundValue(), - 0, // axis XY - (direction==0?false:true), // right or left according to direction - LRMost); - // ------- Find postmost point ------- - MaskSliceType::PointType postMost; - found = - clitk::FindExtremaPointInAGivenDirection(slices[i], - GetBackgroundValue(), - 1, false, LRMost, - distance_max_from_center_point, - postMost); - // ------- Find antmost point ------- - MaskSliceType::PointType antMost; - found = - clitk::FindExtremaPointInAGivenDirection(slices[i], - GetBackgroundValue(), - 1, true, LRMost, - distance_max_from_center_point, - antMost); - // Only add point if found - if (found) { - // ------- Convert 2D to 3D points -------- - MaskImageType::PointType p; - clitk::PointsUtils::Convert2DTo3D(LRMost, input, i, p); - LR.push_back(p); - clitk::PointsUtils::Convert2DTo3D(antMost, input, i, p); - Ant.push_back(p); - clitk::PointsUtils::Convert2DTo3D(postMost, input, i, p); - Post.push_back(p); - } - } -} -//-------------------------------------------------------------------- diff --git a/segmentation/clitkExtractLymphStation_Supports.txx b/segmentation/clitkExtractLymphStation_Supports.txx deleted file mode 100644 index f480d84..0000000 --- a/segmentation/clitkExtractLymphStation_Supports.txx +++ /dev/null @@ -1,594 +0,0 @@ - -#include -#include - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ExtractStationSupports() -{ - // Get initial Mediastinum - m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage("Mediastinum", true); - - // Remove some computed structures - this->GetAFDB()->RemoveTag("CarinaZ"); - this->GetAFDB()->RemoveTag("ApexOfTheChestZ"); - - // Superior and inferior limits. - Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0); - Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]); - - // Read all support limits in a file and apply them - ReadSupportLimits(GetSupportLimitsFilename()); - for(unsigned int i=0; iGetSpacing()[2]); - } - - // S1RL - Support_LeftRight_S1R_S1L(); - - // S2RL - Support_LeftRight_S2R_S2L(); - - // S4RL - Support_LeftRight_S4R_S4L(); - - // Post limits of S1,S2,S4 - Support_Post_S2S4(); - - // S3P : "the anterior border is an imaginary horizontal line - // extending along the posterior wall of the trachea" - StartNewStep("[Support] Ant limits of S3P with trachea"); - m_ListOfSupports["S3P"] = LimitsWithTrachea(m_ListOfSupports["S3P"], 1, 0, 10); - - // S3A : "Posteriorly, the station is limited by station 2R and 2L, - // but excludes the great vessels. An imaginary line joins the - // midpoint of the vessel in the anterior to posterior plane. It is - // here that station 2 contacts station 3a" ===> here limit with - // trachea only - StartNewStep("[Support] Ant limits of S3A with trachea"); - m_ListOfSupports["S3A"] = LimitsWithTrachea(m_ListOfSupports["S3A"], 1, 0, -10); - - // S1RL - posterior limits when SI overlap with S3P - Support_Post_S1_S3P(); - - // S1RL - posterior limits with S2RL above sternal notch - Support_Post_S1_Ant_S2RL(); - - // I will do it later - // Below Carina S7,8,9,10 - m_ListOfSupports["S7"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); - m_ListOfSupports["S8"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); - m_ListOfSupports["S9"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); - m_ListOfSupports["S10"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); - m_ListOfSupports["S11"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); - - // Store image filenames into AFDB - WriteImageSupport("S1R"); WriteImageSupport("S1L"); - WriteImageSupport("S2R"); WriteImageSupport("S2L"); - WriteImageSupport("S3A"); WriteImageSupport("S3P"); - WriteImageSupport("S4R"); WriteImageSupport("S4L"); - WriteImageSupport("S5"); - WriteImageSupport("S6"); - WriteImageSupport("S7"); - WriteImageSupport("S8"); - WriteImageSupport("S9"); - WriteImageSupport("S10"); - WriteImageSupport("S11"); - WriteAFDB(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_SI_Limit(const std::string station_limit, const std::string station, - const std::string structure_limit, const std::string structure, - const double offset) -{ - if (!GetCheckSupportFlag()) - StartNewStep("[Support] "+station_limit+" limit of "+station+" is "+structure_limit+" limit of "+structure); - - // Check - if ((station_limit != "superior") && (station_limit != "inferior")) { - clitkExceptionMacro("Error station_limit must be 'inferior' or 'superior', not '"<< station_limit); - } - if ((structure_limit != "superior") && (structure_limit != "inferior")) { - clitkExceptionMacro("Error structure_limit must be 'inferior' or 'superior', not '"<< structure_limit); - } - - // Get current support - if (m_ListOfSupports.find(station) == m_ListOfSupports.end()) { - // std::cerr << "Warning: support " << station << " not initialized" << std::endl; - m_ListOfSupports[station] = m_Mediastinum; - } - m_Working_Support = m_ListOfSupports[station]; - - // Get structure or structureZ - double z=0.; - int found=0; - std::string file; - - // Try to load structure and compute extrema point - if (this->GetAFDB()->TagExist(structure)) { - MaskImagePointer Structure = this->GetAFDB()->template GetImage (structure); - file = this->GetAFDB()->GetTagValue(structure); - MaskImagePointType p; - p[0] = p[1] = p[2] = 0.0; // to avoid warning - if (structure_limit == "superior") - clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, false, p); - else - clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, true, p); - z = p[2]; - found=1; - } - - // Try to load structureZ - if ((found==0) && (this->GetAFDB()->TagExist(structure+"Z"))) { - z = this->GetAFDB()->GetDouble(structure+"Z"); - found=2; - } - - // Try to load structurePoint - if ((found==0) && (this->GetAFDB()->TagExist(structure+"Point"))) { - MaskImagePointType p; - this->GetAFDB()->GetPoint3D(structure+"Point", p); - z = p[2]; - found=3; - } - - // Try to see if it is an already computed support - if (found==0) { - if (m_ListOfSupports.find(structure) != m_ListOfSupports.end()) { - MaskImagePointer Structure = m_ListOfSupports[structure]; - MaskImagePointType p; - if (structure_limit == "superior") - clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, false, p); - else - clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, true, p); - z = p[2]; - found=4; - } - } - - // Try special case : "FindApexOfTheChest" - if (structure == "FindApexOfTheChest") { - z = FindApexOfTheChest(); - found=5; - } - if (structure == "FindInferiorBorderOfAorticArch") { - z = FindInferiorBorderOfAorticArch(); - found=6; - } - if (structure == "FindSuperiorBorderOfAorticArch") { - z = FindSuperiorBorderOfAorticArch(); - found=6; - } - - // If we find anything - if (found == 0) { - std::cerr << "ERROR : I could not find " << structure << " nor " << structure << "Z nor " - << structure << "Point" << std::endl; - exit(EXIT_FAILURE); - } - - // Apply offset - z += offset; - - // Remove Lower or greater - if (station_limit == "inferior") { - m_Working_Support = - clitk::CropImageRemoveLowerThan(m_Working_Support, 2, z, true, GetBackgroundValue()); - } - else { - m_Working_Support = - clitk::CropImageRemoveGreaterThan(m_Working_Support, 2, z, true, GetBackgroundValue()); - } - - // Check: if reference station is given, display information - if (GetCheckSupportFlag()) { - try { - MaskImagePointer Ref = this->GetAFDB()->template GetImage (station+"_Ref"); - MaskImagePointType p_support; - MaskImagePointType p_ref; - if (station_limit == "superior") { - clitk::FindExtremaPointInAGivenDirection(Ref, GetBackgroundValue(), 2, false, p_ref); - clitk::FindExtremaPointInAGivenDirection(m_Working_Support, GetBackgroundValue(), 2, false, p_support); - } - else { - clitk::FindExtremaPointInAGivenDirection(Ref, GetBackgroundValue(), 2, true, p_ref); - clitk::FindExtremaPointInAGivenDirection(m_Working_Support, GetBackgroundValue(), 2, true, p_support); - } - std::ostringstream os; - os << "[Support] \t" << station << "\t" << station_limit << " " - << "Z = " << z << std::setprecision(2) << std::fixed - << "\tSupport = " << p_support[2] - << "\tRef = " << p_ref[2] - << "\tdiff = " << p_support[2]-p_ref[2] << "\t" - << structure << " " << structure_limit; - if (found==1) os << " (S "+file+")"; - if (found==2) os << " (Z)"; - if (found==3) os << " (P)"; - if (found==4) os << " (p)"; - if (found==5) os << " (Apex)"; - if (found==6) os << " (AorticArch)"; - StartNewStep(os.str()); - } catch(clitk::ExceptionObject e) { } - } - - // Set support - m_ListOfSupports[station] = m_Working_Support; - StopCurrentStep(m_Working_Support); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_LeftRight_S1R_S1L() -{ - /* - Medially, station 1R and 1L are separated by the midline of the - trachea, whilst excluding the thyroid gland. - */ - - // Step S1RL : Left-Right - StartNewStep("[Support] Left-Right S1R S1L"); - std::vector A; - std::vector B; - // Search for centroid positions of trachea - MaskImagePointer Trachea = this->GetAFDB()->template GetImage ("Trachea"); - MaskImagePointer S1RL = m_ListOfSupports["S1R"]; - Trachea = clitk::ResizeImageLike(Trachea, S1RL, GetBackgroundValue()); - std::vector slices; - clitk::ExtractSlices(Trachea, 2, slices); - for(uint i=0; i(slices[i], 0, false, 10); - std::vector c; - clitk::ComputeCentroids(slices[i], GetBackgroundValue(), c); - ImagePointType a,b; - clitk::PointsUtils::Convert2DTo3D(c[1], Trachea, i, a); - A.push_back(a); - b = a; - b[1] += 50; - B.push_back(b); - } - clitk::WriteListOfLandmarks(A, "S1LR_A.txt"); - clitk::WriteListOfLandmarks(B, "S1LR_B.txt"); - - // Clone support - MaskImagePointer S1R = clitk::Clone(S1RL); - MaskImagePointer S1L = clitk::Clone(S1RL); - - // Right part - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1R, A, B, - GetBackgroundValue(), 0, -10); - S1R = clitk::AutoCrop(S1R, GetBackgroundValue()); - m_ListOfSupports["S1R"] = S1R; - - // Left part - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1L, A, B, - GetBackgroundValue(), 0, 10); - S1L = clitk::AutoCrop(S1L, GetBackgroundValue()); - m_ListOfSupports["S1L"] = S1L; - StopCurrentStep(m_ListOfSupports["S1L"]); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_LeftRight_S2R_S2L() -{ - // --------------------------------------------------------------------------- - /* Step : S2RL LeftRight As for lymph node station 4R, 2R includes - nodes extending to the left lateral border of the trachea. - - Rod says: "For station 2 there is a shift in the IASLC definition - dividing 2R from 2L, from the midline to the left lateral - tracheal border. This is represented in the atlas as a vertical - line passing tangentially along the left lateral tracheal border - " - */ - StartNewStep("[Support] Separate 2R/2L according to Trachea"); - MaskImagePointer S2R = m_ListOfSupports["S2R"]; - MaskImagePointer S2L = m_ListOfSupports["S2L"]; - S2R = LimitsWithTrachea(S2R, 0, 1, -10); - S2L = LimitsWithTrachea(S2L, 0, 1, 10); - S2R = clitk::AutoCrop(S2R, GetBackgroundValue()); - S2L = clitk::AutoCrop(S2L, GetBackgroundValue()); - m_ListOfSupports["S2R"] = S2R; - m_ListOfSupports["S2L"] = S2L; - this->GetAFDB()->template ReleaseImage("Trachea"); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_LeftRight_S4R_S4L() -{ - // --------------------------------------------------------------------------- - /* - The medial border of station 4R is defined as an imaginary line - running vertically from the left lateral tracheal border. This is - the same medial border as was described for station 2R. - */ - StartNewStep("[Support] Left Right separation of 4R/4L"); - - MaskImagePointer S4R = m_ListOfSupports["S4R"]; - MaskImagePointer S4L = m_ListOfSupports["S4L"]; - S4R = LimitsWithTrachea(S4R, 0, 1, -10); - S4L = LimitsWithTrachea(S4L, 0, 1, 10); - m_ListOfSupports["S4R"] = S4R; - m_ListOfSupports["S4L"] = S4L; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -typename clitk::ExtractLymphStationsFilter::MaskImagePointer -clitk::ExtractLymphStationsFilter:: -LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection, - double offset) -{ - MaskImagePointType min, max; - GetMinMaxBoundary(input, min, max); - return LimitsWithTrachea(input, extremaDirection, lineDirection, offset, max[2]); -} -template -typename clitk::ExtractLymphStationsFilter::MaskImagePointer -clitk::ExtractLymphStationsFilter:: -LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection, - double offset, double maxSupPosition) -{ - /* - Take the input mask, consider the trachea and limit according to - Left border of the trachea. Keep at Left or at Right according to - the offset - */ - // Read the trachea - MaskImagePointer Trachea = this->GetAFDB()->template GetImage("Trachea"); - - // Find extrema post positions - std::vector tracheaLeftPositionsA; - std::vector tracheaLeftPositionsB; - - // Crop Trachea only on the Sup-Inf axes, without autocrop - // Trachea = clitk::ResizeImageLike(Trachea, input, GetBackgroundValue()); - MaskImagePointType min, max; - GetMinMaxBoundary(input, min, max); - Trachea = clitk::CropImageAlongOneAxis(Trachea, 2, min[2], max[2], - false, GetBackgroundValue()); - - // Select the main CCL (because of bronchus) - Trachea = SliceBySliceKeepMainCCL(Trachea, GetBackgroundValue(), GetForegroundValue()); - - // Slice by slice, build the separation line - clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(Trachea, - GetBackgroundValue(), 2, - extremaDirection, false, // Left - lineDirection, // Vertical line - -1, // margins - tracheaLeftPositionsA, - tracheaLeftPositionsB); - // Do not consider trachea above the limit - int indexMax=tracheaLeftPositionsA.size(); - for(uint i=0; i maxSupPosition) { - indexMax = i; - i = tracheaLeftPositionsA.size(); // stop loop - } - } - tracheaLeftPositionsA.erase(tracheaLeftPositionsA.begin()+indexMax, tracheaLeftPositionsA.end()); - tracheaLeftPositionsB.erase(tracheaLeftPositionsB.begin()+indexMax, tracheaLeftPositionsB.end()); - - // Cut post to this line - clitk::SliceBySliceSetBackgroundFromLineSeparation(input, - tracheaLeftPositionsA, - tracheaLeftPositionsB, - GetBackgroundValue(), - extremaDirection, offset); - MaskImagePointer output = clitk::AutoCrop(input, GetBackgroundValue()); - return output; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_Post_S2S4() -{ - StartNewStep("[Support] Post limits of S2RL, S4RL"); - - double m_ApexOfTheChest = FindApexOfTheChest(); - - // Post limits with Trachea - // MaskImagePointer S1R = m_ListOfSupports["S1R"]; - // MaskImagePointer S1L = m_ListOfSupports["S1L"]; - MaskImagePointer S2R = m_ListOfSupports["S2R"]; - MaskImagePointer S2L = m_ListOfSupports["S2L"]; - MaskImagePointer S4R = m_ListOfSupports["S4R"]; - MaskImagePointer S4L = m_ListOfSupports["S4L"]; - // m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest); - // m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest); - m_ListOfSupports["S2R"] = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest); - m_ListOfSupports["S2L"] = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest); - m_ListOfSupports["S4R"] = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest); - m_ListOfSupports["S4L"] = LimitsWithTrachea(S4L, 1, 0, -10, m_ApexOfTheChest); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_Post_S1_S3P() -{ - StartNewStep("[Support] If S1RL and S3P have Sup-Inf overlap, define S1RL posterior limits with S3P anterior limits (post wall trachea)"); - - // Get current supports - MaskImagePointer S1R = m_ListOfSupports["S1R"]; - MaskImagePointer S1L = m_ListOfSupports["S1L"]; - - // Find extrema ant positions for 3P - std::vector A; - std::vector B; - - // Crop S3P like S1R - MaskImagePointer S3P = clitk::Clone(m_ListOfSupports["S3P"]); - S3P = clitk::ResizeImageLike(S3P, S1R, GetBackgroundValue()); - - // Slice by slice, build the separation line - clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(S3P, - GetBackgroundValue(), 2, - 1, true, // Ant-Post - 0, // Horizontal line - 0, // margins - A, B); - - // clitk::WriteListOfLandmarks(A, "A-S1S3P.txt"); - // clitk::WriteListOfLandmarks(B, "B-S1S3P.txt"); - - // Cut post to this line - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1R, A, B, - GetBackgroundValue(), - 1, -10); - - // Crop S3P like S1L (Redo for S1L) - S3P = clitk::Clone(m_ListOfSupports["S3P"]); - S3P = clitk::ResizeImageLike(S3P, S1L, GetBackgroundValue()); - - // Slice by slice, build the separation line - A.clear(); - B.clear(); - clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(S3P, - GetBackgroundValue(), 2, - 1, true, // Ant-Post - 0, // Horizontal line - 0, // margins - A, B); - // Cut post to this line - clitk::SliceBySliceSetBackgroundFromLineSeparation(S1L, A, B, - GetBackgroundValue(), - 1, -10); - - // Crop both images - S1R = clitk::AutoCrop(S1R, GetBackgroundValue()); - S1L = clitk::AutoCrop(S1L, GetBackgroundValue()); - - StopCurrentStep(S1R); - - m_ListOfSupports["S1R"] = S1R; - m_ListOfSupports["S1L"] = S1L; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -Support_Post_S1_Ant_S2RL() -{ - StartNewStep("[Support] Define S1RL posterior limits with S2RL anterior limits when overlap"); - - // Get RightLung - MaskImagePointer RightLung = this->GetAFDB()->template GetImage("RightLung"); - - // Find common area between S1 and S2 - MaskImagePointType p_min; - MaskImagePointType p_max; - clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S2R"], - GetBackgroundValue(), 2, false, p_max); - clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S1R"], - GetBackgroundValue(), 2, true, p_min); - p_min[2] -= RightLung->GetSpacing()[2]; // consider the slice below (remove lower or equal) - p_max[2] += RightLung->GetSpacing()[2]; // consider the slice abov (remove greater or equal) - - if (p_min[2] > p_max[2]) { - - // Crop RightLung - RightLung = clitk::Clone(RightLung); - RightLung = clitk::ResizeImageLike(RightLung, m_ListOfSupports["S1R"], GetBackgroundValue()); - RightLung = clitk::CropImageRemoveLowerThan(RightLung, 2, p_min[2], true, GetBackgroundValue()); - RightLung = clitk::CropImageRemoveGreaterThan(RightLung, 2, p_max[2], true, GetBackgroundValue()); - - // Find extrema ant positions for RightLung - std::vector A; - std::vector B; - clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(RightLung, - GetBackgroundValue(), 2, - 1, true, // Ant-Post - 0, // Horizontal line - 0, // margins - A, B); - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S1R"], - A, B, - GetBackgroundValue(), - 1, -10); - // I add one pixel to abupt S2R to S1R - for(int i=0; iGetSpacing()[1]; - B[i][1] -= RightLung->GetSpacing()[1]; - } - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S2R"], - A, B, - GetBackgroundValue(), - 1, 10); - } - - // Get LeftLung, crop - MaskImagePointer LeftLung = this->GetAFDB()->template GetImage("LeftLung"); - clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S2L"], - GetBackgroundValue(), 2, false, p_max); - clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S1L"], - GetBackgroundValue(), 2, true, p_min); - p_min[2] -= LeftLung->GetSpacing()[2]; // consider the slice below (remove lower or equal) - p_max[2] += LeftLung->GetSpacing()[2]; // consider the slice abov (remove greater or equal) - - if (p_min[2] > p_max[2]) { - LeftLung = clitk::ResizeImageLike(LeftLung, m_ListOfSupports["S1L"], GetBackgroundValue()); - LeftLung = clitk::CropImageRemoveLowerThan(LeftLung, 2, p_min[2], true, GetBackgroundValue()); - LeftLung = clitk::CropImageRemoveGreaterThan(LeftLung, 2, p_max[2], true, GetBackgroundValue()); - - // Find extrema ant positions for LeftLung - std::vector A; - std::vector B; - clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(LeftLung, - GetBackgroundValue(), 2, - 1, true, // Ant-Post - 0, // Horizontal line - 0, // margins - A, B); - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S1L"], - A, B, - GetBackgroundValue(), - 1, -10); - // I add one pixel to abupt S2R to S1R - for(int i=0; iGetSpacing()[1]; - B[i][1] -= LeftLung->GetSpacing()[1]; - } - clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S2L"], - A, B, - GetBackgroundValue(), - 1, 10); - } -} -//-------------------------------------------------------------------- diff --git a/segmentation/clitkExtractLymphStations.cxx b/segmentation/clitkExtractLymphStations.cxx deleted file mode 100644 index 25b5289..0000000 --- a/segmentation/clitkExtractLymphStations.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -======================================================================-====*/ - -// clitk -#include "clitkExtractLymphStations_ggo.h" -#include "clitkExtractLymphStationsGenericFilter.h" - -//-------------------------------------------------------------------- -int main(int argc, char * argv[]) -{ - - // Init command line - GGO(clitkExtractLymphStations, args_info); - CLITK_INIT; - - // Filter - typedef clitk::ExtractLymphStationsGenericFilter FilterType; - FilterType::Pointer filter = FilterType::New(); - - filter->SetArgsInfo(args_info); - - try { - filter->Update(); - } catch(std::runtime_error e) { - std::cout << e.what() << std::endl; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} // This is the end, my friend -//-------------------------------------------------------------------- diff --git a/segmentation/clitkExtractLymphStations.ggo b/segmentation/clitkExtractLymphStations.ggo deleted file mode 100644 index 457f64e..0000000 --- a/segmentation/clitkExtractLymphStations.ggo +++ /dev/null @@ -1,48 +0,0 @@ -#File clitkExtractLymphStations.ggo -package "clitkExtractLymphStations" -version "1.0" -purpose "Extract LymphStations with help of TODO" - -option "config" - "Config file" string no -option "imagetypes" - "Display allowed image types" flag off -option "verbose" v "Verbose" flag off -option "verboseStep" - "Verbose each step" flag off -option "writeStep" w "Write image at each step" flag off -option "verboseOption" - "Display options values" flag off -option "verboseWarningOff" - "Do not display warning" flag off -option "verboseMemory" - "Display memory usage" flag off - -section "I/O" - -option "afdb" a "Input Anatomical Feature DB" string no -option "afdb_path" p "Input path for image in AFDB" string default="./" no -option "input" i "Input filename" string no -option "support_limits" - "Filename to read the support limits" string yes -option "check_support_limits" - "Display stat on the support limits" flag off -option "output" o "Output lungs mask filename" string no - -section "Options for all stations" -option "force_support" - "Force to compute all supports even if already available" flag off -option "station" - "Force to compute this station even if already exist in the DB" string no multiple -option "relpos" - "List of filenames for relativeposition operations" string no multiple - - - -# section "Options for Station 3A" -# section "Options for Station 2RL" -# section "Options for Station 1RL" - -section "Options for Station 8" -option "S8_esophagusDilatationForAnt" - "Dilatation of esophagus, in mm, for 'anterior' limits (default=15,2,1)" double no multiple -option "S8_esophagusDilatationForRight" - "Dilatation of esophagus, in mm, for 'right' limits (default=5,10,1)" double no multiple -option "S8_ft_Esophagus" - "Fuzzy Threshold for 'Post' to dilated Esophagus" double default="0.5" no - -section "Options for Station 7" -option "S7_ft_Bronchi" - "Fuzzy Threshold for Left/Right bronchi" double default="0.1" no -option "S7_ft_LeftSuperiorPulmonaryVein" - "Fuzzy Threshold for LeftSuperiorPulmonaryVein" double default="0.3" no -option "S7_ft_RightSuperiorPulmonaryVein" - "Fuzzy Threshold for RightSuperiorPulmonaryVein" double default="0.2" no -option "S7_ft_RightPulmonaryArtery" - "Fuzzy Threshold for RightPulmonaryArtery" double default="0.3" no -option "S7_ft_LeftPulmonaryArtery" - "Fuzzy Threshold for LeftPulmonaryArtery (NOT USEFUL YET)" double default="0.5" no -option "S7_ft_SVC" - "Fuzzy Threshold for SVC" double default="0.2" no -option "S7_UseMostInferiorPartOnly" - "Inferior separation with S8." flag off - diff --git a/segmentation/clitkExtractLymphStationsFilter.h b/segmentation/clitkExtractLymphStationsFilter.h deleted file mode 100644 index 080bdb7..0000000 --- a/segmentation/clitkExtractLymphStationsFilter.h +++ /dev/null @@ -1,325 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html - ======================================================================-====*/ - -#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_H -#define CLITKEXTRACTLYMPHSTATIONSFILTER_H - -// clitk -#include "clitkStructuresExtractionFilter.h" -#include "clitkLabelImageOverlapMeasureFilter.h" - -// vtk -#include - -namespace clitk { - - class SupportLimitsType { - public: - std::string station_limit; - std::string station; - std::string structure_limit; - std::string structure; - double offset; - void Read(istream & is) { - is >> station_limit; - is >> station; - is >> structure_limit; - is >> structure; - std::string s; - is >> s; - offset = atof(s.c_str()); - } - }; - - //-------------------------------------------------------------------- - /* - Try to extract the LymphStations part of a thorax CT. - Need a set of Anatomical Features (AFDB) - */ - //-------------------------------------------------------------------- - - template - class ITK_EXPORT ExtractLymphStationsFilter: - public clitk::StructuresExtractionFilter - { - - public: - /** Standard class typedefs. */ - typedef clitk::StructuresExtractionFilter Superclass; - typedef ExtractLymphStationsFilter Self; - typedef itk::SmartPointer Pointer; - typedef itk::SmartPointer ConstPointer; - - /** Method for creation through the object factory. */ - itkNewMacro(Self); - - /** Run-time type information (and related methods). */ - itkTypeMacro(ExtractLymphStationsFilter, ImageToImageFilter); - - /** Some convenient typedefs. */ - typedef TImageType ImageType; - typedef typename ImageType::ConstPointer ImageConstPointer; - typedef typename ImageType::Pointer ImagePointer; - typedef typename ImageType::RegionType ImageRegionType; - typedef typename ImageType::PixelType ImagePixelType; - typedef typename ImageType::SizeType ImageSizeType; - typedef typename ImageType::IndexType ImageIndexType; - typedef typename ImageType::PointType ImagePointType; - - typedef uchar MaskImagePixelType; - typedef itk::Image MaskImageType; - typedef typename MaskImageType::Pointer MaskImagePointer; - typedef typename MaskImageType::RegionType MaskImageRegionType; - typedef typename MaskImageType::SizeType MaskImageSizeType; - typedef typename MaskImageType::IndexType MaskImageIndexType; - typedef typename MaskImageType::PointType MaskImagePointType; - - typedef itk::Image MaskSliceType; - typedef typename MaskSliceType::Pointer MaskSlicePointer; - typedef typename MaskSliceType::PointType MaskSlicePointType; - typedef typename MaskSliceType::RegionType MaskSliceRegionType; - typedef typename MaskSliceType::SizeType MaskSliceSizeType; - typedef typename MaskSliceType::IndexType MaskSliceIndexType; - - /** ImageDimension constants */ - itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); - FILTERBASE_INIT; - - itkGetConstMacro(BackgroundValue, MaskImagePixelType); - itkGetConstMacro(ForegroundValue, MaskImagePixelType); - itkSetMacro(BackgroundValue, MaskImagePixelType); - itkSetMacro(ForegroundValue, MaskImagePixelType); - - // Station 8 - itkSetMacro(EsophagusDiltationForAnt, MaskImagePointType); - itkGetConstMacro(EsophagusDiltationForAnt, MaskImagePointType); - itkSetMacro(EsophagusDiltationForRight, MaskImagePointType); - itkGetConstMacro(EsophagusDiltationForRight, MaskImagePointType); - itkSetMacro(InjectedThresholdForS8, double); - itkGetConstMacro(InjectedThresholdForS8, double); - - // Station 7 - itkGetConstMacro(S7_UseMostInferiorPartOnlyFlag, bool); - itkSetMacro(S7_UseMostInferiorPartOnlyFlag, bool); - itkBooleanMacro(S7_UseMostInferiorPartOnlyFlag); - - // All stations - bool GetComputeStation(std::string s); - void AddComputeStation(std::string station) ; - void SetFuzzyThreshold(std::string station, std::string tag, double value); - double GetFuzzyThreshold(std::string station, std::string tag); - void SetThreshold(std::string station, std::string tag, double value); - double GetThreshold(std::string station, std::string tag); - itkGetConstMacro(ForceSupportsFlag, bool); - itkSetMacro(ForceSupportsFlag, bool); - itkBooleanMacro(ForceSupportsFlag); - - itkGetConstMacro(CheckSupportFlag, bool); - itkSetMacro(CheckSupportFlag, bool); - itkBooleanMacro(CheckSupportFlag); - - itkGetConstMacro(SupportLimitsFilename, std::string); - itkSetMacro(SupportLimitsFilename, std::string); - - protected: - ExtractLymphStationsFilter(); - virtual ~ExtractLymphStationsFilter() {} - - virtual void GenerateOutputInformation(); - virtual void GenerateInputRequestedRegion(); - virtual void GenerateData(); - - // To avoid repeat "this->" - AnatomicalFeatureDatabase * GetAFDB() { return clitk::FilterWithAnatomicalFeatureDatabaseManagement::GetAFDB(); } - void WriteAFDB() { clitk::FilterWithAnatomicalFeatureDatabaseManagement::WriteAFDB(); } - void LoadAFDB() { clitk::FilterWithAnatomicalFeatureDatabaseManagement::LoadAFDB(); } - void StartNewStep(std::string s) { clitk::FilterBase::StartNewStep(s); } - void StartSubStep() { clitk::FilterBase::StartSubStep(); } - template - void StopCurrentStep(typename TInternalImageType::Pointer p, std::string txt="") { clitk::FilterBase::StopCurrentStep(p, txt); } - void StopCurrentStep() {clitk::FilterBase::StopCurrentStep(); } - void StopSubStep() {clitk::FilterBase::StopSubStep(); } - - ImageConstPointer m_Input; - MaskImagePointer m_Mediastinum; - MaskImagePointer m_Working_Support; - std::map m_ListOfStations; - std::map m_ListOfSupports; - MaskImagePixelType m_BackgroundValue; - MaskImagePixelType m_ForegroundValue; - std::map m_ComputeStationMap; - std::string m_SupportLimitsFilename; - std::vector m_ListOfSupportLimits; - - bool CheckForStation(std::string station); - void Remove_Structures(std::string station, std::string s); - void WriteImageSupport(std::string support); - void WriteImageStation(std::string station); - void ComputeOverlapWithRef(std::string station); - void Support_SI_Limit(const std::string station_limit, const std::string station, - const std::string structure_limit, const std::string structure, - const double offset); - void ReadSupportLimits(std::string filename); - - // Functions common to several stations - double FindCarina(); - double FindApexOfTheChest(); - double FindSuperiorBorderOfAorticArch(); - double FindInferiorBorderOfAorticArch(); - void FindLeftAndRightBronchi(); - void FindLineForS7S8Separation(MaskImagePointType & A, MaskImagePointType & B); - MaskImagePointer FindAntPostVesselsOLD(); - MaskImagePointer FindAntPostVessels2(); - - // Global parameters - typedef std::map FuzzyThresholdByStructureType; - std::map m_FuzzyThreshold; - typedef std::map ThresholdByStructureType; - std::map m_Threshold; - - // Station's supports - void ExtractStationSupports(); - void Support_LeftRight_S1R_S1L(); - void Support_LeftRight_S2R_S2L(); - void Support_LeftRight_S4R_S4L(); - void Support_Post_S1S2S4(); - - MaskImagePointer LimitsWithTrachea(MaskImageType * input, - int extremaDirection, int lineDirection, - double offset, double maxSupPosition); - MaskImagePointer LimitsWithTrachea(MaskImageType * input, - int extremaDirection, int lineDirection, - double offset); - // Station 8 - double m_DiaphragmInferiorLimit; - double m_OriginOfRightMiddleLobeBronchusZ; - double m_InjectedThresholdForS8; - MaskImagePointer m_Esophagus; - MaskImagePointType m_EsophagusDiltationForAnt; - MaskImagePointType m_EsophagusDiltationForRight; - - void ExtractStation_8(); - void ExtractStation_8_SetDefaultValues(); - void ExtractStation_8_SI_Limits(); - void ExtractStation_8_Ant_Limits(); - void ExtractStation_8_Left_Sup_Limits(); - void ExtractStation_8_Left_Inf_Limits(); - void ExtractStation_8_Single_CCL_Limits(); - void ExtractStation_8_Remove_Structures(); - - // Station 3P - void ExtractStation_3P(); - void ExtractStation_3P_SetDefaultValues(); - void ExtractStation_3P_LR_inf_Limits(); - void ExtractStation_3P_LR_sup_Limits_2(); - void ExtractStation_3P_Remove_Structures(); - void ExtractStation_3P_LR_sup_Limits(); - - // Station 3A - void ExtractStation_3A(); - void ExtractStation_3A_SetDefaultValues(); - void ExtractStation_3A_Post_Left_Limits_With_Aorta_S5_Support(); - void ExtractStation_3A_Post_Limits_With_Dilated_Aorta_S6_Support(); - void ExtractStation_3A_AntPost_Superiorly(); - void ExtractStation_3A_Remove_Structures(); - - // Station 2RL - void ExtractStation_2RL(); - void ExtractStation_2RL_SetDefaultValues(); - void ExtractStation_2RL_Ant_Limits(std::string s); - void ExtractStation_2RL_Remove_Structures(std::string s); - void ExtractStation_2RL_Cut_BrachioCephalicVein_superiorly_when_it_split(); - vtkSmartPointer Build3DMeshFrom2DContour(const std::vector & points); - - // Station 1RL - void ExtractStation_1RL(); - void ExtractStation_1RL_SetDefaultValues(); - void ExtractStation_1RL_Ant_Limits(); - void ExtractStation_1RL_Post_Limits(); - - // Station 4RL - void ExtractStation_4RL_SetDefaultValues(); - void ExtractStation_4L(); - void ExtractStation_4R(); - void ExtractStation_S4L_S5_Limits_Aorta_LeftPulmonaryArtery(int KeepPoint); - - // Station 5 - void ExtractStation_5_SetDefaultValues(); - void ExtractStation_5(); - void ExtractStation_5_Limits_AscendingAorta_Ant(); - - // Station 6 - void ExtractStation_6_SetDefaultValues(); - void ExtractStation_6(); - - - // Station 7 - void ExtractStation_7(); - void ExtractStation_7_SetDefaultValues(); - void ExtractStation_7_SI_Limits(); - void ExtractStation_7_RL_Interior_Limits(); - - void ExtractStation_7_RL_Limits_OLD(); - void ExtractStation_7_Posterior_Limits(); - void ExtractStation_7_Remove_Structures(); - bool m_S7_UseMostInferiorPartOnlyFlag; - bool m_ForceSupportsFlag; - bool m_CheckSupportFlag; - MaskImagePointer m_Working_Trachea; - MaskImagePointer m_LeftBronchus; - MaskImagePointer m_RightBronchus; - typedef std::vector ListOfPointsType; - ListOfPointsType m_RightMostInLeftBronchus; - ListOfPointsType m_AntMostInLeftBronchus; - ListOfPointsType m_PostMostInLeftBronchus; - ListOfPointsType m_LeftMostInRightBronchus; - ListOfPointsType m_AntMostInRightBronchus; - ListOfPointsType m_PostMostInRightBronchus; - - void FindExtremaPointsInBronchus(MaskImagePointer input, - int direction, - double distance_max_from_center_point, - ListOfPointsType & LR, - ListOfPointsType & Ant, - ListOfPointsType & Post); - private: - ExtractLymphStationsFilter(const Self&); //purposely not implemented - void operator=(const Self&); //purposely not implemented - - }; // end class - //-------------------------------------------------------------------- - -} // end namespace clitk -//-------------------------------------------------------------------- - -#ifndef ITK_MANUAL_INSTANTIATION -#include "clitkExtractLymphStationsFilter.txx" -#include "clitkExtractLymphStation_Supports.txx" -#include "clitkExtractLymphStation_3P.txx" -#include "clitkExtractLymphStation_2RL.txx" -#include "clitkExtractLymphStation_3A.txx" -#include "clitkExtractLymphStation_4RL.txx" -#include "clitkExtractLymphStation_1RL.txx" -#include "clitkExtractLymphStation_5.txx" -#include "clitkExtractLymphStation_6.txx" - -#include "clitkExtractLymphStation_8.txx" -#include "clitkExtractLymphStation_7.txx" -#endif - -#endif diff --git a/segmentation/clitkExtractLymphStationsFilter.txx b/segmentation/clitkExtractLymphStationsFilter.txx deleted file mode 100644 index 64455a8..0000000 --- a/segmentation/clitkExtractLymphStationsFilter.txx +++ /dev/null @@ -1,1481 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html - ======================================================================-====*/ - -#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_TXX -#define CLITKEXTRACTLYMPHSTATIONSFILTER_TXX - -// clitk -#include "clitkCommon.h" -#include "clitkExtractLymphStationsFilter.h" -#include "clitkAddRelativePositionConstraintToLabelImageFilter.h" -#include "clitkSegmentationUtils.h" -#include "clitkAutoCropFilter.h" -#include "clitkSegmentationUtils.h" -#include "clitkSliceBySliceRelativePositionFilter.h" -#include "clitkMeshToBinaryImageFilter.h" - -// itk -#include -#include -#include -#include -#include -#include -#include - -// itk ENST -#include "RelativePositionPropImageFilter.h" - -// vtk -#include -#include -#include - -//-------------------------------------------------------------------- -template -clitk::ExtractLymphStationsFilter:: -ExtractLymphStationsFilter(): - clitk::StructuresExtractionFilter() -{ - this->SetNumberOfRequiredInputs(1); - SetBackgroundValue(0); - SetForegroundValue(1); - ForceSupportsFlagOn(); - SetSupportLimitsFilename("none"); - CheckSupportFlagOff(); - - // Default values - ExtractStation_3P_SetDefaultValues(); - ExtractStation_2RL_SetDefaultValues(); - ExtractStation_3A_SetDefaultValues(); - ExtractStation_1RL_SetDefaultValues(); - ExtractStation_4RL_SetDefaultValues(); - ExtractStation_5_SetDefaultValues(); - ExtractStation_6_SetDefaultValues(); - - // TODO - ExtractStation_7_SetDefaultValues(); - ExtractStation_8_SetDefaultValues(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -GenerateOutputInformation() { - // Get inputs - this->LoadAFDB(); - m_Input = dynamic_cast(itk::ProcessObject::GetInput(0)); - m_Mediastinum = this->GetAFDB()->template GetImage ("Mediastinum"); - - // DD(this->GetVerboseMemoryFlag()); - // clitk::PrintMemory(this->GetVerboseMemoryFlag(), "Start"); - - // Clean some computer landmarks to force the recomputation - // FIXME -> to put elsewhere ? - this->GetAFDB()->RemoveTag("AntPostVesselsSeparation"); - - // Must I compute the supports ? - bool supportsExist = true; - if (!GetForceSupportsFlag()) { - try { - m_ListOfSupports["S1R"] = this->GetAFDB()->template GetImage("Support_S1R"); - m_ListOfSupports["S1L"] = this->GetAFDB()->template GetImage("Support_S1L"); - m_ListOfSupports["S2R"] = this->GetAFDB()->template GetImage("Support_S2R"); - m_ListOfSupports["S2L"] = this->GetAFDB()->template GetImage("Support_S2L"); - m_ListOfSupports["S4R"] = this->GetAFDB()->template GetImage("Support_S4R"); - m_ListOfSupports["S4L"] = this->GetAFDB()->template GetImage("Support_S4L"); - - m_ListOfSupports["S3A"] = this->GetAFDB()->template GetImage("Support_S3A"); - m_ListOfSupports["S3P"] = this->GetAFDB()->template GetImage("Support_S3P"); - m_ListOfSupports["S5"] = this->GetAFDB()->template GetImage("Support_S5"); - m_ListOfSupports["S6"] = this->GetAFDB()->template GetImage("Support_S6"); - m_ListOfSupports["S7"] = this->GetAFDB()->template GetImage("Support_S7"); - m_ListOfSupports["S8"] = this->GetAFDB()->template GetImage("Support_S8"); - m_ListOfSupports["S9"] = this->GetAFDB()->template GetImage("Support_S9"); - m_ListOfSupports["S10"] = this->GetAFDB()->template GetImage("Support_S10"); - m_ListOfSupports["S11"] = this->GetAFDB()->template GetImage("Support_S11"); - } catch(clitk::ExceptionObject o) { - supportsExist = false; - } - } - - if (!supportsExist || GetForceSupportsFlag()) { - this->StartNewStep("Supports for stations"); - this->StartSubStep(); - - // FIXME : why should I remove theses tags ??? - this->GetAFDB()->RemoveTag("CarinaZ"); - this->GetAFDB()->RemoveTag("ApexOfTheChestZ"); - this->GetAFDB()->RemoveTag("ApexOfTheChest"); - this->GetAFDB()->RemoveTag("RightBronchus"); - this->GetAFDB()->RemoveTag("LeftBronchus"); - this->GetAFDB()->RemoveTag("SuperiorBorderOfAorticArchZ"); - this->GetAFDB()->RemoveTag("SuperiorBorderOfAorticArch"); - this->GetAFDB()->RemoveTag("InferiorBorderOfAorticArchZ"); - this->GetAFDB()->RemoveTag("InferiorBorderOfAorticArch"); - ExtractStationSupports(); - this->StopSubStep(); - } - - // Extract Stations - ExtractStation_1RL(); - ExtractStation_2RL(); - ExtractStation_3P(); - ExtractStation_3A(); - ExtractStation_4R(); - ExtractStation_4L(); - ExtractStation_5(); - ExtractStation_6(); - - // ---------- todo ----------------------- - - // Extract Station8 - // ExtractStation_8(); - - // Extract Station7 - //this->StartNewStep("Station 7"); - //this->StartSubStep(); - //ExtractStation_7(); - //this->StopSubStep(); - -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -GenerateInputRequestedRegion() { - //DD("GenerateInputRequestedRegion (nothing?)"); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -GenerateData() { - // Final Step -> graft output (if SetNthOutput => redo) - // this->GraftOutput(m_ListOfStations["8"]); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -bool -clitk::ExtractLymphStationsFilter:: -CheckForStation(std::string station) -{ - // Compute Station name - std::string s = "Station"+station; - - - // Define the starting support - // if (GetComputeStation(station)) { - // std::cout << "Station " << station << " already exists, but re-computation forced." << std::endl; - // } - if (GetComputeStation(station)) { - m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage("Mediastinum", true); - return true; - } - else return false; - // else { - // std::cout << "Station " << station << " found. I used it" << std::endl; - // return false; - // } - - // Check if station already exist in DB - - // FIXME -> do nothing if not on the command line. Is it what I want ? - //bool found = false; - if (this->GetAFDB()->TagExist(s)) { - m_ListOfStations[station] = this->GetAFDB()->template GetImage(s); - //found = true; - } - -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -bool -clitk::ExtractLymphStationsFilter:: -GetComputeStation(std::string station) -{ - return (m_ComputeStationMap.find(station) != m_ComputeStationMap.end()); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -AddComputeStation(std::string station) -{ - m_ComputeStationMap[station] = true; -} -//-------------------------------------------------------------------- - - - -//-------------------------------------------------------------------- -template -class comparePointsX { -public: - bool operator() (PointType i, PointType j) { return (i[0] -class comparePointsWithAngle { -public: - bool operator() (PairType i, PairType j) { return (i.second < j.second); } -}; -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void HypercubeCorners(std::vector > & out) { - std::vector > previous; - HypercubeCorners(previous); - out.resize(previous.size()*2); - for(unsigned int i=0; i p; - if (i -void HypercubeCorners<1>(std::vector > & out) { - out.resize(2); - out[0][0] = 0; - out[1][0] = 1; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void ComputeImageBoundariesCoordinates(typename ImageType::Pointer image, - std::vector & bounds) -{ - // Get image max/min coordinates - const unsigned int dim=ImageType::ImageDimension; - typedef typename ImageType::PointType PointType; - typedef typename ImageType::IndexType IndexType; - PointType min_c, max_c; - IndexType min_i, max_i; - min_i = image->GetLargestPossibleRegion().GetIndex(); - for(unsigned int i=0; iGetLargestPossibleRegion().GetSize()[i] + min_i[i]; - image->TransformIndexToPhysicalPoint(min_i, min_c); - image->TransformIndexToPhysicalPoint(max_i, max_c); - - // Get corners coordinates - HypercubeCorners(bounds); - for(unsigned int i=0; i -void -clitk::ExtractLymphStationsFilter:: -Remove_Structures(std::string station, std::string s) -{ - try { - this->StartNewStep("[Station"+station+"] Remove "+s); - MaskImagePointer Structure = this->GetAFDB()->template GetImage(s); - clitk::AndNot(m_Working_Support, Structure, GetBackgroundValue()); - } - catch(clitk::ExceptionObject e) { - std::cout << s << " not found, skip." << std::endl; - } -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -SetFuzzyThreshold(std::string station, std::string tag, double value) -{ - m_FuzzyThreshold[station][tag] = value; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -SetThreshold(std::string station, std::string tag, double value) -{ - m_Threshold[station][tag] = value; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -double -clitk::ExtractLymphStationsFilter:: -GetFuzzyThreshold(std::string station, std::string tag) -{ - if (m_FuzzyThreshold.find(station) == m_FuzzyThreshold.end()) { - clitkExceptionMacro("Could not find options for station "+station+" in the list (while searching for tag "+tag+")."); - return 0.0; - } - - if (m_FuzzyThreshold[station].find(tag) == m_FuzzyThreshold[station].end()) { - clitkExceptionMacro("Could not find options "+tag+" in the list of FuzzyThreshold for station "+station+"."); - return 0.0; - } - - return m_FuzzyThreshold[station][tag]; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -double -clitk::ExtractLymphStationsFilter:: -GetThreshold(std::string station, std::string tag) -{ - if (m_Threshold.find(station) == m_Threshold.end()) { - clitkExceptionMacro("Could not find options for station "+station+" in the list (while searching for tag "+tag+")."); - return 0.0; - } - - if (m_Threshold[station].find(tag) == m_Threshold[station].end()) { - clitkExceptionMacro("Could not find options "+tag+" in the list of Threshold for station "+station+"."); - return 0.0; - } - - return m_Threshold[station][tag]; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -FindLineForS7S8Separation(MaskImagePointType & A, MaskImagePointType & B) -{ - // Create line from A to B with - // A = upper border of LLL at left - // B = lower border of bronchus intermedius (BI) or RightMiddleLobeBronchus - - try { - this->GetAFDB()->GetPoint3D("LineForS7S8Separation_Begin", A); - this->GetAFDB()->GetPoint3D("LineForS7S8Separation_End", B); - } - catch(clitk::ExceptionObject & o) { - - DD("FindLineForS7S8Separation"); - // Load LeftLowerLobeBronchus and get centroid point - MaskImagePointer LeftLowerLobeBronchus = - this->GetAFDB()->template GetImage ("LeftLowerLobeBronchus"); - std::vector c; - clitk::ComputeCentroids(LeftLowerLobeBronchus, GetBackgroundValue(), c); - A = c[1]; - - // Load RightMiddleLobeBronchus and get superior point (not centroid here) - MaskImagePointer RightMiddleLobeBronchus = - this->GetAFDB()->template GetImage ("RightMiddleLobeBronchus"); - bool b = FindExtremaPointInAGivenDirection(RightMiddleLobeBronchus, - GetBackgroundValue(), - 2, false, B); - if (!b) { - clitkExceptionMacro("Error while searching most superior point in RightMiddleLobeBronchus. Abort"); - } - - // Insert into the DB - this->GetAFDB()->SetPoint3D("LineForS7S8Separation_Begin", A); - this->GetAFDB()->SetPoint3D("LineForS7S8Separation_End", B); - } -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -double -clitk::ExtractLymphStationsFilter:: -FindCarina() -{ - double z; - try { - z = this->GetAFDB()->GetDouble("CarinaZ"); - } - catch(clitk::ExceptionObject e) { - //DD("FindCarinaSlicePosition"); - // Get Carina - MaskImagePointer Carina = this->GetAFDB()->template GetImage("Carina"); - - // Get Centroid and Z value - std::vector centroids; - clitk::ComputeCentroids(Carina, GetBackgroundValue(), centroids); - - // We dont need Carina structure from now - this->GetAFDB()->template ReleaseImage("Carina"); - - // Put inside the AFDB - this->GetAFDB()->SetPoint3D("CarinaPoint", centroids[1]); - this->GetAFDB()->SetDouble("CarinaZ", centroids[1][2]); - this->WriteAFDB(); - z = centroids[1][2]; - } - return z; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -double -clitk::ExtractLymphStationsFilter:: -FindApexOfTheChest() -{ - double z; - try { - z = this->GetAFDB()->GetDouble("ApexOfTheChestZ"); - } - catch(clitk::ExceptionObject e) { - - /* - //DD("FindApexOfTheChestPosition"); - MaskImagePointer Lungs = this->GetAFDB()->template GetImage("Lungs"); - MaskImagePointType p; - p[0] = p[1] = p[2] = 0.0; // to avoid warning - clitk::FindExtremaPointInAGivenDirection(Lungs, GetBackgroundValue(), 2, false, p); - - // We dont need Lungs structure from now - this->GetAFDB()->template ReleaseImage("Lungs"); - - // Put inside the AFDB - this->GetAFDB()->SetPoint3D("ApexOfTheChest", p); - p[2] -= 5; // We consider 5 mm lower - this->GetAFDB()->SetDouble("ApexOfTheChestZ", p[2]); - this->WriteAFDB(); - z = p[2]; - */ - - // the superior border becomes the more inferior of the two apices - MaskImagePointer RightLung = this->GetAFDB()->template GetImage("RightLung"); - MaskImagePointer LeftLung = this->GetAFDB()->template GetImage("LeftLung"); - MaskImagePointType pr; - MaskImagePointType pl; - clitk::FindExtremaPointInAGivenDirection(RightLung, GetBackgroundValue(), 2, false, pr); - clitk::FindExtremaPointInAGivenDirection(LeftLung, GetBackgroundValue(), 2, false, pl); - // We dont need Lungs structure from now - this->GetAFDB()->template ReleaseImage("RightLung"); - this->GetAFDB()->template ReleaseImage("LeftLung"); - // Put inside the AFDB - if (pr[2] < pl[2]) z = pr[2]; - else z = pl[2]; - this->GetAFDB()->SetDouble("ApexOfTheChestZ", z); - this->WriteAFDB(); - } - return z; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -FindLeftAndRightBronchi() -{ - try { - m_RightBronchus = this->GetAFDB()->template GetImage ("RightBronchus"); - m_LeftBronchus = this->GetAFDB()->template GetImage ("LeftBronchus"); - } - catch(clitk::ExceptionObject & o) { - - DD("FindLeftAndRightBronchi"); - // The goal is to separate the trachea inferiorly to the carina into - // a Left and Right bronchus. - - // Get the trachea - MaskImagePointer Trachea = this->GetAFDB()->template GetImage("Trachea"); - - // Get the Carina position - double m_CarinaZ = FindCarina(); - - // Consider only inferiorly to the Carina - MaskImagePointer m_Working_Trachea = - clitk::CropImageRemoveGreaterThan(Trachea, 2, m_CarinaZ, true, // AutoCrop - GetBackgroundValue()); - - // Labelize the trachea - m_Working_Trachea = Labelize(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 - MaskImagePointer RightBronchus; - MaskImagePointer LeftBronchus; - typedef itk::ImageSliceIteratorWithIndex 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 from 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 c; - clitk::ComputeCentroids(m_Working_Trachea, GetBackgroundValue(), c); - ImagePointType C1 = c[1]; - ImagePointType C2 = c[2]; - - ImagePixelType rightLabel; - ImagePixelType leftLabel; - if (C1[0] < C2[0]) { rightLabel = 1; leftLabel = 2; } - else { rightLabel = 2; leftLabel = 1; } - - // Select LeftLabel (set one label to Backgroundvalue) - RightBronchus = - clitk::Binarize(m_Working_Trachea, rightLabel, rightLabel, - GetBackgroundValue(), GetForegroundValue()); - /* - SetBackground(m_Working_Trachea, m_Working_Trachea, - leftLabel, GetBackgroundValue(), false); - */ - LeftBronchus = clitk::Binarize(m_Working_Trachea, leftLabel, leftLabel, - GetBackgroundValue(), GetForegroundValue()); - /* - SetBackground(m_Working_Trachea, m_Working_Trachea, - rightLabel, GetBackgroundValue(), false); - */ - - // Crop images - RightBronchus = clitk::AutoCrop(RightBronchus, GetBackgroundValue()); - LeftBronchus = clitk::AutoCrop(LeftBronchus, GetBackgroundValue()); - - // Insert int AFDB if need after - this->GetAFDB()->template SetImage ("RightBronchus", "seg/rightBronchus.mhd", - RightBronchus, true); - this->GetAFDB()->template SetImage ("LeftBronchus", "seg/leftBronchus.mhd", - LeftBronchus, true); - } -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -double -clitk::ExtractLymphStationsFilter:: -FindSuperiorBorderOfAorticArch() -{ - double z; - try { - z = this->GetAFDB()->GetDouble("SuperiorBorderOfAorticArchZ"); - } - catch(clitk::ExceptionObject e) { - // DD("FindSuperiorBorderOfAorticArch"); - MaskImagePointer Aorta = this->GetAFDB()->template GetImage("Aorta"); - MaskImagePointType p; - p[0] = p[1] = p[2] = 0.0; // to avoid warning - clitk::FindExtremaPointInAGivenDirection(Aorta, GetBackgroundValue(), 2, false, p); - p[2] += Aorta->GetSpacing()[2]; // the slice above - - // We dont need Lungs structure from now - this->GetAFDB()->template ReleaseImage("Aorta"); - - // Put inside the AFDB - this->GetAFDB()->SetPoint3D("SuperiorBorderOfAorticArch", p); - this->GetAFDB()->SetDouble("SuperiorBorderOfAorticArchZ", p[2]); - this->WriteAFDB(); - z = p[2]; - } - return z; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -double -clitk::ExtractLymphStationsFilter:: -FindInferiorBorderOfAorticArch() -{ - double z; - try { - z = this->GetAFDB()->GetDouble("InferiorBorderOfAorticArchZ"); - } - catch(clitk::ExceptionObject e) { - //DD("FindInferiorBorderOfAorticArch"); - MaskImagePointer Aorta = this->GetAFDB()->template GetImage("Aorta"); - std::vector slices; - clitk::ExtractSlices(Aorta, 2, slices); - bool found=false; - uint i = slices.size()-1; - while (!found) { - slices[i] = Labelize(slices[i], 0, false, 10); - std::vector c; - clitk::ComputeCentroids(slices[i], GetBackgroundValue(), c); - if (c.size()>2) { - found = true; - } - else { - i--; - } - } - MaskImageIndexType index; - index[0] = index[1] = 0.0; - index[2] = i+1; - MaskImagePointType lower; - Aorta->TransformIndexToPhysicalPoint(index, lower); - - // We dont need Lungs structure from now - this->GetAFDB()->template ReleaseImage("Aorta"); - - // Put inside the AFDB - this->GetAFDB()->SetPoint3D("InferiorBorderOfAorticArch", lower); - this->GetAFDB()->SetDouble("InferiorBorderOfAorticArchZ", lower[2]); - this->WriteAFDB(); - z = lower[2]; - } - return z; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -typename clitk::ExtractLymphStationsFilter::MaskImagePointer -clitk::ExtractLymphStationsFilter:: -FindAntPostVesselsOLD() -{ - // ----------------------------------------------------- - /* Rod says: "The anterior border, as with the Atlas – UM, is - posterior to the vessels (right subclavian vein, left - brachiocephalic vein, right brachiocephalic vein, left subclavian - artery, left common carotid artery and brachiocephalic trunk). - These vessels are not included in the nodal station. The anterior - border is drawn to the midpoint of the vessel and an imaginary - line joins the middle of these vessels. Between the vessels, - station 2 is in contact with station 3a." */ - - // Check if no already done - bool found = true; - MaskImagePointer binarizedContour; - try { - binarizedContour = this->GetAFDB()->template GetImage ("AntPostVesselsSeparation"); - } - catch(clitk::ExceptionObject e) { - found = false; - } - if (found) { - return binarizedContour; - } - - /* Here, we consider the vessels form a kind of anterior barrier. We - link all vessels centroids and remove what is post to it. - - select the list of structure - vessel1 = BrachioCephalicArtery - vessel2 = BrachioCephalicVein (warning several CCL, keep most at Right) - vessel3 = CommonCarotidArtery - vessel4 = SubclavianArtery - other = Thyroid - other = Aorta - - crop images as needed - - slice by slice, choose the CCL and extract centroids - - slice by slice, sort according to polar angle wrt Trachea centroid. - - slice by slice, link centroids and close contour - - remove outside this contour - - merge with support - */ - - // Read structures - MaskImagePointer BrachioCephalicArtery = this->GetAFDB()->template GetImage("BrachioCephalicArtery"); - MaskImagePointer BrachioCephalicVein = this->GetAFDB()->template GetImage("BrachioCephalicVein"); - MaskImagePointer CommonCarotidArtery = this->GetAFDB()->template GetImage("CommonCarotidArtery"); - MaskImagePointer SubclavianArtery = this->GetAFDB()->template GetImage("SubclavianArtery"); - MaskImagePointer Thyroid = this->GetAFDB()->template GetImage("Thyroid"); - MaskImagePointer Aorta = this->GetAFDB()->template GetImage("Aorta"); - MaskImagePointer Trachea = this->GetAFDB()->template GetImage("Trachea"); - - // Create a temporay support - // From first slice of BrachioCephalicVein to end of 3A - MaskImagePointer support = this->GetAFDB()->template GetImage("Support_Sup_Carina"); - MaskImagePointType p; - p[0] = p[1] = p[2] = 0.0; // to avoid warning - clitk::FindExtremaPointInAGivenDirection(BrachioCephalicVein, GetBackgroundValue(), 2, true, p); - double inf = p [2]; - clitk::FindExtremaPointInAGivenDirection(this->GetAFDB()->template GetImage("Support_S3A"), - GetBackgroundValue(), 2, false, p); - double sup = p [2]; - support = clitk::CropImageAlongOneAxis(support, 2, inf, sup, - false, GetBackgroundValue()); - - // Resize all structures like support - BrachioCephalicArtery = - clitk::ResizeImageLike(BrachioCephalicArtery, support, GetBackgroundValue()); - CommonCarotidArtery = - clitk::ResizeImageLike(CommonCarotidArtery, support, GetBackgroundValue()); - SubclavianArtery = - clitk::ResizeImageLike(SubclavianArtery, support, GetBackgroundValue()); - Thyroid = - clitk::ResizeImageLike(Thyroid, support, GetBackgroundValue()); - Aorta = - clitk::ResizeImageLike(Aorta, support, GetBackgroundValue()); - BrachioCephalicVein = - clitk::ResizeImageLike(BrachioCephalicVein, support, GetBackgroundValue()); - Trachea = - clitk::ResizeImageLike(Trachea, support, GetBackgroundValue()); - - // Extract slices - std::vector slices_BrachioCephalicArtery; - clitk::ExtractSlices(BrachioCephalicArtery, 2, slices_BrachioCephalicArtery); - std::vector slices_BrachioCephalicVein; - clitk::ExtractSlices(BrachioCephalicVein, 2, slices_BrachioCephalicVein); - std::vector slices_CommonCarotidArtery; - clitk::ExtractSlices(CommonCarotidArtery, 2, slices_CommonCarotidArtery); - std::vector slices_SubclavianArtery; - clitk::ExtractSlices(SubclavianArtery, 2, slices_SubclavianArtery); - std::vector slices_Thyroid; - clitk::ExtractSlices(Thyroid, 2, slices_Thyroid); - std::vector slices_Aorta; - clitk::ExtractSlices(Aorta, 2, slices_Aorta); - std::vector slices_Trachea; - clitk::ExtractSlices(Trachea, 2, slices_Trachea); - unsigned int n= slices_BrachioCephalicArtery.size(); - - // Get the boundaries of one slice - std::vector bounds; - ComputeImageBoundariesCoordinates(slices_BrachioCephalicArtery[0], bounds); - - // For all slices, for all structures, find the centroid and build the contour - // List of 3D points (for debug) - std::vector p3D; - - vtkSmartPointer append = vtkSmartPointer::New(); - for(unsigned int i=0; i(slices_CommonCarotidArtery[i], - GetBackgroundValue(), true, 1); - slices_SubclavianArtery[i] = Labelize(slices_SubclavianArtery[i], - GetBackgroundValue(), true, 1); - slices_BrachioCephalicArtery[i] = Labelize(slices_BrachioCephalicArtery[i], - GetBackgroundValue(), true, 1); - slices_BrachioCephalicVein[i] = Labelize(slices_BrachioCephalicVein[i], - GetBackgroundValue(), true, 1); - slices_Thyroid[i] = Labelize(slices_Thyroid[i], - GetBackgroundValue(), true, 1); - slices_Aorta[i] = Labelize(slices_Aorta[i], - GetBackgroundValue(), true, 1); - - // Search centroids - std::vector points2D; - std::vector centroids1; - std::vector centroids2; - std::vector centroids3; - std::vector centroids4; - std::vector centroids5; - std::vector centroids6; - ComputeCentroids(slices_CommonCarotidArtery[i], GetBackgroundValue(), centroids1); - ComputeCentroids(slices_SubclavianArtery[i], GetBackgroundValue(), centroids2); - ComputeCentroids(slices_BrachioCephalicArtery[i], GetBackgroundValue(), centroids3); - ComputeCentroids(slices_Thyroid[i], GetBackgroundValue(), centroids4); - ComputeCentroids(slices_Aorta[i], GetBackgroundValue(), centroids5); - ComputeCentroids(slices_BrachioCephalicVein[i], GetBackgroundValue(), centroids6); - - // BrachioCephalicVein -> when it is separated into two CCL, we - // only consider the most at Right one - if (centroids6.size() > 2) { - if (centroids6[1][0] < centroids6[2][0]) centroids6.erase(centroids6.begin()+2); - else centroids6.erase(centroids6.begin()+1); - } - - // BrachioCephalicVein -> when SubclavianArtery has 2 CCL - // (BrachioCephalicArtery is divided) -> forget BrachioCephalicVein - if ((centroids3.size() ==1) && (centroids2.size() > 2)) { - centroids6.clear(); - } - - for(unsigned int j=1; j centroids_trachea; - ComputeCentroids(slices_Trachea[i], GetBackgroundValue(), centroids_trachea); - typedef std::pair PointAngleType; - std::vector angles; - for(unsigned int j=0; j0) angle = atan(y/x); - if ((x<0) && (y>=0)) angle = atan(y/x)+M_PI; - if ((x<0) && (y<0)) angle = atan(y/x)-M_PI; - if (x==0) { - if (y>0) angle = M_PI/2.0; - if (y<0) angle = -M_PI/2.0; - if (y==0) angle = 0; - } - angle = clitk::rad2deg(angle); - // Angle is [-180;180] wrt the X axis. We change the X axis to - // be the vertical line, because we want to sort from Right to - // Left from Post to Ant. - if (angle>0) - angle = (270-angle); - if (angle<0) { - angle = -angle-90; - if (angle<0) angle = 360-angle; - } - PointAngleType a; - a.first = points2D[j]; - a.second = angle; - angles.push_back(a); - } - - // Do nothing if less than 2 points --> n - if (points2D.size() < 3) { //continue; - continue; - } - - // Sort points2D according to polar angles - std::sort(angles.begin(), angles.end(), comparePointsWithAngle()); - for(unsigned int j=0; j toadd; - unsigned int index = 0; - double dmax = 5; - while (indexdmax) { - - MaskSlicePointType b; - b[0] = a[0]+(c[0]-a[0])/2.0; - b[1] = a[1]+(c[1]-a[1])/2.0; - - // Compute distance to trachea centroid - MaskSlicePointType m = centroids_trachea[1]; - double da = m.EuclideanDistanceTo(a); - double db = m.EuclideanDistanceTo(b); - //double dc = m.EuclideanDistanceTo(c); - - // Mean distance, find point on the line from trachea centroid - // to b - double alpha = (da+db)/2.0; - MaskSlicePointType v; - double n = sqrt( pow(b[0]-m[0], 2) + pow(b[1]-m[1], 2)); - v[0] = (b[0]-m[0])/n; - v[1] = (b[1]-m[1])/n; - MaskSlicePointType r; - r[0] = m[0]+alpha*v[0]; - r[1] = m[1]+alpha*v[1]; - points2D.insert(points2D.begin()+index+1, r); - } - else { - index++; - } - } - // DDV(points2D, points2D.size()); - - // Add some points to close the contour - // - H line towards Right - MaskSlicePointType p = points2D[0]; - p[0] = bounds[0][0]; - points2D.insert(points2D.begin(), p); - // - corner Right/Post - p = bounds[0]; - points2D.insert(points2D.begin(), p); - // - H line towards Left - p = points2D.back(); - p[0] = bounds[2][0]; - points2D.push_back(p); - // - corner Right/Post - p = bounds[2]; - points2D.push_back(p); - // Close contour with the first point - points2D.push_back(points2D[0]); - // DDV(points2D, points2D.size()); - - // Build 3D points from the 2D points - std::vector points3D; - clitk::PointsUtils::Convert2DListTo3DList(points2D, i, support, points3D); - for(unsigned int x=0; x mesh = Build3DMeshFrom2DContour(points3D); - append->AddInput(mesh); - } - - // DEBUG: write points3D - clitk::WriteListOfLandmarks(p3D, "vessels-centroids.txt"); - - // Build the final 3D mesh form the list 2D mesh - append->Update(); - vtkSmartPointer mesh = append->GetOutput(); - - // Debug, write the mesh - /* - vtkSmartPointer w = vtkSmartPointer::New(); - w->SetInput(mesh); - w->SetFileName("bidon.vtk"); - w->Write(); - */ - - // Compute a single binary 3D image from the list of contours - clitk::MeshToBinaryImageFilter::Pointer filter = - clitk::MeshToBinaryImageFilter::New(); - filter->SetMesh(mesh); - filter->SetLikeImage(support); - filter->Update(); - binarizedContour = filter->GetOutput(); - - // Crop - clitk::FindExtremaPointInAGivenDirection(binarizedContour, GetForegroundValue(), 2, true, p); - inf = p[2]; - DD(p); - clitk::FindExtremaPointInAGivenDirection(binarizedContour, GetForegroundValue(), 2, false, p); - sup = p[2]; - DD(p); - binarizedContour = clitk::CropImageAlongOneAxis(binarizedContour, 2, inf, sup, - false, GetBackgroundValue()); - // Update the AFDB - writeImage(binarizedContour, "seg/AntPostVesselsSeparation.mha"); - this->GetAFDB()->SetImageFilename("AntPostVesselsSeparation", "seg/AntPostVesselsSeparation.mha"); - this->WriteAFDB(); - return binarizedContour; - - /* - // Inverse binary mask if needed. We test a point that we know must be in FG. If it is not, inverse - ImagePointType p = p3D[2]; // This is the first centroid of the first slice - p[1] += 50; // 50 mm Post from this point must be kept - ImageIndexType index; - binarizedContour->TransformPhysicalPointToIndex(p, index); - bool isInside = (binarizedContour->GetPixel(index) != GetBackgroundValue()); - - // remove from support - typedef clitk::BooleanOperatorLabelImageFilter BoolFilterType; - typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); - boolFilter->InPlaceOn(); - boolFilter->SetInput1(m_Working_Support); - boolFilter->SetInput2(binarizedContour); - boolFilter->SetBackgroundValue1(GetBackgroundValue()); - boolFilter->SetBackgroundValue2(GetBackgroundValue()); - if (isInside) - boolFilter->SetOperationType(BoolFilterType::And); - else - boolFilter->SetOperationType(BoolFilterType::AndNot); - boolFilter->Update(); - m_Working_Support = boolFilter->GetOutput(); - */ - - // End - //StopCurrentStep(m_Working_Support); - //m_ListOfStations["2R"] = m_Working_Support; - //m_ListOfStations["2L"] = m_Working_Support; -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -typename clitk::ExtractLymphStationsFilter::MaskImagePointer -clitk::ExtractLymphStationsFilter:: -FindAntPostVessels2() -{ - // ----------------------------------------------------- - /* Rod says: "The anterior border, as with the Atlas – UM, is - posterior to the vessels (right subclavian vein, left - brachiocephalic vein, right brachiocephalic vein, left subclavian - artery, left common carotid artery and brachiocephalic trunk). - These vessels are not included in the nodal station. The anterior - border is drawn to the midpoint of the vessel and an imaginary - line joins the middle of these vessels. Between the vessels, - station 2 is in contact with station 3a." */ - - // Check if no already done - bool found = true; - MaskImagePointer binarizedContour; - try { - binarizedContour = this->GetAFDB()->template GetImage ("AntPostVesselsSeparation"); - } - catch(clitk::ExceptionObject e) { - found = false; - } - if (found) { - return binarizedContour; - } - - /* Here, we consider the vessels form a kind of anterior barrier. We - link all vessels centroids and remove what is post to it. - - select the list of structure - vessel1 = BrachioCephalicArtery - vessel2 = BrachioCephalicVein (warning several CCL, keep most at Right) - vessel3 = CommonCarotidArtery - vessel4 = SubclavianArtery - other = Thyroid - other = Aorta - - crop images as needed - - slice by slice, choose the CCL and extract centroids - - slice by slice, sort according to polar angle wrt Trachea centroid. - - slice by slice, link centroids and close contour - - remove outside this contour - - merge with support - */ - - // Read structures - std::map MapOfStructures; - typedef std::map::iterator MapIter; - MapOfStructures["BrachioCephalicArtery"] = this->GetAFDB()->template GetImage("BrachioCephalicArtery"); - MapOfStructures["BrachioCephalicVein"] = this->GetAFDB()->template GetImage("BrachioCephalicVein"); - MapOfStructures["CommonCarotidArteryLeft"] = this->GetAFDB()->template GetImage("LeftCommonCarotidArtery"); - MapOfStructures["CommonCarotidArteryRight"] = this->GetAFDB()->template GetImage("RightCommonCarotidArtery"); - MapOfStructures["SubclavianArteryLeft"] = this->GetAFDB()->template GetImage("LeftSubclavianArtery"); - MapOfStructures["SubclavianArteryRight"] = this->GetAFDB()->template GetImage("RightSubclavianArtery"); - MapOfStructures["Thyroid"] = this->GetAFDB()->template GetImage("Thyroid"); - MapOfStructures["Aorta"] = this->GetAFDB()->template GetImage("Aorta"); - MapOfStructures["Trachea"] = this->GetAFDB()->template GetImage("Trachea"); - - std::vector ListOfStructuresNames; - - // Create a temporay support - // From first slice of BrachioCephalicVein to end of 3A or end of 2RL - MaskImagePointer support = this->GetAFDB()->template GetImage("Support_Sup_Carina"); - MaskImagePointType p; - p[0] = p[1] = p[2] = 0.0; // to avoid warning - clitk::FindExtremaPointInAGivenDirection(MapOfStructures["BrachioCephalicVein"], - GetBackgroundValue(), 2, true, p); - double inf = p[2]; - clitk::FindExtremaPointInAGivenDirection(this->GetAFDB()->template GetImage("Support_S3A"), - GetBackgroundValue(), 2, false, p); - MaskImagePointType p2; - clitk::FindExtremaPointInAGivenDirection(this->GetAFDB()->template GetImage("Support_S2L"), - GetBackgroundValue(), 2, false, p2); - if (p2[2] > p[2]) p = p2; - - double sup = p[2]+support->GetSpacing()[2];//one slice more ? - support = clitk::CropImageAlongOneAxis(support, 2, inf, sup, - false, GetBackgroundValue()); - - // Resize all structures like support - for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) { - it->second = clitk::ResizeImageLike(it->second, support, GetBackgroundValue()); - } - - // Extract slices - typedef std::vector SlicesType; - std::map MapOfSlices; - for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) { - SlicesType s; - clitk::ExtractSlices(it->second, 2, s); - MapOfSlices[it->first] = s; - } - - unsigned int n= MapOfSlices["Trachea"].size(); - - // Get the boundaries of one slice - std::vector bounds; - ComputeImageBoundariesCoordinates(MapOfSlices["Trachea"][0], bounds); - - // LOOP ON SLICES - // For all slices, for all structures, find the centroid and build the contour - // List of 3D points (for debug) - std::vector p3D; - vtkSmartPointer append = vtkSmartPointer::New(); - for(unsigned int i=0; ifirst][i]; - s = clitk::Labelize(s, GetBackgroundValue(), true, 1); - } - - // Search centroids - std::vector points2D; - typedef std::vector CentroidsType; - std::map MapOfCentroids; - for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) { - std::string structure = it->first; - MaskSlicePointer & s = MapOfSlices[structure][i]; - CentroidsType c; - clitk::ComputeCentroids(s, GetBackgroundValue(), c); - MapOfCentroids[structure] = c; - } - - - // BrachioCephalicVein -> when it is separated into two CCL, we - // only consider the most at Right one - CentroidsType & c = MapOfCentroids["BrachioCephalicVein"]; - if (c.size() > 2) { - if (c[1][0] < c[2][0]) c.erase(c.begin()+2); - else c.erase(c.begin()+1); - } - - /* - // BrachioCephalicVein -> when SubclavianArtery has 2 CCL - // (BrachioCephalicArtery is divided) -> forget BrachioCephalicVein - if ((MapOfCentroids["BrachioCephalicArtery"].size() ==1) - && (MapOfCentroids["SubclavianArtery"].size() > 2)) { - MapOfCentroids["BrachioCephalicVein"].clear(); - } - */ - - // Add all 2D points - for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) { - std::string structure = it->first; - if (structure != "Trachea") { // do not add centroid of trachea - CentroidsType & c = MapOfCentroids[structure]; - for(unsigned int j=1; j centroids_trachea; - //ComputeCentroids(MapOfSlices["Trachea"][i], GetBackgroundValue(), centroids_trachea); - CentroidsType centroids_trachea = MapOfCentroids["Trachea"]; - typedef std::pair PointAngleType; - std::vector angles; - for(unsigned int j=0; j0) angle = atan(y/x); - if ((x<0) && (y>=0)) angle = atan(y/x)+M_PI; - if ((x<0) && (y<0)) angle = atan(y/x)-M_PI; - if (x==0) { - if (y>0) angle = M_PI/2.0; - if (y<0) angle = -M_PI/2.0; - if (y==0) angle = 0; - } - angle = clitk::rad2deg(angle); - // Angle is [-180;180] wrt the X axis. We change the X axis to - // be the vertical line, because we want to sort from Right to - // Left from Post to Ant. - if (angle>0) - angle = (270-angle); - if (angle<0) { - angle = -angle-90; - if (angle<0) angle = 360-angle; - } - PointAngleType a; - a.first = points2D[j]; - a.second = angle; - angles.push_back(a); - } - - // Do nothing if less than 2 points --> n - if (points2D.size() < 3) { //continue; - continue; - } - - // Sort points2D according to polar angles - std::sort(angles.begin(), angles.end(), comparePointsWithAngle()); - for(unsigned int j=0; j toadd; - unsigned int index = 0; - double dmax = 5; - while (indexdmax) { - - MaskSlicePointType b; - b[0] = a[0]+(c[0]-a[0])/2.0; - b[1] = a[1]+(c[1]-a[1])/2.0; - - // Compute distance to trachea centroid - MaskSlicePointType m = centroids_trachea[1]; - double da = m.EuclideanDistanceTo(a); - double db = m.EuclideanDistanceTo(b); - //double dc = m.EuclideanDistanceTo(c); - - // Mean distance, find point on the line from trachea centroid - // to b - double alpha = (da+db)/2.0; - MaskSlicePointType v; - double n = sqrt( pow(b[0]-m[0], 2) + pow(b[1]-m[1], 2)); - v[0] = (b[0]-m[0])/n; - v[1] = (b[1]-m[1])/n; - MaskSlicePointType r; - r[0] = m[0]+alpha*v[0]; - r[1] = m[1]+alpha*v[1]; - points2D.insert(points2D.begin()+index+1, r); - } - else { - index++; - } - } - // DDV(points2D, points2D.size()); - - // Add some points to close the contour - // - H line towards Right - MaskSlicePointType p = points2D[0]; - p[0] = bounds[0][0]; - points2D.insert(points2D.begin(), p); - // - corner Right/Post - p = bounds[0]; - points2D.insert(points2D.begin(), p); - // - H line towards Left - p = points2D.back(); - p[0] = bounds[2][0]; - points2D.push_back(p); - // - corner Right/Post - p = bounds[2]; - points2D.push_back(p); - // Close contour with the first point - points2D.push_back(points2D[0]); - // DDV(points2D, points2D.size()); - - // Build 3D points from the 2D points - std::vector points3D; - clitk::PointsUtils::Convert2DListTo3DList(points2D, i, support, points3D); - for(unsigned int x=0; x mesh = Build3DMeshFrom2DContour(points3D); - append->AddInput(mesh); - // if (i ==n-1) { // last slice - // clitk::PointsUtils::Convert2DListTo3DList(points2D, i+1, support, points3D); - // vtkSmartPointer mesh = Build3DMeshFrom2DContour(points3D); - // append->AddInput(mesh); - // } - } - - // DEBUG: write points3D - clitk::WriteListOfLandmarks(p3D, "vessels-centroids.txt"); - - // Build the final 3D mesh form the list 2D mesh - append->Update(); - vtkSmartPointer mesh = append->GetOutput(); - - // Debug, write the mesh - /* - vtkSmartPointer w = vtkSmartPointer::New(); - w->SetInput(mesh); - w->SetFileName("bidon.vtk"); - w->Write(); - */ - - // Compute a single binary 3D image from the list of contours - clitk::MeshToBinaryImageFilter::Pointer filter = - clitk::MeshToBinaryImageFilter::New(); - filter->SetMesh(mesh); - filter->SetLikeImage(support); - filter->Update(); - binarizedContour = filter->GetOutput(); - - // Crop - clitk::FindExtremaPointInAGivenDirection(binarizedContour, - GetForegroundValue(), 2, true, p); - inf = p[2]; - clitk::FindExtremaPointInAGivenDirection(binarizedContour, - GetForegroundValue(), 2, false, p); - sup = p[2]+binarizedContour->GetSpacing()[2]; // extend to include the last slice - binarizedContour = clitk::CropImageAlongOneAxis(binarizedContour, 2, inf, sup, - false, GetBackgroundValue()); - - // Update the AFDB - writeImage(binarizedContour, "seg/AntPostVesselsSeparation.mha"); - this->GetAFDB()->SetImageFilename("AntPostVesselsSeparation", "seg/AntPostVesselsSeparation.mha"); - this->WriteAFDB(); - return binarizedContour; - - /* - // Inverse binary mask if needed. We test a point that we know must be in FG. If it is not, inverse - ImagePointType p = p3D[2]; // This is the first centroid of the first slice - p[1] += 50; // 50 mm Post from this point must be kept - ImageIndexType index; - binarizedContour->TransformPhysicalPointToIndex(p, index); - bool isInside = (binarizedContour->GetPixel(index) != GetBackgroundValue()); - - // remove from support - typedef clitk::BooleanOperatorLabelImageFilter BoolFilterType; - typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); - boolFilter->InPlaceOn(); - boolFilter->SetInput1(m_Working_Support); - boolFilter->SetInput2(binarizedContour); - boolFilter->SetBackgroundValue1(GetBackgroundValue()); - boolFilter->SetBackgroundValue2(GetBackgroundValue()); - if (isInside) - boolFilter->SetOperationType(BoolFilterType::And); - else - boolFilter->SetOperationType(BoolFilterType::AndNot); - boolFilter->Update(); - m_Working_Support = boolFilter->GetOutput(); - */ - - // End - //StopCurrentStep(m_Working_Support); - //m_ListOfStations["2R"] = m_Working_Support; - //m_ListOfStations["2L"] = m_Working_Support; -} -//-------------------------------------------------------------------- - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -WriteImageSupport(std::string support) -{ - writeImage(m_ListOfSupports[support], this->GetAFDBPath()+"/"+"seg/Support_"+support+".mha"); - this->GetAFDB()->SetImageFilename("Support_"+support, "seg/Support_"+support+".mha"); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -WriteImageStation(std::string station) -{ - writeImage(m_ListOfStations[station], GetAFDB()->GetPath()+"/seg/Station"+station+".mha"); - GetAFDB()->SetImageFilename("Station"+station, "seg/Station"+station+".mha"); - WriteAFDB(); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ComputeOverlapWithRef(std::string station) -{ - if (GetComputeStation(station)) { - MaskImagePointer ref = this->GetAFDB()->template GetImage ("Station"+station+"_Ref"); - typedef clitk::LabelImageOverlapMeasureFilter FilterType; - typename FilterType::Pointer filter = FilterType::New(); - filter->SetInput(0, m_ListOfStations[station]); - filter->SetInput(1, ref); - filter->Update(); - } -} -//-------------------------------------------------------------------- - -//-------------------------------------------------------------------- -template -void -clitk::ExtractLymphStationsFilter:: -ReadSupportLimits(std::string filename) -{ - m_ListOfSupportLimits.clear(); - ifstream is; - openFileForReading(is, filename); - while (is) { - skipComment(is); - SupportLimitsType s; - s.Read(is); - if (is) m_ListOfSupportLimits.push_back(s); - } -} -//-------------------------------------------------------------------- - -#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX - diff --git a/segmentation/clitkExtractLymphStationsGenericFilter.h b/segmentation/clitkExtractLymphStationsGenericFilter.h deleted file mode 100644 index afeb66b..0000000 --- a/segmentation/clitkExtractLymphStationsGenericFilter.h +++ /dev/null @@ -1,80 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -======================================================================-====*/ - -#ifndef CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H -#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H - -#include "clitkIO.h" -#include "clitkImageToImageGenericFilter.h" -#include "clitkExtractLymphStationsFilter.h" - -//-------------------------------------------------------------------- -namespace clitk -{ - - template - class ITK_EXPORT ExtractLymphStationsGenericFilter: - public ImageToImageGenericFilter > - { - - public: - //-------------------------------------------------------------------- - ExtractLymphStationsGenericFilter(); - - //-------------------------------------------------------------------- - typedef ImageToImageGenericFilter > Superclass; - typedef ExtractLymphStationsGenericFilter Self; - typedef itk::SmartPointer Pointer; - typedef itk::SmartPointer ConstPointer; - - //-------------------------------------------------------------------- - itkNewMacro(Self); - itkTypeMacro(ExtractLymphStationsGenericFilter, LightObject); - - //-------------------------------------------------------------------- - // Options for the GenericFilter - void SetArgsInfo(const ArgsInfoType & a); - - //-------------------------------------------------------------------- - // Options for the Filter - template - void SetOptionsFromArgsInfoToFilter(FilterType * f) ; - - //-------------------------------------------------------------------- - // Main function called each time the filter is updated - template - void UpdateWithInputImageType(); - - protected: - template void InitializeImageType(); - ArgsInfoType mArgsInfo; - - private: - ExtractLymphStationsGenericFilter(const Self&); //purposely not implemented - void operator=(const Self&); //purposely not implemented - - }; // end class - //-------------------------------------------------------------------- - -} // end namespace clitk - -#ifndef ITK_MANUAL_INSTANTIATION -#include "clitkExtractLymphStationsGenericFilter.txx" -#endif - -#endif // #define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H diff --git a/segmentation/clitkExtractLymphStationsGenericFilter.txx b/segmentation/clitkExtractLymphStationsGenericFilter.txx deleted file mode 100644 index a27b4a6..0000000 --- a/segmentation/clitkExtractLymphStationsGenericFilter.txx +++ /dev/null @@ -1,169 +0,0 @@ -/*========================================================================= - Program: vv http://www.creatis.insa-lyon.fr/rio/vv - - Authors belong to: - - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr - - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the copyright notices for more information. - - It is distributed under dual licence - - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html - ======================================================================-====*/ - -#ifndef CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX -#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX - -#include "clitkImageCommon.h" - -//-------------------------------------------------------------------- -template -clitk::ExtractLymphStationsGenericFilter::ExtractLymphStationsGenericFilter(): - ImageToImageGenericFilter("ExtractLymphStations") -{ - // Default values - cmdline_parser_clitkExtractLymphStations_init(&mArgsInfo); - InitializeImageType<3>(); // Only for 3D images -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -template -void clitk::ExtractLymphStationsGenericFilter::InitializeImageType() -{ - ADD_IMAGE_TYPE(Dim, short); // Can add float later -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -void clitk::ExtractLymphStationsGenericFilter::SetArgsInfo(const ArgsInfoType & a) -{ - mArgsInfo=a; - SetIOVerbose(mArgsInfo.verbose_flag); - if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes(); - if (mArgsInfo.input_given) AddInputFilename(mArgsInfo.input_arg); - if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractLymphStationsGenericFilter:: -SetOptionsFromArgsInfoToFilter(FilterType * f) -{ - f->SetVerboseOptionFlag(mArgsInfo.verbose_flag); - f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag); - f->SetWriteStepFlag(mArgsInfo.writeStep_flag); - f->SetVerboseMemoryFlag(mArgsInfo.verboseMemory_flag); - f->SetAFDBFilename(mArgsInfo.afdb_arg); - if (mArgsInfo.afdb_path_given) f->SetAFDBPath(mArgsInfo.afdb_path_arg); - f->SetForceSupportsFlag(mArgsInfo.force_support_flag); - f->SetSupportLimitsFilename(mArgsInfo.support_limits_arg); - f->SetCheckSupportFlag(mArgsInfo.check_support_limits_flag); - - // Station 8 - //f->SetDistanceMaxToAnteriorPartOfTheSpine(mArgsInfo.S8_maxAntSpine_arg); - f->SetFuzzyThreshold("8", "Esophagus", mArgsInfo.S8_ft_Esophagus_arg); - // f->SetInjectedThresholdForS8(mArgsInfo.tS8_injectedThreshold_arg); - - // Check multiple options for radius dilatation - /* - typename FilterType::MaskImagePointType p; - SetMultipleOptionMacro(mArgsInfo, esophagusDilatation, 3, p); - default ? = set before - exception if fail - */ - typename FilterType::MaskImagePointType p; - p[0] = 7; p[1] = 5; p[2] = 0; // default value - if (mArgsInfo.S8_esophagusDilatationForAnt_given == 3) { - for(uint i=0; i<3; i++) - p[i] = mArgsInfo.S8_esophagusDilatationForAnt_arg[i]; - } - else { - if (mArgsInfo.S8_esophagusDilatationForAnt_given == 1) { - for(uint i=0; i<3; i++) - p[i] = mArgsInfo.S8_esophagusDilatationForAnt_arg[0]; - } - } - f->SetEsophagusDiltationForAnt(p); - - p[0] = 5; p[1] = 10; p[2] = 1; // default value - if (mArgsInfo.S8_esophagusDilatationForRight_given == 3) { - for(uint i=0; i<3; i++) - p[i] = mArgsInfo.S8_esophagusDilatationForRight_arg[i]; - } - else { - if (mArgsInfo.S8_esophagusDilatationForRight_given == 1) { - for(uint i=0; i<3; i++) - p[i] = mArgsInfo.S8_esophagusDilatationForRight_arg[0]; - } - } - f->SetEsophagusDiltationForRight(p); - - for(uint i=0; iAddComputeStation(mArgsInfo.station_arg[i]); - - // Station 3A - - // Station 7 - f->SetFuzzyThreshold("7", "Bronchi", mArgsInfo.S7_ft_Bronchi_arg); - f->SetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein", mArgsInfo.S7_ft_LeftSuperiorPulmonaryVein_arg); - f->SetFuzzyThreshold("7", "RightSuperiorPulmonaryVein", mArgsInfo.S7_ft_RightSuperiorPulmonaryVein_arg); - f->SetFuzzyThreshold("7", "RightPulmonaryArtery", mArgsInfo.S7_ft_RightPulmonaryArtery_arg); - f->SetFuzzyThreshold("7", "LeftPulmonaryArtery", mArgsInfo.S7_ft_LeftPulmonaryArtery_arg); - f->SetFuzzyThreshold("7", "SVC", mArgsInfo.S7_ft_SVC_arg); - f->SetS7_UseMostInferiorPartOnlyFlag(mArgsInfo.S7_UseMostInferiorPartOnly_flag); - - // Station 2RL - - // Station 1RL - - // Set RelativePositionList filenames - for(uint i=0; iAddRelativePositionListFilename(mArgsInfo.relpos_arg[i]); -} -//-------------------------------------------------------------------- - - -//-------------------------------------------------------------------- -// Update with the number of dimensions and the pixeltype -//-------------------------------------------------------------------- -template -template -void clitk::ExtractLymphStationsGenericFilter::UpdateWithInputImageType() -{ - // Reading input - typename ImageType::Pointer input = this->template GetInput(0); - - // Create filter - typedef clitk::ExtractLymphStationsFilter FilterType; - typename FilterType::Pointer filter = FilterType::New(); - - // Set global Options - filter->SetInput(input); - SetOptionsFromArgsInfoToFilter(filter); - - // Go ! - filter->Update(); - - // Write/Save results - typedef uchar MaskImagePixelType; - typedef itk::Image OutputImageType; - typename OutputImageType::Pointer output = filter->GetOutput(); - this->template SetNextOutput(output); -} -//-------------------------------------------------------------------- - -#endif //#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX -- 2.47.1