+++ /dev/null
-
-
-// vtk
-#include <vtkAppendPolyData.h>
-#include <vtkPolyDataWriter.h>
-#include <vtkCellArray.h>
-
-// clitk
-#include "clitkMeshToBinaryImageFilter.h"
-
-// itk
-#include <itkImageDuplicator.h>
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_1RL_SetDefaultValues()
-{
-
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["1R"], "seg/Station1R.mhd");
- writeImage<MaskImageType>(m_ListOfStations["1L"], "seg/Station1L.mhd");
- GetAFDB()->SetImageFilename("Station1R", "seg/Station1R.mhd");
- GetAFDB()->SetImageFilename("Station1L", "seg/Station1L.mhd");
- WriteAFDB();
- StopSubStep();
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>("Trachea");
- MaskImagePointer Thyroid = GetAFDB()->template GetImage<MaskImageType>("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<MaskImageType>(Trachea, S1R, GetBackgroundValue());
- Thyroid = clitk::ResizeImageLike<MaskImageType>(Thyroid, S1R, GetBackgroundValue());
-
- // Search for most Ant point, slice by slice, between Trachea and Thyroid
- std::vector<MaskSlicePointer> Trachea_slices;
- clitk::ExtractSlices<MaskImageType>(Trachea, 2, Trachea_slices);
- std::vector<MaskSlicePointer> Thyroid_slices;
- clitk::ExtractSlices<MaskImageType>(Thyroid, 2, Thyroid_slices);
- std::vector<typename ImageType::PointType> A;
- std::vector<typename ImageType::PointType> B;
- for(uint i=0; i<Trachea_slices.size(); i++) {
- MaskSlicePointType p;
- MaskSlicePointType q;
- FindExtremaPointInAGivenDirection<MaskSliceType>(Trachea_slices[i],
- GetBackgroundValue(),
- 1, true, p);
- FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskImageType>::Convert2DTo3D(p, Trachea, i, A[i]);
- p[0] += 10;
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(p, Trachea, i, B[i]);
- }
-
- // Remove anterior to this line (keep +10 offset)
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
- GetBackgroundValue(), 1, +10);
- m_ListOfStations["1R"] = S1R;
-
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
- GetBackgroundValue(), 1, +10);
- StopCurrentStep<MaskImageType>(S1L);
- m_ListOfStations["1L"] = S1L;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_1RL_Post_Limits()
-{
- // -----------------------------------------------------
- StartNewStep("[Station 1RL] Posterior limits with VertebralArtery");
-
- MaskImagePointer VertebralArtery = GetAFDB()->template GetImage<MaskImageType>("VertebralArtery");
- MaskImagePointer S1R = m_ListOfStations["1R"];
- MaskImagePointer S1L = m_ListOfStations["1L"];
-
- // Resize like S1R.
- VertebralArtery = clitk::ResizeImageLike<MaskImageType>(VertebralArtery, S1R, GetBackgroundValue());
-
- // Search for most Ant point
- std::vector<MaskSlicePointer> VertebralArtery_slices;
- clitk::ExtractSlices<MaskImageType>(VertebralArtery, 2, VertebralArtery_slices);
- std::vector<typename ImageType::PointType> A;
- std::vector<typename ImageType::PointType> B;
- for(uint i=0; i<VertebralArtery_slices.size(); i++) {
- MaskSlicePointType p;
- FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskImageType>::Convert2DTo3D(p, VertebralArtery, i, A[i]);
- p[0] += 10;
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(p, VertebralArtery, i, B[i]);
- }
-
- // Remove anterior to this line (keep -10 offset)
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
- GetBackgroundValue(), 1, -10);
- m_ListOfStations["1R"] = S1R;
-
- // Remove anterior to this line (keep -10 offset)
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
- GetBackgroundValue(), 1, -10);
- StopCurrentStep<MaskImageType>(S1L);
- m_ListOfStations["1L"] = S1L;
-}
-//--------------------------------------------------------------------
-
-
+++ /dev/null
-
-
-// vtk
-#include <vtkAppendPolyData.h>
-#include <vtkPolyDataWriter.h>
-#include <vtkCellArray.h>
-
-// clitk
-#include "clitkMeshToBinaryImageFilter.h"
-
-// itk
-#include <itkImageDuplicator.h>
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_2RL_SetDefaultValues()
-{
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["2R"], "seg/Station2R.mhd");
- writeImage<MaskImageType>(m_ListOfStations["2L"], "seg/Station2L.mhd");
- GetAFDB()->SetImageFilename("Station2R", "seg/Station2R.mhd");
- GetAFDB()->SetImageFilename("Station2L", "seg/Station2L.mhd");
- WriteAFDB();
- StopSubStep();
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>(binarizedContour,
- m_Working_Support,
- GetForegroundValue());
- // remove from support
- typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> 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<MaskImageType>(m_Working_Support);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_2RL_Cut_BrachioCephalicVein_superiorly_when_it_split()
-{
- // -----------------------------------------------------
- StartNewStep("[Station 2RL] Cut BrachioCephalicVein superiorly (when it split)");
-
- // Get BrachioCephalicVein
- MaskImagePointer BrachioCephalicVein = GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicVein");
-
- // Remove the part superior to the slice where BrachioCephalicVein
- // divide in two CCL
- std::vector<MaskSlicePointer> BCV_slices;
- clitk::ExtractSlices<MaskImageType>(BrachioCephalicVein, 2, BCV_slices);
- bool stop = false;
- uint i=0;
- while (!stop) {
- // Count the number of CCL
- int nb;
- clitk::LabelizeAndCountNumberOfObjects<MaskSliceType>(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<MaskImageType>(BrachioCephalicVein, 2,
- p[2], true,
- GetBackgroundValue());
-
- // Now, insert this image in the AFDB (but do not store on disk)
- GetAFDB()->template SetImage<MaskImageType>("BrachioCephalicVein_ForS2RL", "bidon",
- BrachioCephalicVein, false);
- // End
- StopCurrentStep<MaskImageType>(BrachioCephalicVein);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-// Build a vtk mesh from a list of slice number/closed-contours
-template <class ImageType>
-vtkSmartPointer<vtkPolyData>
-clitk::ExtractLymphStationsFilter<ImageType>::
-Build3DMeshFrom2DContour(const std::vector<ImagePointType> & points)
-{
- // create a contour, polydata.
- vtkSmartPointer<vtkPolyData> mesh = vtkSmartPointer<vtkPolyData>::New();
- mesh->Allocate(); //for cell structures
- mesh->SetPoints(vtkPoints::New());
- vtkIdType ids[2];
- int point_number = points.size();
- for (unsigned int i=0; i<points.size(); i++) {
- mesh->GetPoints()->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 <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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");
-}
-//--------------------------------------------------------------------
-
-
+++ /dev/null
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_3A_SetDefaultValues()
-{
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["3A"],
- GetBackgroundValue(),
- GetForegroundValue());
-
- // Store image filenames into AFDB
- writeImage<MaskImageType>(m_ListOfStations["3A"], "seg/Station3A.mhd");
- GetAFDB()->SetImageFilename("Station3A", "seg/Station3A.mhd");
- WriteAFDB();
- StopSubStep();
-}
-//--------------------------------------------------------------------
-
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <MaskImageType>("Aorta");
- Aorta = clitk::ResizeImageLike<MaskImageType>(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<MaskSlicePointer> slices;
- clitk::ExtractSlices<MaskImageType>(Aorta, 2, slices);
- std::vector<MaskImagePointType> points;
- for(uint i=0; i<slices.size(); i++) {
- // Select most ant CCL
- slices[i] = clitk::Labelize<MaskSliceType>(slices[i], GetBackgroundValue(), false, 1);
- std::vector<MaskSlicePointType> c;
- clitk::ComputeCentroids<MaskSliceType>(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<MaskSliceType, MaskSliceType>(slices[i], slices[i], l,
- GetBackgroundValue(), true);
-
- // Detect the most ant point
- MaskSlicePointType p;
- MaskImagePointType pA;
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskImageType>::Convert2DTo3D(p, Aorta, i, pA);
- points.push_back(pA);
- }
-
- // DEBUG
- // MaskImagePointer o = clitk::JoinSlices<MaskImageType>(slices, Aorta, 2);
- // writeImage<MaskImageType>(o, "o.mhd");
- // clitk::WriteListOfLandmarks<MaskImageType>(points, "Ant-Aorta.txt");
-
- // Remove Post/Left to this point
- m_Working_Support =
- clitk::SliceBySliceSetBackgroundFromPoints<MaskImageType>(m_Working_Support,
- GetBackgroundValue(), 2,
- points,
- true, // Set BG if X greater than point[x], and
- true); // if Y greater than point[y]
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["3A"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_3A_Post_Limits_With_Dilated_Aorta_S6_Support()
-{
- StartNewStep("[Station 3A] Post limits with dilated Aorta");
-
- // Consider Aorta
- MaskImagePointer Aorta = GetAFDB()->template GetImage <MaskImageType>("Aorta");
-
- // Limits the support to S6
- MaskImagePointer S6 = m_ListOfSupports["S6"];
- Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, S6, GetBackgroundValue());
-
- // Extend 1cm anteriorly
- MaskImagePointType radius; // in mm
- radius[0] = 10;
- radius[1] = 10;
- radius[2] = 0; // required
- Aorta = clitk::Dilate<MaskImageType>(Aorta, radius, GetBackgroundValue(), GetForegroundValue(), false);
-
- // Now, insert this image in the AFDB (but do not store on disk)
- GetAFDB()->template SetImage<MaskImageType>("Aorta_Dilated_Anteriorly", "seg/Aorta_Dilated_Anteriorly.mha", Aorta, false);
- writeImage<MaskImageType>(Aorta, "seg/Aorta_Dilated_Anteriorly.mha");
- GetAFDB()->Write();
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["3A"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>(binarizedContour,
- m_Working_Support,
- GetBackgroundValue());
-
- // remove from support
- typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> 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<MaskImageType>(m_Working_Support);
- m_ListOfStations["3A"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <MaskImageType>("BrachioCephalicVein");
- BrachioCephalicVein = clitk::ResizeImageLike<MaskImageType>(BrachioCephalicVein,
- m_Working_Support,
- GetBackgroundValue());
- std::vector<MaskSlicePointer> slices;
- std::vector<MaskSlicePointer> slices_BCV;
- clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
- clitk::ExtractSlices<MaskImageType>(BrachioCephalicVein, 2, slices_BCV);
- for(uint i=0; i<slices.size(); i++) {
- // Labelize slices_BCV
- slices_BCV[i] = Labelize<MaskSliceType>(slices_BCV[i], 0, true, 1);
-
- // Compute centroids
- std::vector<typename MaskSliceType::PointType> centroids;
- ComputeCentroids<MaskSliceType>(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<MaskSliceType, MaskSliceType>(slices_BCV[i],
- slices_BCV[i],
- label,
- GetBackgroundValue(),
- true);
- }
-
- // Remove from the support
- clitk::AndNot<MaskSliceType>(slices[i], slices_BCV[i], GetBackgroundValue());
- }
-
- // Joint
- m_Working_Support = clitk::JoinSlices<MaskImageType>(slices, m_Working_Support, 2);
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["3A"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
+++ /dev/null
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_3P_SetDefaultValues()
-{
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["3P"], "seg/Station3P.mhd");
- GetAFDB()->SetImageFilename("Station3P", "seg/Station3P.mhd");
- WriteAFDB();
- StopSubStep();
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>(m_Working_Support);
- m_ListOfStations["3P"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>("Trachea");
- MaskImagePointer SubclavianArtery = GetAFDB()->template GetImage<MaskImageType>("SubclavianArtery");
-
- // Crop like current support
- Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, m_Working_Support, GetBackgroundValue());
- SubclavianArtery = clitk::ResizeImageLike<MaskImageType>(SubclavianArtery, m_Working_Support, GetBackgroundValue());
-
- // writeImage<MaskImageType>(Trachea, "tr.mhd");
- // writeImage<MaskImageType>(SubclavianArtery, "sca.mhd");
-
- // Get list of slices
- std::vector<MaskSlicePointer> slices_support;
- std::vector<MaskSlicePointer> slices_trachea;
- std::vector<MaskSlicePointer> slices_subclavianartery;
- clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices_support);
- clitk::ExtractSlices<MaskImageType>(Trachea, 2, slices_trachea);
- clitk::ExtractSlices<MaskImageType>(SubclavianArtery, 2, slices_subclavianartery);
-
- // Loop on slices
- std::vector<MaskImagePointType> points;
- MaskImagePointType p;
- for(uint i=0; i<slices_support.size(); i++) {
- // Get Trachea centroid
- std::vector<typename MaskSliceType::PointType> centroids;
- typename MaskSliceType::PointType c;
- ComputeCentroids<MaskSliceType>(slices_trachea[i], GetBackgroundValue(), centroids);
- c = centroids[1];
-
- // [debug] Store point
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(centroids[1], Trachea, i, p);
- points.push_back(p);
-
- // Get Right and Left CCL in SubclavianArtery
- slices_subclavianartery[i] = Labelize<MaskSliceType>(slices_subclavianartery[i], 0, true, 10);
- ComputeCentroids<MaskSliceType>(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<centroids.size(); j++) {
- if (centroids[j][0] < c[0]) { // At Right of Trachea centroid
- if (centroids[j][0] >= 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<MaskImageType>::Convert2DTo3D(centroids[label_right], SubclavianArtery, i, p);
- points.push_back(p);
-
- // Set Background and ForegroundValue according to label_right
- MaskSlicePointer object =
- clitk::Binarize<MaskSliceType>(slices_subclavianartery[i], label_right, label_right,
- GetBackgroundValue(), GetForegroundValue());
-
- // Relative Position : not at Right
- typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskSliceType> 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<MaskImageType>::Convert2DTo3D(centroids[label_left], SubclavianArtery, i, p);
- points.push_back(p);
-
- // Set Background and ForegroundValue according to label_right
- MaskSlicePointer object =
- clitk::Binarize<MaskSliceType>(slices_subclavianartery[i], label_left, label_left,
- GetBackgroundValue(), GetForegroundValue());
-
- // Relative Position : not at Right
- typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskSliceType> 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<MaskImageType>(slices_support, m_Working_Support, 2);
-
- // Save list points
- clitk::WriteListOfLandmarks<MaskImageType>(points, "subcl-lr.txt");
-
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["3P"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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) ");
-
-
-}
-//--------------------------------------------------------------------
-
+++ /dev/null
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_4RL_SetDefaultValues()
-{
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["4L"],
- GetBackgroundValue(),
- GetForegroundValue());
- StopCurrentStep<MaskImageType>(m_ListOfStations["4L"]);
-
- // Store image filenames into AFDB
- WriteImageStation("4L");
- StopSubStep();
- ComputeOverlapWithRef("4L");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>("AscendingAorta");
- MaskImagePointer DescendingAorta = GetAFDB()->template GetImage<MaskImageType>("DescendingAorta");
-
- // Crop like support (inferiorly)
- m_Working_Support = clitk::AutoCrop<MaskImageType>(m_Working_Support, GetBackgroundValue());
- AscendingAorta =
- clitk::ResizeImageLike<MaskImageType>(AscendingAorta, m_Working_Support, GetBackgroundValue());
- DescendingAorta =
- clitk::ResizeImageLike<MaskImageType>(DescendingAorta, m_Working_Support, GetBackgroundValue());
-
- // Crop superior part (when AscendingAorta and DescendingAorta join)
- MaskImagePointType p;
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(AscendingAorta,
- GetBackgroundValue(), 2, false, p);
- double max = p[2]+AscendingAorta->GetSpacing()[2];
- AscendingAorta =
- clitk::CropImageRemoveGreaterThan<MaskImageType>(AscendingAorta, 2, max, false, GetBackgroundValue());
- DescendingAorta =
- clitk::CropImageRemoveGreaterThan<MaskImageType>(DescendingAorta, 2, max, false, GetBackgroundValue());
-
- // Crop inferior part, where LeftPulmonaryArtery start
- MaskImagePointer AscendingAortaCopy = clitk::Clone<MaskImageType>(AscendingAorta);
- MaskImagePointer LeftPulmonaryArtery = GetAFDB()->template GetImage<MaskImageType>("LeftPulmonaryArtery");
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(LeftPulmonaryArtery,
- GetBackgroundValue(), 2, false, p);
- max = p[2]+LeftPulmonaryArtery->GetSpacing()[2];
- AscendingAorta =
- clitk::CropImageRemoveLowerThan<MaskImageType>(AscendingAorta, 2, max, false, GetBackgroundValue());
- DescendingAorta =
- clitk::CropImageRemoveLowerThan<MaskImageType>(DescendingAorta, 2, max, false, GetBackgroundValue());
-
- // Find closest points
- std::vector<MaskImagePointType> A;
- std::vector<MaskImagePointType> B;
- clitk::SliceBySliceBuildLineSegmentAccordingToMinimalDistanceBetweenStructures<MaskImageType>(AscendingAorta,
- DescendingAorta,
- GetBackgroundValue(),
- 2, A, B);
- // Separate according to AB lines
- // clitk::WriteListOfLandmarks<MaskImageType>(A, "A.txt");
- // clitk::WriteListOfLandmarks<MaskImageType>(B, "B.txt");
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, A, B,
- GetBackgroundValue(),
- 1, KeepPoint); // Keep point along axis 1
-
- // Now, same principle between AscendingAorta and LeftPulmonaryArtery
- AscendingAorta =
- clitk::ResizeImageLike<MaskImageType>(AscendingAortaCopy, m_Working_Support, GetBackgroundValue());
- LeftPulmonaryArtery =
- clitk::ResizeImageLike<MaskImageType>(LeftPulmonaryArtery, m_Working_Support, GetBackgroundValue());
- AscendingAorta =
- clitk::CropImageRemoveGreaterThan<MaskImageType>(AscendingAorta, 2, max, false, GetBackgroundValue());
- LeftPulmonaryArtery =
- clitk::CropImageRemoveGreaterThan<MaskImageType>(LeftPulmonaryArtery, 2, max, false, GetBackgroundValue());
- A.clear();
- B.clear();
- clitk::SliceBySliceBuildLineSegmentAccordingToMinimalDistanceBetweenStructures<MaskImageType>(AscendingAorta,
- LeftPulmonaryArtery,
- GetBackgroundValue(),
- 2, A, B);
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, A, B,
- GetBackgroundValue(),
- 1, KeepPoint); // Keep point along axis 1
-
- // AutoCrop
- m_Working_Support = clitk::AutoCrop<MaskImageType>(m_Working_Support, GetBackgroundValue());
-
- // End
- StopCurrentStep<MaskImageType>(m_Working_Support);
-}
-//--------------------------------------------------------------------
-
-
+++ /dev/null
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_5_SetDefaultValues()
-{
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["5"],
- GetBackgroundValue(),
- GetForegroundValue());
-
- // AutoCrop
- m_ListOfStations["5"] = clitk::AutoCrop<MaskImageType>(m_ListOfStations["5"], GetBackgroundValue());
- StopCurrentStep<MaskImageType>(m_ListOfStations["5"]);
-
- // Store image filenames into AFDB
- writeImage<MaskImageType>(m_ListOfStations["5"], "seg/Station5.mhd");
- GetAFDB()->SetImageFilename("Station5", "seg/Station5.mhd");
- WriteAFDB();
- StopSubStep();
-
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_5_Limits_AscendingAorta_Ant()
-{
- // ----------------------------------------------------------
- StartNewStep("[Station 5] Limits with Ant part of AscendingAorta");
-
- // Get AscendingAorta
- MaskImagePointer AscendingAorta = GetAFDB()->template GetImage<MaskImageType>("AscendingAorta");
-
- // Crop and select most Ant points
- AscendingAorta =
- clitk::ResizeImageLike<MaskImageType>(AscendingAorta, m_Working_Support, GetBackgroundValue());
- std::vector<MaskImagePointType> A;
- std::vector<MaskImagePointType> B;
- clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(AscendingAorta,
- GetBackgroundValue(),
- 2, 1, true, 0, -1, A, B);
- //1 mm margin
-
- // Separate according to AB lines
- // clitk::WriteListOfLandmarks<MaskImageType>(A, "A.txt");
- // clitk::WriteListOfLandmarks<MaskImageType>(B, "B.txt");
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, A, B,
- GetBackgroundValue(),
- 1, 10); // Keep point along axis 1
- // End
- StopCurrentStep<MaskImageType>(m_Working_Support);
-}
-//--------------------------------------------------------------------
-
-
+++ /dev/null
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_6_SetDefaultValues()
-{
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(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<MaskImageType>(m_ListOfStations["6"],
- GetBackgroundValue(),
- GetForegroundValue());
- StopCurrentStep<MaskImageType>(m_ListOfStations["6"]);
-
- // Store image filenames into AFDB
- writeImage<MaskImageType>(m_ListOfStations["6"], "seg/Station6.mhd");
- GetAFDB()->SetImageFilename("Station6", "seg/Station6.mhd");
- WriteAFDB();
- StopSubStep();
-
-}
-//--------------------------------------------------------------------
-
-
+++ /dev/null
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(m_ListOfStations["7"], "seg/Station7.mhd");
- GetAFDB()->SetImageFilename("Station7", "seg/Station7.mhd");
- WriteAFDB();
- }
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_7_SI_Limits()
-{
- StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLL-RMLBronchus");
- // Get Inputs
- MaskImagePointer Trachea = GetAFDB()->template GetImage <MaskImageType>("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<MaskImageType>(m_Working_Support, GetBackgroundValue(),
- A, B, 2, 0, false);
-
- // Get the CarinaZ position
- double m_CarinaZ = FindCarina();
-
- // Crop support
- m_Working_Support =
- clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2,
- A[2], m_CarinaZ, true,
- GetBackgroundValue());
- // Crop trachea
- m_Working_Trachea =
- clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2,
- A[2], m_CarinaZ, true,
- GetBackgroundValue());
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["7"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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 <MaskImageType>("RightBronchus");
- m_LeftBronchus = GetAFDB()->template GetImage <MaskImageType>("LeftBronchus");
-
- // Resize like m_Working_Support
- m_LeftBronchus =
- clitk::ResizeImageLike<MaskImageType>(m_LeftBronchus, m_Working_Support, GetBackgroundValue());
- m_RightBronchus =
- clitk::ResizeImageLike<MaskImageType>(m_RightBronchus, m_Working_Support, GetBackgroundValue());
-
- // Extract slices, Label, compute centroid, keep most central connected component
- std::vector<MaskSlicePointer> slices_leftbronchus;
- std::vector<MaskSlicePointer> slices_rightbronchus;
- std::vector<MaskSlicePointer> slices_support;
- clitk::ExtractSlices<MaskImageType>(m_LeftBronchus, 2, slices_leftbronchus);
- clitk::ExtractSlices<MaskImageType>(m_RightBronchus, 2, slices_rightbronchus);
- clitk::ExtractSlices<MaskImageType>(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.size(); i++) {
- slices_leftbronchus[i] = Labelize<MaskSliceType>(slices_leftbronchus[i], 0, false, 10);
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(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<c.size(); j++) {
- if (c[j][0] < most_at_left) {
- most_at_left = c[j][0];
- most_at_left_index = j;
- }
- }
- // Put all other CCL to Background
- slices_leftbronchus[i] =
- clitk::Binarize<MaskSliceType>(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.size(); i++) {
- slices_rightbronchus[i] = Labelize<MaskSliceType>(slices_rightbronchus[i], 0, false, 10);
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(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<c.size(); j++) {
- if (c[j][0] > 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<MaskSliceType>(slices_rightbronchus[i], most_at_right_index,
- most_at_right_index, GetBackgroundValue(), GetForegroundValue());
- } // end c.size
- }
-
- // Joint slices
- m_LeftBronchus = clitk::JoinSlices<MaskImageType>(slices_leftbronchus, m_LeftBronchus, 2);
- m_RightBronchus = clitk::JoinSlices<MaskImageType>(slices_rightbronchus, m_RightBronchus, 2);
-
- // For Right bronchus, Find most Left point. Remove corner Ant/Right corner
- for(uint i=0; i<slices_rightbronchus.size(); i++) {
- // Find most point most at left
- MaskSlicePointType p_left;
- MaskSlicePointType p_post;
- bool b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_rightbronchus[i], GetBackgroundValue(), 0, false, p_left);
- if (b) {
- b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskSliceType>(slices_support[i], GetBackgroundValue(), region);
- }
- }
-
- // For Left bronchus, Find most Right point. Remove corner Ant/Left corner
- for(uint i=0; i<slices_leftbronchus.size(); i++) {
- // Find most point most at right
- MaskSlicePointType p_right;
- MaskSlicePointType p_post;
- bool b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_leftbronchus[i], GetBackgroundValue(), 0, true, p_right);
- if (b) {
- b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<ImageType> 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<MaskSliceType>(slices_support[i], GetBackgroundValue(), region);
- }
- }
-
- m_Working_Support = clitk::JoinSlices<MaskImageType>(slices_support, m_Working_Support, 2);
-
- // Also remove what is at right of the Right bronchus (left respectively)
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, m_LeftBronchus, 2,
- GetFuzzyThreshold("7", "Bronchi"), "NotLeftTo",
- false, 3, false);
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, m_RightBronchus, 2,
- GetFuzzyThreshold("7", "Bronchi"), "NotRightTo",
- false, 3, false);
-
- // SECOND PART
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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 <MaskImageType>("RightBronchus");
- m_LeftBronchus = GetAFDB()->template GetImage <MaskImageType>("LeftBronchus");
-
- // Extract slices, Label, compute centroid, keep most central connected component
- std::vector<MaskSlicePointer> slices_leftbronchus;
- std::vector<MaskSlicePointer> slices_rightbronchus;
- clitk::ExtractSlices<MaskImageType>(m_LeftBronchus, 2, slices_leftbronchus);
- clitk::ExtractSlices<MaskImageType>(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.size(); i++) {
- slices_leftbronchus[i] = Labelize<MaskSliceType>(slices_leftbronchus[i], 0, false, 10);
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(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<c.size(); j++) {
- if (c[j][0] < most_at_left) {
- most_at_left = c[j][0];
- most_at_left_index = j;
- }
- }
- // Put all other CCL to Background
- slices_leftbronchus[i] =
- clitk::Binarize<MaskSliceType>(slices_leftbronchus[i], most_at_left_index,
- most_at_left_index, GetBackgroundValue(), GetForegroundValue());
- } // end c.size
- }
-
- for(uint i=0; i<slices_rightbronchus.size(); i++) {
- slices_rightbronchus[i] = Labelize<MaskSliceType>(slices_rightbronchus[i], 0, false, 10);
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(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<c.size(); j++) {
- if (c[j][0] > 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<MaskSliceType>(slices_rightbronchus[i], most_at_right_index,
- most_at_right_index, GetBackgroundValue(), GetForegroundValue());
- } // end c.size
- }
-
- // Joint slices
- m_LeftBronchus = clitk::JoinSlices<MaskImageType>(slices_leftbronchus, m_LeftBronchus, 2);
- m_RightBronchus = clitk::JoinSlices<MaskImageType>(slices_rightbronchus, m_RightBronchus, 2);
-
- writeImage<MaskImageType>(m_LeftBronchus, "step-left.mhd");
- writeImage<MaskImageType>(m_RightBronchus, "step-right.mhd");
-
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, m_LeftBronchus, 2,
- GetFuzzyThreshold("7", "Bronchi"), "RightTo",
- false, 3, false);
- StopCurrentStep<MaskImageType>(m_Working_Support);
-
-
- // ----------------------------------------------------------------
- StartNewStep("[Station7] Limits with bronchus : LeftTo the right bronchus");
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, m_RightBronchus, 2,
- GetFuzzyThreshold("7", "Bronchi"), "LeftTo",
- false, 3, false);
- StopCurrentStep<MaskImageType>(m_Working_Support);
-
-
- // ----------------------------------------------------------------
- StartNewStep("[Station7] Limits with LeftSuperiorPulmonaryVein");
- try {
- MaskImagePointer LeftSuperiorPulmonaryVein = GetAFDB()->template GetImage<MaskImageType>("LeftSuperiorPulmonaryVein");
- typedef SliceBySliceRelativePositionFilter<MaskImageType> 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<MaskImageType>(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<MaskImageType>("RightSuperiorPulmonaryVein");
- typedef SliceBySliceRelativePositionFilter<MaskImageType> 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<MaskImageType>(m_Working_Support);
- }
- catch (clitk::ExceptionObject e) {
- std::cout << "Not RightSuperiorPulmonaryVein, skip" << std::endl;
- }
-
- // ----------------------------------------------------------------
- StartNewStep("[Station7] Limits with RightPulmonaryArtery");
- MaskImagePointer RightPulmonaryArtery = GetAFDB()->template GetImage<MaskImageType>("RightPulmonaryArtery");
- typedef SliceBySliceRelativePositionFilter<MaskImageType> 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<MaskImageType>(m_Working_Support);
-
- // ----------------------------------------------------------------
- StartNewStep("[Station7] Limits with LeftPulmonaryArtery");
- MaskImagePointer LeftPulmonaryArtery = GetAFDB()->template GetImage<MaskImageType>("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<MaskImageType>(m_Working_Support);
-
- StartNewStep("[Station7] Limits with SVC");
- MaskImagePointer SVC = GetAFDB()->template GetImage<MaskImageType>("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<MaskImageType>(m_Working_Support);
-
- // End
- m_ListOfStations["7"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(m_RightBronchus, m_Working_Support, GetBackgroundValue());
- MaskImagePointer LeftBronchus = clitk::ResizeImageLike<MaskImageType>(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_RightMostInLeftBronchus.size(); i++) {
- osrl << i << " " << m_RightMostInLeftBronchus[i][0] << " " << m_RightMostInLeftBronchus[i][1]
- << " " << m_RightMostInLeftBronchus[i][2] << " 0 0 " << std::endl;
- osal << i << " " << m_AntMostInLeftBronchus[i][0] << " " << m_AntMostInLeftBronchus[i][1]
- << " " << m_AntMostInLeftBronchus[i][2] << " 0 0 " << std::endl;
- ospl << i << " " << m_PostMostInLeftBronchus[i][0] << " " << m_PostMostInLeftBronchus[i][1]
- << " " << m_PostMostInLeftBronchus[i][2] << " 0 0 " << std::endl;
- }
-
- for(uint i=0; i<m_LeftMostInRightBronchus.size(); i++) {
- osrr << i << " " << m_LeftMostInRightBronchus[i][0] << " " << m_LeftMostInRightBronchus[i][1]
- << " " << m_LeftMostInRightBronchus[i][2] << " 0 0 " << std::endl;
- osar << i << " " << m_AntMostInRightBronchus[i][0] << " " << m_AntMostInRightBronchus[i][1]
- << " " << m_AntMostInRightBronchus[i][2] << " 0 0 " << std::endl;
- ospr << i << " " << m_PostMostInRightBronchus[i][0] << " " << m_PostMostInRightBronchus[i][1]
- << " " << m_PostMostInRightBronchus[i][2] << " 0 0 " << std::endl;
- }
- osrl.close();
- osal.close();
- ospl.close();
- osrr.close();
- osar.close();
- ospr.close();
-
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
- m_PostMostInRightBronchus,
- m_PostMostInLeftBronchus,
- GetBackgroundValue(), 1, -10);
- // If needed -> can do the same with AntMost.
-
- // End
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["7"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>(m_Working_Support, GetBackgroundValue(), GetForegroundValue());
-
- Remove_Structures("7", "Esophagus");
-
- // END
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["7"] = m_Working_Support;
- return;
-}
-//--------------------------------------------------------------------
-
-
-
+++ /dev/null
-
-#include <itkBinaryDilateImageFilter.h>
-#include <itkMirrorPadImageFilter.h>
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>(m_ListOfStations["8"], "seg/Station8.mhd");
- GetAFDB()->SetImageFilename("Station8", "seg/Station8.mhd");
- WriteAFDB();
- StopSubStep();
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>(m_Working_Support,
- GetBackgroundValue(), A, B, 2, 0, true);
-
- /* -----------------------------------------------
- INFERIOR LIMIT = Diaphragm
- -----------------------------------------------
- */
-
- // Found most inferior part of the lung
- MaskImagePointer Lungs = GetAFDB()->template GetImage<MaskImageType>("Lungs");
- // It should be already croped, so I took the origin and add 10mm above
- m_DiaphragmInferiorLimit = Lungs->GetOrigin()[2]+10;
- GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
-
- m_Working_Support =
- clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2,
- m_DiaphragmInferiorLimit,
- B[2], true,
- GetBackgroundValue());
- // Done.
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>("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<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue()); // Needed ?
-
- // Dilate to keep only not Anterior positions
- MaskImagePointType radiusInMM = GetEsophagusDiltationForAnt();
- m_Esophagus = clitk::Dilate<MaskImageType>(m_Esophagus,
- radiusInMM,
- GetBackgroundValue(),
- GetForegroundValue(), true);
- // Keep what is Posterior to Esophagus
- typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> 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<MaskImageType>(m_Working_Support, GetBackgroundValue());
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>("Aorta");
- MaskImagePointer PulmonaryTrunk = GetAFDB()->template GetImage<MaskImageType>("PulmonaryTrunk");
-
- // Resize like the PT and define the slices
- MaskImagePointType min, max;
- clitk::GetMinMaxPointPosition<MaskImageType>(PulmonaryTrunk, min, max);
- Aorta = clitk::CropImageAlongOneAxis<MaskImageType>(Aorta, 2, min[2], max[2], false, GetBackgroundValue());
- std::vector<MaskSlicePointer> slices_aorta;
- clitk::ExtractSlices<MaskImageType>(Aorta, 2, slices_aorta);
- std::vector<MaskSlicePointer> slices_PT;
- clitk::ExtractSlices<MaskImageType>(PulmonaryTrunk, 2, slices_PT);
-
- // Find the points at left
- std::vector<MaskImagePointType> p_A;
- std::vector<MaskImagePointType> p_B;
- MaskImagePointType pA;
- MaskImagePointType pB;
- for(uint i=0; i<slices_PT.size(); i++) {
- typename MaskSliceType::PointType ps;
- // In Aorta (assume a single CCL)
- bool found =
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_aorta[i], GetBackgroundValue(), 0, false, ps);
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(ps, Aorta, i, pA);
-
- if (found) {
- // In PT : generally 2 CCL, we keep the most at left
- found =
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_PT[i], GetBackgroundValue(), 0, false, ps);
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(ps, PulmonaryTrunk, i, pB);
- }
-
- if (found) {
- p_A.push_back(pA);
- p_B.push_back(pB);
- }
- }
- clitk::WriteListOfLandmarks<MaskImageType>(p_A, "S8-Aorta-Left-points.txt");
- clitk::WriteListOfLandmarks<MaskImageType>(p_B, "S8-PT-Left-points.txt");
-
- // Remove part at Left
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
- p_A, p_B,
- GetBackgroundValue(),
- 0, -10);
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_Single_CCL_Limits()
-{
- //--------------------------------------------------------------------
- StartNewStep("[Station8 or 3P] Slice by slice, keep a single CCL (the closest to VertebralBody)");
-
- // Consider slices
- std::vector<typename MaskSliceType::Pointer> slices;
- std::vector<typename MaskSliceType::Pointer> slices_vb;
- clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
- MaskImagePointer VertebralBody =
- GetAFDB()->template GetImage <MaskImageType>("VertebralBody");
- VertebralBody = clitk::ResizeImageLike<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
- clitk::ExtractSlices<MaskImageType>(VertebralBody, 2, slices_vb);
-
- for(uint i=0; i<slices.size(); i++) {
- // Decompose in labels
- slices[i] = Labelize<MaskSliceType>(slices[i], 0, true, 100);
- // Compute centroids coordinate
- std::vector<typename MaskSliceType::PointType> centroids;
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(slices[i], GetBackgroundValue(), centroids);
- clitk::ComputeCentroids<MaskSliceType>(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<centroids.size(); j++) {
- double d = centroids[j].EuclideanDistanceTo(c[1]);
- if (d<distance) {
- distance = d;
- index = j;
- }
- }
- // remove all others label
- slices[i] = KeepLabels<MaskSliceType>(slices[i], GetBackgroundValue(),
- GetForegroundValue(), index, index, true);
- }
- }
- m_Working_Support = clitk::JoinSlices<MaskImageType>(slices, m_Working_Support, 2);
-
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<typename MaskSliceType::Pointer> slices;
- clitk::ExtractSlices<MaskImageType>(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<MaskImageType>("Lungs");
- clitk::AndNot<MaskImageType>(m_Esophagus, Lungs, GetBackgroundValue());
- GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
-
- // Estract slices of Esophagus (resize like support before to have the same set of slices)
- MaskImagePointer EsophagusForSlice =
- clitk::ResizeImageLike<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue());
- std::vector<typename MaskSliceType::Pointer> eso_slices;
- clitk::ExtractSlices<MaskImageType>(EsophagusForSlice, 2, eso_slices);
-
- // Estract slices of Vertebral (resize like support before to have the same set of slices)
- MaskImagePointer VertebralBody = GetAFDB()->template GetImage<MaskImageType>("VertebralBody");
- VertebralBody = clitk::ResizeImageLike<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
- // Remove what is outside the support to not consider what is to
- // posterior in the VertebralBody (post the horizontal line)
- clitk::And<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
- // writeImage<MaskImageType>(VertebralBody, "vb.mhd");
- std::vector<typename MaskSliceType::Pointer> vert_slices;
- clitk::ExtractSlices<MaskImageType>(VertebralBody, 2, vert_slices);
-
- // Estract slices of Aorta (resize like support before to have the same set of slices)
- MaskImagePointer Aorta = GetAFDB()->template GetImage<MaskImageType>("Aorta");
- Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, m_Working_Support, GetBackgroundValue());
- std::vector<typename MaskSliceType::Pointer> aorta_slices;
- clitk::ExtractSlices<MaskImageType>(Aorta, 2, aorta_slices);
-
- // Extract slices of Mediastinum (resize like support before to have the same set of slices)
- m_Mediastinum = GetAFDB()->template GetImage<MaskImageType>("Mediastinum");
- m_Mediastinum = clitk::ResizeImageLike<MaskImageType>(m_Mediastinum, m_Working_Support, GetBackgroundValue());
- std::vector<typename MaskSliceType::Pointer> mediast_slices;
- clitk::ExtractSlices<MaskImageType>(m_Mediastinum, 2, mediast_slices);
-
- // List of points
- std::vector<MaskImagePointType> p_MostLeftVertebralBody;
- std::vector<MaskImagePointType> p_MostRightVertebralBody;
- std::vector<MaskImagePointType> p_MostLeftAorta;
- std::vector<MaskImagePointType> p_MostLeftEsophagus;
-
- /*
- In the following, we search for the LeftRight limits. We search
- for the most Right points in Esophagus and in VertebralBody and
- consider a line between those to most right points. All points in
- the support which are most right to this line are discarded. Same
- for the left part. The underlying assumption is that the support
- is concave between Eso/VertebralBody. Esophagus is a bit
- dilatated. On VertebralBody we go right (or left) until we reach
- the lung (but no more 20 mm).
- */
-
- // Temporary 3D point
- MaskImagePointType p;
-
- typename MaskSliceType::PointType minSlicePoint;
- typename MaskSliceType::PointType maxSlicePoint;
- clitk::GetMinMaxPointPosition<MaskSliceType>(vert_slices[0], minSlicePoint, maxSlicePoint);
-
- // Loop slices
- for(uint i=0; i<slices.size() ; i++) {
- // Declare all needed 2D points (sp = slice point)
- // typename MaskSliceType::PointType sp_MostRightVertebralBody;
- typename MaskSliceType::PointType sp_MostLeftVertebralBody;
- typename MaskSliceType::PointType sp_MostLeftAorta;
- typename MaskSliceType::PointType sp_temp;
- typename MaskSliceType::PointType sp_MostLeftEsophagus;
-
- /* -------------------------------------------------------------------------------------
- Find first point not in mediastinum at LEFT
- */
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[i], GetBackgroundValue(),
- 0, false, sp_MostLeftVertebralBody);
- // clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
- // DD(p);
-
- sp_MostLeftVertebralBody =
- clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, false,
- sp_MostLeftVertebralBody, GetBackgroundValue(), 30);
- // clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
- // DD(p);
-
- sp_MostLeftVertebralBody[0] += 2; // 2mm margin
- // clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
- // DD(p);
-
- // Convert 2D points into 3D
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
- p_MostLeftVertebralBody.push_back(p);
-
- /* -------------------------------------------------------------------------------------
- Find first point not in mediastinum at RIGHT. Not used yet.
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[i], GetBackgroundValue(),
- 0, true, sp_MostRightVertebralBody);
- sp_MostRightVertebralBody =
- clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, true,
- sp_MostRightVertebralBody, GetBackgroundValue(),30);
- sp_MostRightVertebralBody[0] -= 2; // 2 mm margin
-
- // Convert 2D points into 3D
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostRightVertebralBody, VertebralBody, i, p);
- p_MostRightVertebralBody.push_back(p);
- */
-
-
- /* -------------------------------------------------------------------------------------
- Find most Left point in Esophagus
- */
- bool found = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskImageType>::Convert2DTo3D(sp_MostLeftEsophagus, EsophagusForSlice, i, p);
- p_MostLeftEsophagus.push_back(p);
- }
-
- /* -------------------------------------------------------------------------------------
- Find most Left point in Aorta
- */
- if (found) {
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftAorta);
- sp_MostLeftAorta = clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, false, sp_MostLeftAorta, GetBackgroundValue(), 10);
- typename MaskSliceType::PointType temp=sp_MostLeftEsophagus;
- temp[0] -= 10;
- if (clitk::IsOnTheSameLineSide(sp_MostLeftAorta, sp_MostLeftVertebralBody, sp_MostLeftEsophagus, temp)) {
- // sp_MostLeftAorta is on the same side than temp (at Right) -> ignore Aorta
- sp_MostLeftAorta = sp_MostLeftEsophagus;
- }
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftAorta, Aorta, i, p);
- p_MostLeftAorta.push_back(p);
- }
-
- } // End of slice loop
-
- clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftVertebralBody, "S8-MostLeft-VB-points.txt");
- // clitk::WriteListOfLandmarks<MaskImageType>(p_MostRightVertebralBody, "S8-MostRight-VB-points.txt");
- clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftAorta, "S8-MostLeft-Aorta-points.txt");
- clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftEsophagus, "S8-MostLeft-eso-points.txt");
-
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
- p_MostLeftVertebralBody, p_MostLeftAorta,
- GetBackgroundValue(), 0, -10);
-
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
- p_MostLeftAorta, p_MostLeftEsophagus,
- GetBackgroundValue(), 0, -10);
- // END
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["8"] = m_Working_Support;
- return;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_Remove_Structures()
-{
- //--------------------------------------------------------------------
- Remove_Structures("8", "Aorta");
- Remove_Structures("8", "Esophagus");
- Remove_Structures("8", "VertebralBody");
-
- // END
- StopCurrentStep<MaskImageType>(m_Working_Support);
- m_ListOfStations["8"] = m_Working_Support;
- return;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<typename MaskSliceType::Pointer> slices;
- clitk::ExtractSlices<MaskImageType>(input, 2, slices);
-
- // Loop on slices
- bool found;
- for(uint i=0; i<slices.size(); i++) {
- /*
- // Keep main CCL
- slices[i] = Labelize<MaskSliceType>(slices[i], 0, true, 10);
- slices[i] = KeepLabels<MaskSliceType>(slices[i],
- GetBackgroundValue(),
- GetForegroundValue(), 1, 1, true);
- */
-
- // ------- Find rightmost or leftmost point -------
- MaskSliceType::PointType LRMost;
- found =
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskSliceType>(slices[i],
- GetBackgroundValue(),
- 1, false, LRMost,
- distance_max_from_center_point,
- postMost);
- // ------- Find antmost point -------
- MaskSliceType::PointType antMost;
- found =
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskImageType>::Convert2DTo3D(LRMost, input, i, p);
- LR.push_back(p);
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(antMost, input, i, p);
- Ant.push_back(p);
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(postMost, input, i, p);
- Post.push_back(p);
- }
- }
-}
-//--------------------------------------------------------------------
+++ /dev/null
-
-#include <itkBinaryDilateImageFilter.h>
-#include <itkMirrorPadImageFilter.h>
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStationSupports()
-{
- // Get initial Mediastinum
- m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage<MaskImageType>("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; i<m_ListOfSupportLimits.size(); i++) {
- SupportLimitsType s = m_ListOfSupportLimits[i];
- Support_SI_Limit(s.station_limit, s.station, s.structure_limit,
- s.structure, s.offset*m_Working_Support->GetSpacing()[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<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
- m_ListOfSupports["S8"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
- m_ListOfSupports["S9"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
- m_ListOfSupports["S10"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
- m_ListOfSupports["S11"] = clitk::Clone<MaskImageType>(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 <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <MaskImageType>(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<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
- else
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(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<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
- else
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(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<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
- }
- else {
- m_Working_Support =
- clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
- }
-
- // Check: if reference station is given, display information
- if (GetCheckSupportFlag()) {
- try {
- MaskImagePointer Ref = this->GetAFDB()->template GetImage <MaskImageType>(station+"_Ref");
- MaskImagePointType p_support;
- MaskImagePointType p_ref;
- if (station_limit == "superior") {
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, false, p_ref);
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, false, p_support);
- }
- else {
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, true, p_ref);
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(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<MaskImageType>(m_Working_Support);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<ImagePointType> A;
- std::vector<ImagePointType> B;
- // Search for centroid positions of trachea
- MaskImagePointer Trachea = this->GetAFDB()->template GetImage <MaskImageType>("Trachea");
- MaskImagePointer S1RL = m_ListOfSupports["S1R"];
- Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, S1RL, GetBackgroundValue());
- std::vector<MaskSlicePointer> slices;
- clitk::ExtractSlices<MaskImageType>(Trachea, 2, slices);
- for(uint i=0; i<slices.size(); i++) {
- slices[i] = Labelize<MaskSliceType>(slices[i], 0, false, 10);
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(slices[i], GetBackgroundValue(), c);
- ImagePointType a,b;
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(c[1], Trachea, i, a);
- A.push_back(a);
- b = a;
- b[1] += 50;
- B.push_back(b);
- }
- clitk::WriteListOfLandmarks<MaskImageType>(A, "S1LR_A.txt");
- clitk::WriteListOfLandmarks<MaskImageType>(B, "S1LR_B.txt");
-
- // Clone support
- MaskImagePointer S1R = clitk::Clone<MaskImageType>(S1RL);
- MaskImagePointer S1L = clitk::Clone<MaskImageType>(S1RL);
-
- // Right part
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
- GetBackgroundValue(), 0, -10);
- S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
- m_ListOfSupports["S1R"] = S1R;
-
- // Left part
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
- GetBackgroundValue(), 0, 10);
- S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
- m_ListOfSupports["S1L"] = S1L;
- StopCurrentStep<MaskImageType>(m_ListOfSupports["S1L"]);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>(S2R, GetBackgroundValue());
- S2L = clitk::AutoCrop<MaskImageType>(S2L, GetBackgroundValue());
- m_ListOfSupports["S2R"] = S2R;
- m_ListOfSupports["S2L"] = S2L;
- this->GetAFDB()->template ReleaseImage<MaskImageType>("Trachea");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <class ImageType>
-typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
-clitk::ExtractLymphStationsFilter<ImageType>::
-LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection,
- double offset)
-{
- MaskImagePointType min, max;
- GetMinMaxBoundary<MaskImageType>(input, min, max);
- return LimitsWithTrachea(input, extremaDirection, lineDirection, offset, max[2]);
-}
-template <class ImageType>
-typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>("Trachea");
-
- // Find extrema post positions
- std::vector<MaskImagePointType> tracheaLeftPositionsA;
- std::vector<MaskImagePointType> tracheaLeftPositionsB;
-
- // Crop Trachea only on the Sup-Inf axes, without autocrop
- // Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, input, GetBackgroundValue());
- MaskImagePointType min, max;
- GetMinMaxBoundary<MaskImageType>(input, min, max);
- Trachea = clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2, min[2], max[2],
- false, GetBackgroundValue());
-
- // Select the main CCL (because of bronchus)
- Trachea = SliceBySliceKeepMainCCL<MaskImageType>(Trachea, GetBackgroundValue(), GetForegroundValue());
-
- // Slice by slice, build the separation line
- clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(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<tracheaLeftPositionsA.size(); i++) {
- if (tracheaLeftPositionsA[i][2] > 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<MaskImageType>(input,
- tracheaLeftPositionsA,
- tracheaLeftPositionsB,
- GetBackgroundValue(),
- extremaDirection, offset);
- MaskImagePointer output = clitk::AutoCrop<MaskImageType>(input, GetBackgroundValue());
- return output;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImagePointType> A;
- std::vector<MaskImagePointType> B;
-
- // Crop S3P like S1R
- MaskImagePointer S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
- S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1R, GetBackgroundValue());
-
- // Slice by slice, build the separation line
- clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P,
- GetBackgroundValue(), 2,
- 1, true, // Ant-Post
- 0, // Horizontal line
- 0, // margins
- A, B);
-
- // clitk::WriteListOfLandmarks<MaskImageType>(A, "A-S1S3P.txt");
- // clitk::WriteListOfLandmarks<MaskImageType>(B, "B-S1S3P.txt");
-
- // Cut post to this line
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
- GetBackgroundValue(),
- 1, -10);
-
- // Crop S3P like S1L (Redo for S1L)
- S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
- S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1L, GetBackgroundValue());
-
- // Slice by slice, build the separation line
- A.clear();
- B.clear();
- clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P,
- GetBackgroundValue(), 2,
- 1, true, // Ant-Post
- 0, // Horizontal line
- 0, // margins
- A, B);
- // Cut post to this line
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
- GetBackgroundValue(),
- 1, -10);
-
- // Crop both images
- S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
- S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
-
- StopCurrentStep<MaskImageType>(S1R);
-
- m_ListOfSupports["S1R"] = S1R;
- m_ListOfSupports["S1L"] = S1L;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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<MaskImageType>("RightLung");
-
- // Find common area between S1 and S2
- MaskImagePointType p_min;
- MaskImagePointType p_max;
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2R"],
- GetBackgroundValue(), 2, false, p_max);
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(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<MaskImageType>(RightLung);
- RightLung = clitk::ResizeImageLike<MaskImageType>(RightLung, m_ListOfSupports["S1R"], GetBackgroundValue());
- RightLung = clitk::CropImageRemoveLowerThan<MaskImageType>(RightLung, 2, p_min[2], true, GetBackgroundValue());
- RightLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(RightLung, 2, p_max[2], true, GetBackgroundValue());
-
- // Find extrema ant positions for RightLung
- std::vector<MaskImagePointType> A;
- std::vector<MaskImagePointType> B;
- clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(RightLung,
- GetBackgroundValue(), 2,
- 1, true, // Ant-Post
- 0, // Horizontal line
- 0, // margins
- A, B);
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1R"],
- A, B,
- GetBackgroundValue(),
- 1, -10);
- // I add one pixel to abupt S2R to S1R
- for(int i=0; i<A.size(); i++) {
- A[i][1] -= RightLung->GetSpacing()[1];
- B[i][1] -= RightLung->GetSpacing()[1];
- }
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2R"],
- A, B,
- GetBackgroundValue(),
- 1, 10);
- }
-
- // Get LeftLung, crop
- MaskImagePointer LeftLung = this->GetAFDB()->template GetImage<MaskImageType>("LeftLung");
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2L"],
- GetBackgroundValue(), 2, false, p_max);
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(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<MaskImageType>(LeftLung, m_ListOfSupports["S1L"], GetBackgroundValue());
- LeftLung = clitk::CropImageRemoveLowerThan<MaskImageType>(LeftLung, 2, p_min[2], true, GetBackgroundValue());
- LeftLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(LeftLung, 2, p_max[2], true, GetBackgroundValue());
-
- // Find extrema ant positions for LeftLung
- std::vector<MaskImagePointType> A;
- std::vector<MaskImagePointType> B;
- clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(LeftLung,
- GetBackgroundValue(), 2,
- 1, true, // Ant-Post
- 0, // Horizontal line
- 0, // margins
- A, B);
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1L"],
- A, B,
- GetBackgroundValue(),
- 1, -10);
- // I add one pixel to abupt S2R to S1R
- for(int i=0; i<A.size(); i++) {
- A[i][1] -= LeftLung->GetSpacing()[1];
- B[i][1] -= LeftLung->GetSpacing()[1];
- }
- clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2L"],
- A, B,
- GetBackgroundValue(),
- 1, 10);
- }
-}
-//--------------------------------------------------------------------
+++ /dev/null
-/*=========================================================================
- 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<args_info_clitkExtractLymphStations> 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
-//--------------------------------------------------------------------
+++ /dev/null
-#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
-
+++ /dev/null
-/*=========================================================================
- 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 <vtkPolyData.h>
-
-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 TImageType>
- class ITK_EXPORT ExtractLymphStationsFilter:
- public clitk::StructuresExtractionFilter<TImageType>
- {
-
- public:
- /** Standard class typedefs. */
- typedef clitk::StructuresExtractionFilter<TImageType> Superclass;
- typedef ExtractLymphStationsFilter Self;
- typedef itk::SmartPointer<Self> Pointer;
- typedef itk::SmartPointer<const Self> 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<MaskImagePixelType, 3> 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<MaskImagePixelType, 2> 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<class TInternalImageType>
- void StopCurrentStep(typename TInternalImageType::Pointer p, std::string txt="") { clitk::FilterBase::StopCurrentStep<TInternalImageType>(p, txt); }
- void StopCurrentStep() {clitk::FilterBase::StopCurrentStep(); }
- void StopSubStep() {clitk::FilterBase::StopSubStep(); }
-
- ImageConstPointer m_Input;
- MaskImagePointer m_Mediastinum;
- MaskImagePointer m_Working_Support;
- std::map<std::string, MaskImagePointer> m_ListOfStations;
- std::map<std::string, MaskImagePointer> m_ListOfSupports;
- MaskImagePixelType m_BackgroundValue;
- MaskImagePixelType m_ForegroundValue;
- std::map<std::string, bool> m_ComputeStationMap;
- std::string m_SupportLimitsFilename;
- std::vector<SupportLimitsType> 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<std::string, double> FuzzyThresholdByStructureType;
- std::map<std::string, FuzzyThresholdByStructureType> m_FuzzyThreshold;
- typedef std::map<std::string, double> ThresholdByStructureType;
- std::map<std::string, ThresholdByStructureType> 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<vtkPolyData> Build3DMeshFrom2DContour(const std::vector<ImagePointType> & 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<MaskImageType::PointType> 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
+++ /dev/null
-/*=========================================================================
- 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 <itkStatisticsLabelMapFilter.h>
-#include <itkLabelImageToStatisticsLabelMapFilter.h>
-#include <itkRegionOfInterestImageFilter.h>
-#include <itkBinaryThresholdImageFilter.h>
-#include <itkImageSliceConstIteratorWithIndex.h>
-#include <itkImageSliceIteratorWithIndex.h>
-#include <itkBinaryThinningImageFilter.h>
-
-// itk ENST
-#include "RelativePositionPropImageFilter.h"
-
-// vtk
-#include <vtkAppendPolyData.h>
-#include <vtkPolyDataWriter.h>
-#include <vtkCellArray.h>
-
-//--------------------------------------------------------------------
-template <class TImageType>
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractLymphStationsFilter():
- clitk::StructuresExtractionFilter<ImageType>()
-{
- 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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateOutputInformation() {
- // Get inputs
- this->LoadAFDB();
- m_Input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
- m_Mediastinum = this->GetAFDB()->template GetImage <MaskImageType>("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<MaskImageType>("Support_S1R");
- m_ListOfSupports["S1L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S1L");
- m_ListOfSupports["S2R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S2R");
- m_ListOfSupports["S2L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S2L");
- m_ListOfSupports["S4R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S4R");
- m_ListOfSupports["S4L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S4L");
-
- m_ListOfSupports["S3A"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S3A");
- m_ListOfSupports["S3P"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S3P");
- m_ListOfSupports["S5"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S5");
- m_ListOfSupports["S6"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S6");
- m_ListOfSupports["S7"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S7");
- m_ListOfSupports["S8"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S8");
- m_ListOfSupports["S9"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S9");
- m_ListOfSupports["S10"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S10");
- m_ListOfSupports["S11"] = this->GetAFDB()->template GetImage<MaskImageType>("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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateInputRequestedRegion() {
- //DD("GenerateInputRequestedRegion (nothing?)");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateData() {
- // Final Step -> graft output (if SetNthOutput => redo)
- // this->GraftOutput(m_ListOfStations["8"]);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-bool
-clitk::ExtractLymphStationsFilter<TImageType>::
-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<MaskImageType>("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<MaskImageType>(s);
- //found = true;
- }
-
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-bool
-clitk::ExtractLymphStationsFilter<TImageType>::
-GetComputeStation(std::string station)
-{
- return (m_ComputeStationMap.find(station) != m_ComputeStationMap.end());
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-AddComputeStation(std::string station)
-{
- m_ComputeStationMap[station] = true;
-}
-//--------------------------------------------------------------------
-
-
-
-//--------------------------------------------------------------------
-template<class PointType>
-class comparePointsX {
-public:
- bool operator() (PointType i, PointType j) { return (i[0]<j[0]); }
-};
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template<class PairType>
-class comparePointsWithAngle {
-public:
- bool operator() (PairType i, PairType j) { return (i.second < j.second); }
-};
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template<int Dim>
-void HypercubeCorners(std::vector<itk::Point<double, Dim> > & out) {
- std::vector<itk::Point<double, Dim-1> > previous;
- HypercubeCorners<Dim-1>(previous);
- out.resize(previous.size()*2);
- for(unsigned int i=0; i<out.size(); i++) {
- itk::Point<double, Dim> p;
- if (i<previous.size()) p[0] = 0;
- else p[0] = 1;
- for(int j=0; j<Dim-1; j++)
- {
- p[j+1] = previous[i%previous.size()][j];
- }
- out[i] = p;
- }
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template<>
-void HypercubeCorners<1>(std::vector<itk::Point<double, 1> > & out) {
- out.resize(2);
- out[0][0] = 0;
- out[1][0] = 1;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template<class ImageType>
-void ComputeImageBoundariesCoordinates(typename ImageType::Pointer image,
- std::vector<typename ImageType::PointType> & 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; i<dim; i++)
- max_i[i] = image->GetLargestPossibleRegion().GetSize()[i] + min_i[i];
- image->TransformIndexToPhysicalPoint(min_i, min_c);
- image->TransformIndexToPhysicalPoint(max_i, max_c);
-
- // Get corners coordinates
- HypercubeCorners<ImageType::ImageDimension>(bounds);
- for(unsigned int i=0; i<bounds.size(); i++) {
- for(unsigned int j=0; j<dim; j++) {
- if (bounds[i][j] == 0) bounds[i][j] = min_c[j];
- if (bounds[i][j] == 1) bounds[i][j] = max_c[j];
- }
- }
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-Remove_Structures(std::string station, std::string s)
-{
- try {
- this->StartNewStep("[Station"+station+"] Remove "+s);
- MaskImagePointer Structure = this->GetAFDB()->template GetImage<MaskImageType>(s);
- clitk::AndNot<MaskImageType>(m_Working_Support, Structure, GetBackgroundValue());
- }
- catch(clitk::ExceptionObject e) {
- std::cout << s << " not found, skip." << std::endl;
- }
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-SetFuzzyThreshold(std::string station, std::string tag, double value)
-{
- m_FuzzyThreshold[station][tag] = value;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-SetThreshold(std::string station, std::string tag, double value)
-{
- m_Threshold[station][tag] = value;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-double
-clitk::ExtractLymphStationsFilter<TImageType>::
-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 <class TImageType>
-double
-clitk::ExtractLymphStationsFilter<TImageType>::
-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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-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 <MaskImageType>("LeftLowerLobeBronchus");
- std::vector<MaskImagePointType> c;
- clitk::ComputeCentroids<MaskImageType>(LeftLowerLobeBronchus, GetBackgroundValue(), c);
- A = c[1];
-
- // Load RightMiddleLobeBronchus and get superior point (not centroid here)
- MaskImagePointer RightMiddleLobeBronchus =
- this->GetAFDB()->template GetImage <MaskImageType>("RightMiddleLobeBronchus");
- bool b = FindExtremaPointInAGivenDirection<MaskImageType>(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 <class TImageType>
-double
-clitk::ExtractLymphStationsFilter<TImageType>::
-FindCarina()
-{
- double z;
- try {
- z = this->GetAFDB()->GetDouble("CarinaZ");
- }
- catch(clitk::ExceptionObject e) {
- //DD("FindCarinaSlicePosition");
- // Get Carina
- MaskImagePointer Carina = this->GetAFDB()->template GetImage<MaskImageType>("Carina");
-
- // Get Centroid and Z value
- std::vector<MaskImagePointType> centroids;
- clitk::ComputeCentroids<MaskImageType>(Carina, GetBackgroundValue(), centroids);
-
- // We dont need Carina structure from now
- this->GetAFDB()->template ReleaseImage<MaskImageType>("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 <class TImageType>
-double
-clitk::ExtractLymphStationsFilter<TImageType>::
-FindApexOfTheChest()
-{
- double z;
- try {
- z = this->GetAFDB()->GetDouble("ApexOfTheChestZ");
- }
- catch(clitk::ExceptionObject e) {
-
- /*
- //DD("FindApexOfTheChestPosition");
- MaskImagePointer Lungs = this->GetAFDB()->template GetImage<MaskImageType>("Lungs");
- MaskImagePointType p;
- p[0] = p[1] = p[2] = 0.0; // to avoid warning
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Lungs, GetBackgroundValue(), 2, false, p);
-
- // We dont need Lungs structure from now
- this->GetAFDB()->template ReleaseImage<MaskImageType>("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<MaskImageType>("RightLung");
- MaskImagePointer LeftLung = this->GetAFDB()->template GetImage<MaskImageType>("LeftLung");
- MaskImagePointType pr;
- MaskImagePointType pl;
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(RightLung, GetBackgroundValue(), 2, false, pr);
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(LeftLung, GetBackgroundValue(), 2, false, pl);
- // We dont need Lungs structure from now
- this->GetAFDB()->template ReleaseImage<MaskImageType>("RightLung");
- this->GetAFDB()->template ReleaseImage<MaskImageType>("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 <class TImageType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-FindLeftAndRightBronchi()
-{
- try {
- m_RightBronchus = this->GetAFDB()->template GetImage <MaskImageType>("RightBronchus");
- m_LeftBronchus = this->GetAFDB()->template GetImage <MaskImageType>("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<MaskImageType>("Trachea");
-
- // Get the Carina position
- double m_CarinaZ = FindCarina();
-
- // Consider only inferiorly to the Carina
- MaskImagePointer m_Working_Trachea =
- clitk::CropImageRemoveGreaterThan<MaskImageType>(Trachea, 2, m_CarinaZ, true, // AutoCrop
- GetBackgroundValue());
-
- // Labelize the trachea
- m_Working_Trachea = Labelize<MaskImageType>(m_Working_Trachea, 0, true, 1);
-
- // Carina position must at the first slice that separate the two
- // main bronchus (not superiorly). We thus first check that the
- // upper slice is composed of at least two labels
- MaskImagePointer RightBronchus;
- MaskImagePointer LeftBronchus;
- typedef itk::ImageSliceIteratorWithIndex<MaskImageType> SliceIteratorType;
- SliceIteratorType iter(m_Working_Trachea, m_Working_Trachea->GetLargestPossibleRegion());
- iter.SetFirstDirection(0);
- iter.SetSecondDirection(1);
- iter.GoToReverseBegin(); // Start from the end (because image is IS not SI)
- int maxLabel=0;
- while (!iter.IsAtReverseEndOfSlice()) {
- while (!iter.IsAtReverseEndOfLine()) {
- if (iter.Get() > maxLabel) maxLabel = iter.Get();
- --iter;
- }
- iter.PreviousLine();
- }
- if (maxLabel < 2) {
- clitkExceptionMacro("First slice 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<ImagePointType> c;
- clitk::ComputeCentroids<MaskImageType>(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<MaskImageType>(m_Working_Trachea, rightLabel, rightLabel,
- GetBackgroundValue(), GetForegroundValue());
- /*
- SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea,
- leftLabel, GetBackgroundValue(), false);
- */
- LeftBronchus = clitk::Binarize<MaskImageType>(m_Working_Trachea, leftLabel, leftLabel,
- GetBackgroundValue(), GetForegroundValue());
- /*
- SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea,
- rightLabel, GetBackgroundValue(), false);
- */
-
- // Crop images
- RightBronchus = clitk::AutoCrop<MaskImageType>(RightBronchus, GetBackgroundValue());
- LeftBronchus = clitk::AutoCrop<MaskImageType>(LeftBronchus, GetBackgroundValue());
-
- // Insert int AFDB if need after
- this->GetAFDB()->template SetImage <MaskImageType>("RightBronchus", "seg/rightBronchus.mhd",
- RightBronchus, true);
- this->GetAFDB()->template SetImage <MaskImageType>("LeftBronchus", "seg/leftBronchus.mhd",
- LeftBronchus, true);
- }
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-double
-clitk::ExtractLymphStationsFilter<TImageType>::
-FindSuperiorBorderOfAorticArch()
-{
- double z;
- try {
- z = this->GetAFDB()->GetDouble("SuperiorBorderOfAorticArchZ");
- }
- catch(clitk::ExceptionObject e) {
- // DD("FindSuperiorBorderOfAorticArch");
- MaskImagePointer Aorta = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
- MaskImagePointType p;
- p[0] = p[1] = p[2] = 0.0; // to avoid warning
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Aorta, GetBackgroundValue(), 2, false, p);
- p[2] += Aorta->GetSpacing()[2]; // the slice above
-
- // We dont need Lungs structure from now
- this->GetAFDB()->template ReleaseImage<MaskImageType>("Aorta");
-
- // Put inside the AFDB
- this->GetAFDB()->SetPoint3D("SuperiorBorderOfAorticArch", p);
- this->GetAFDB()->SetDouble("SuperiorBorderOfAorticArchZ", p[2]);
- this->WriteAFDB();
- z = p[2];
- }
- return z;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-double
-clitk::ExtractLymphStationsFilter<TImageType>::
-FindInferiorBorderOfAorticArch()
-{
- double z;
- try {
- z = this->GetAFDB()->GetDouble("InferiorBorderOfAorticArchZ");
- }
- catch(clitk::ExceptionObject e) {
- //DD("FindInferiorBorderOfAorticArch");
- MaskImagePointer Aorta = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
- std::vector<MaskSlicePointer> slices;
- clitk::ExtractSlices<MaskImageType>(Aorta, 2, slices);
- bool found=false;
- uint i = slices.size()-1;
- while (!found) {
- slices[i] = Labelize<MaskSliceType>(slices[i], 0, false, 10);
- std::vector<typename MaskSliceType::PointType> c;
- clitk::ComputeCentroids<MaskSliceType>(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<MaskImageType>("Aorta");
-
- // Put inside the AFDB
- this->GetAFDB()->SetPoint3D("InferiorBorderOfAorticArch", lower);
- this->GetAFDB()->SetDouble("InferiorBorderOfAorticArchZ", lower[2]);
- this->WriteAFDB();
- z = lower[2];
- }
- return z;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <MaskImageType>("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<MaskImageType>("BrachioCephalicArtery");
- MaskImagePointer BrachioCephalicVein = this->GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicVein");
- MaskImagePointer CommonCarotidArtery = this->GetAFDB()->template GetImage<MaskImageType>("CommonCarotidArtery");
- MaskImagePointer SubclavianArtery = this->GetAFDB()->template GetImage<MaskImageType>("SubclavianArtery");
- MaskImagePointer Thyroid = this->GetAFDB()->template GetImage<MaskImageType>("Thyroid");
- MaskImagePointer Aorta = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
- MaskImagePointer Trachea = this->GetAFDB()->template GetImage<MaskImageType>("Trachea");
-
- // Create a temporay support
- // From first slice of BrachioCephalicVein to end of 3A
- MaskImagePointer support = this->GetAFDB()->template GetImage<MaskImageType>("Support_Sup_Carina");
- MaskImagePointType p;
- p[0] = p[1] = p[2] = 0.0; // to avoid warning
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(BrachioCephalicVein, GetBackgroundValue(), 2, true, p);
- double inf = p [2];
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(this->GetAFDB()->template GetImage<MaskImageType>("Support_S3A"),
- GetBackgroundValue(), 2, false, p);
- double sup = p [2];
- support = clitk::CropImageAlongOneAxis<MaskImageType>(support, 2, inf, sup,
- false, GetBackgroundValue());
-
- // Resize all structures like support
- BrachioCephalicArtery =
- clitk::ResizeImageLike<MaskImageType>(BrachioCephalicArtery, support, GetBackgroundValue());
- CommonCarotidArtery =
- clitk::ResizeImageLike<MaskImageType>(CommonCarotidArtery, support, GetBackgroundValue());
- SubclavianArtery =
- clitk::ResizeImageLike<MaskImageType>(SubclavianArtery, support, GetBackgroundValue());
- Thyroid =
- clitk::ResizeImageLike<MaskImageType>(Thyroid, support, GetBackgroundValue());
- Aorta =
- clitk::ResizeImageLike<MaskImageType>(Aorta, support, GetBackgroundValue());
- BrachioCephalicVein =
- clitk::ResizeImageLike<MaskImageType>(BrachioCephalicVein, support, GetBackgroundValue());
- Trachea =
- clitk::ResizeImageLike<MaskImageType>(Trachea, support, GetBackgroundValue());
-
- // Extract slices
- std::vector<MaskSlicePointer> slices_BrachioCephalicArtery;
- clitk::ExtractSlices<MaskImageType>(BrachioCephalicArtery, 2, slices_BrachioCephalicArtery);
- std::vector<MaskSlicePointer> slices_BrachioCephalicVein;
- clitk::ExtractSlices<MaskImageType>(BrachioCephalicVein, 2, slices_BrachioCephalicVein);
- std::vector<MaskSlicePointer> slices_CommonCarotidArtery;
- clitk::ExtractSlices<MaskImageType>(CommonCarotidArtery, 2, slices_CommonCarotidArtery);
- std::vector<MaskSlicePointer> slices_SubclavianArtery;
- clitk::ExtractSlices<MaskImageType>(SubclavianArtery, 2, slices_SubclavianArtery);
- std::vector<MaskSlicePointer> slices_Thyroid;
- clitk::ExtractSlices<MaskImageType>(Thyroid, 2, slices_Thyroid);
- std::vector<MaskSlicePointer> slices_Aorta;
- clitk::ExtractSlices<MaskImageType>(Aorta, 2, slices_Aorta);
- std::vector<MaskSlicePointer> slices_Trachea;
- clitk::ExtractSlices<MaskImageType>(Trachea, 2, slices_Trachea);
- unsigned int n= slices_BrachioCephalicArtery.size();
-
- // Get the boundaries of one slice
- std::vector<MaskSlicePointType> bounds;
- ComputeImageBoundariesCoordinates<MaskSliceType>(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<MaskImagePointType> p3D;
-
- vtkSmartPointer<vtkAppendPolyData> append = vtkSmartPointer<vtkAppendPolyData>::New();
- for(unsigned int i=0; i<n; i++) {
- // Labelize the slices
- slices_CommonCarotidArtery[i] = Labelize<MaskSliceType>(slices_CommonCarotidArtery[i],
- GetBackgroundValue(), true, 1);
- slices_SubclavianArtery[i] = Labelize<MaskSliceType>(slices_SubclavianArtery[i],
- GetBackgroundValue(), true, 1);
- slices_BrachioCephalicArtery[i] = Labelize<MaskSliceType>(slices_BrachioCephalicArtery[i],
- GetBackgroundValue(), true, 1);
- slices_BrachioCephalicVein[i] = Labelize<MaskSliceType>(slices_BrachioCephalicVein[i],
- GetBackgroundValue(), true, 1);
- slices_Thyroid[i] = Labelize<MaskSliceType>(slices_Thyroid[i],
- GetBackgroundValue(), true, 1);
- slices_Aorta[i] = Labelize<MaskSliceType>(slices_Aorta[i],
- GetBackgroundValue(), true, 1);
-
- // Search centroids
- std::vector<MaskSlicePointType> points2D;
- std::vector<MaskSlicePointType> centroids1;
- std::vector<MaskSlicePointType> centroids2;
- std::vector<MaskSlicePointType> centroids3;
- std::vector<MaskSlicePointType> centroids4;
- std::vector<MaskSlicePointType> centroids5;
- std::vector<MaskSlicePointType> centroids6;
- ComputeCentroids<MaskSliceType>(slices_CommonCarotidArtery[i], GetBackgroundValue(), centroids1);
- ComputeCentroids<MaskSliceType>(slices_SubclavianArtery[i], GetBackgroundValue(), centroids2);
- ComputeCentroids<MaskSliceType>(slices_BrachioCephalicArtery[i], GetBackgroundValue(), centroids3);
- ComputeCentroids<MaskSliceType>(slices_Thyroid[i], GetBackgroundValue(), centroids4);
- ComputeCentroids<MaskSliceType>(slices_Aorta[i], GetBackgroundValue(), centroids5);
- ComputeCentroids<MaskSliceType>(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<centroids1.size(); j++) points2D.push_back(centroids1[j]);
- for(unsigned int j=1; j<centroids2.size(); j++) points2D.push_back(centroids2[j]);
- for(unsigned int j=1; j<centroids3.size(); j++) points2D.push_back(centroids3[j]);
- for(unsigned int j=1; j<centroids4.size(); j++) points2D.push_back(centroids4[j]);
- for(unsigned int j=1; j<centroids5.size(); j++) points2D.push_back(centroids5[j]);
- for(unsigned int j=1; j<centroids6.size(); j++) points2D.push_back(centroids6[j]);
-
- // Sort by angle according to trachea centroid and vertical line,
- // in polar coordinates :
- // http://en.wikipedia.org/wiki/Polar_coordinate_system
- std::vector<MaskSlicePointType> centroids_trachea;
- ComputeCentroids<MaskSliceType>(slices_Trachea[i], GetBackgroundValue(), centroids_trachea);
- typedef std::pair<MaskSlicePointType, double> PointAngleType;
- std::vector<PointAngleType> angles;
- for(unsigned int j=0; j<points2D.size(); j++) {
- //double r = centroids_trachea[1].EuclideanDistanceTo(points2D[j]);
- double x = (points2D[j][0]-centroids_trachea[1][0]); // X : Right to Left
- double y = (centroids_trachea[1][1]-points2D[j][1]); // Y : Post to Ant
- double angle = 0;
- if (x>0) 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<PointAngleType>());
- for(unsigned int j=0; j<angles.size(); j++) {
- points2D[j] = angles[j].first;
- }
- // DDV(points2D, points2D.size());
-
- /* When vessels are far away, we try to replace the line segment
- with a curved line that join the two vessels but stay
- approximately at the same distance from the trachea centroids
- than the vessels.
-
- For that:
- - let a and c be two successive vessels centroids
- - id distance(a,c) < threshold, next point
-
- TODO HERE
-
- - compute mid position between two successive points -
- compute dist to trachea centroid for the 3 pts - if middle too
- low, add one point
- */
- std::vector<MaskSlicePointType> toadd;
- unsigned int index = 0;
- double dmax = 5;
- while (index<points2D.size()-1) {
- MaskSlicePointType a = points2D[index];
- MaskSlicePointType c = points2D[index+1];
-
- double dac = a.EuclideanDistanceTo(c);
- if (dac>dmax) {
-
- 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<ImagePointType> points3D;
- clitk::PointsUtils<MaskImageType>::Convert2DListTo3DList(points2D, i, support, points3D);
- for(unsigned int x=0; x<points3D.size(); x++) p3D.push_back(points3D[x]);
-
- // Build the mesh from the contour's points
- vtkSmartPointer<vtkPolyData> mesh = Build3DMeshFrom2DContour(points3D);
- append->AddInput(mesh);
- }
-
- // DEBUG: write points3D
- clitk::WriteListOfLandmarks<MaskImageType>(p3D, "vessels-centroids.txt");
-
- // Build the final 3D mesh form the list 2D mesh
- append->Update();
- vtkSmartPointer<vtkPolyData> mesh = append->GetOutput();
-
- // Debug, write the mesh
- /*
- vtkSmartPointer<vtkPolyDataWriter> w = vtkSmartPointer<vtkPolyDataWriter>::New();
- w->SetInput(mesh);
- w->SetFileName("bidon.vtk");
- w->Write();
- */
-
- // Compute a single binary 3D image from the list of contours
- clitk::MeshToBinaryImageFilter<MaskImageType>::Pointer filter =
- clitk::MeshToBinaryImageFilter<MaskImageType>::New();
- filter->SetMesh(mesh);
- filter->SetLikeImage(support);
- filter->Update();
- binarizedContour = filter->GetOutput();
-
- // Crop
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(binarizedContour, GetForegroundValue(), 2, true, p);
- inf = p[2];
- DD(p);
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(binarizedContour, GetForegroundValue(), 2, false, p);
- sup = p[2];
- DD(p);
- binarizedContour = clitk::CropImageAlongOneAxis<MaskImageType>(binarizedContour, 2, inf, sup,
- false, GetBackgroundValue());
- // Update the AFDB
- writeImage<MaskImageType>(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<MaskImageType> 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<MaskImageType>(m_Working_Support);
- //m_ListOfStations["2R"] = m_Working_Support;
- //m_ListOfStations["2L"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
-clitk::ExtractLymphStationsFilter<ImageType>::
-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 <MaskImageType>("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<std::string, MaskImagePointer> MapOfStructures;
- typedef std::map<std::string, MaskImagePointer>::iterator MapIter;
- MapOfStructures["BrachioCephalicArtery"] = this->GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicArtery");
- MapOfStructures["BrachioCephalicVein"] = this->GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicVein");
- MapOfStructures["CommonCarotidArteryLeft"] = this->GetAFDB()->template GetImage<MaskImageType>("LeftCommonCarotidArtery");
- MapOfStructures["CommonCarotidArteryRight"] = this->GetAFDB()->template GetImage<MaskImageType>("RightCommonCarotidArtery");
- MapOfStructures["SubclavianArteryLeft"] = this->GetAFDB()->template GetImage<MaskImageType>("LeftSubclavianArtery");
- MapOfStructures["SubclavianArteryRight"] = this->GetAFDB()->template GetImage<MaskImageType>("RightSubclavianArtery");
- MapOfStructures["Thyroid"] = this->GetAFDB()->template GetImage<MaskImageType>("Thyroid");
- MapOfStructures["Aorta"] = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
- MapOfStructures["Trachea"] = this->GetAFDB()->template GetImage<MaskImageType>("Trachea");
-
- std::vector<std::string> ListOfStructuresNames;
-
- // Create a temporay support
- // From first slice of BrachioCephalicVein to end of 3A or end of 2RL
- MaskImagePointer support = this->GetAFDB()->template GetImage<MaskImageType>("Support_Sup_Carina");
- MaskImagePointType p;
- p[0] = p[1] = p[2] = 0.0; // to avoid warning
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(MapOfStructures["BrachioCephalicVein"],
- GetBackgroundValue(), 2, true, p);
- double inf = p[2];
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(this->GetAFDB()->template GetImage<MaskImageType>("Support_S3A"),
- GetBackgroundValue(), 2, false, p);
- MaskImagePointType p2;
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(this->GetAFDB()->template GetImage<MaskImageType>("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<MaskImageType>(support, 2, inf, sup,
- false, GetBackgroundValue());
-
- // Resize all structures like support
- for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) {
- it->second = clitk::ResizeImageLike<MaskImageType>(it->second, support, GetBackgroundValue());
- }
-
- // Extract slices
- typedef std::vector<MaskSlicePointer> SlicesType;
- std::map<std::string, SlicesType> MapOfSlices;
- for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) {
- SlicesType s;
- clitk::ExtractSlices<MaskImageType>(it->second, 2, s);
- MapOfSlices[it->first] = s;
- }
-
- unsigned int n= MapOfSlices["Trachea"].size();
-
- // Get the boundaries of one slice
- std::vector<MaskSlicePointType> bounds;
- ComputeImageBoundariesCoordinates<MaskSliceType>(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<MaskImagePointType> p3D;
- vtkSmartPointer<vtkAppendPolyData> append = vtkSmartPointer<vtkAppendPolyData>::New();
- for(unsigned int i=0; i<n; i++) {
-
- // Labelize the slices
- for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) {
- MaskSlicePointer & s = MapOfSlices[it->first][i];
- s = clitk::Labelize<MaskSliceType>(s, GetBackgroundValue(), true, 1);
- }
-
- // Search centroids
- std::vector<MaskSlicePointType> points2D;
- typedef std::vector<MaskSlicePointType> CentroidsType;
- std::map<std::string, CentroidsType> MapOfCentroids;
- for (MapIter it = MapOfStructures.begin(); it != MapOfStructures.end(); ++it) {
- std::string structure = it->first;
- MaskSlicePointer & s = MapOfSlices[structure][i];
- CentroidsType c;
- clitk::ComputeCentroids<MaskSliceType>(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<c.size(); j++) points2D.push_back(c[j]);
- }
- }
-
- // Sort by angle according to trachea centroid and vertical line,
- // in polar coordinates :
- // http://en.wikipedia.org/wiki/Polar_coordinate_system
- // std::vector<MaskSlicePointType> centroids_trachea;
- //ComputeCentroids<MaskSliceType>(MapOfSlices["Trachea"][i], GetBackgroundValue(), centroids_trachea);
- CentroidsType centroids_trachea = MapOfCentroids["Trachea"];
- typedef std::pair<MaskSlicePointType, double> PointAngleType;
- std::vector<PointAngleType> angles;
- for(unsigned int j=0; j<points2D.size(); j++) {
- //double r = centroids_trachea[1].EuclideanDistanceTo(points2D[j]);
- double x = (points2D[j][0]-centroids_trachea[1][0]); // X : Right to Left
- double y = (centroids_trachea[1][1]-points2D[j][1]); // Y : Post to Ant
- double angle = 0;
- if (x>0) 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<PointAngleType>());
- for(unsigned int j=0; j<angles.size(); j++) {
- points2D[j] = angles[j].first;
- }
- // DDV(points2D, points2D.size());
-
- /* When vessels are far away, we try to replace the line segment
- with a curved line that join the two vessels but stay
- approximately at the same distance from the trachea centroids
- than the vessels.
-
- For that:
- - let a and c be two successive vessels centroids
- - id distance(a,c) < threshold, next point
-
- TODO HERE
-
- - compute mid position between two successive points -
- compute dist to trachea centroid for the 3 pts - if middle too
- low, add one point
- */
- std::vector<MaskSlicePointType> toadd;
- unsigned int index = 0;
- double dmax = 5;
- while (index<points2D.size()-1) {
- MaskSlicePointType a = points2D[index];
- MaskSlicePointType c = points2D[index+1];
-
- double dac = a.EuclideanDistanceTo(c);
- if (dac>dmax) {
-
- 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<ImagePointType> points3D;
- clitk::PointsUtils<MaskImageType>::Convert2DListTo3DList(points2D, i, support, points3D);
- for(unsigned int x=0; x<points3D.size(); x++) p3D.push_back(points3D[x]);
-
- // Build the mesh from the contour's points
- vtkSmartPointer<vtkPolyData> mesh = Build3DMeshFrom2DContour(points3D);
- append->AddInput(mesh);
- // if (i ==n-1) { // last slice
- // clitk::PointsUtils<MaskImageType>::Convert2DListTo3DList(points2D, i+1, support, points3D);
- // vtkSmartPointer<vtkPolyData> mesh = Build3DMeshFrom2DContour(points3D);
- // append->AddInput(mesh);
- // }
- }
-
- // DEBUG: write points3D
- clitk::WriteListOfLandmarks<MaskImageType>(p3D, "vessels-centroids.txt");
-
- // Build the final 3D mesh form the list 2D mesh
- append->Update();
- vtkSmartPointer<vtkPolyData> mesh = append->GetOutput();
-
- // Debug, write the mesh
- /*
- vtkSmartPointer<vtkPolyDataWriter> w = vtkSmartPointer<vtkPolyDataWriter>::New();
- w->SetInput(mesh);
- w->SetFileName("bidon.vtk");
- w->Write();
- */
-
- // Compute a single binary 3D image from the list of contours
- clitk::MeshToBinaryImageFilter<MaskImageType>::Pointer filter =
- clitk::MeshToBinaryImageFilter<MaskImageType>::New();
- filter->SetMesh(mesh);
- filter->SetLikeImage(support);
- filter->Update();
- binarizedContour = filter->GetOutput();
-
- // Crop
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(binarizedContour,
- GetForegroundValue(), 2, true, p);
- inf = p[2];
- clitk::FindExtremaPointInAGivenDirection<MaskImageType>(binarizedContour,
- GetForegroundValue(), 2, false, p);
- sup = p[2]+binarizedContour->GetSpacing()[2]; // extend to include the last slice
- binarizedContour = clitk::CropImageAlongOneAxis<MaskImageType>(binarizedContour, 2, inf, sup,
- false, GetBackgroundValue());
-
- // Update the AFDB
- writeImage<MaskImageType>(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<MaskImageType> 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<MaskImageType>(m_Working_Support);
- //m_ListOfStations["2R"] = m_Working_Support;
- //m_ListOfStations["2L"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-WriteImageSupport(std::string support)
-{
- writeImage<MaskImageType>(m_ListOfSupports[support], this->GetAFDBPath()+"/"+"seg/Support_"+support+".mha");
- this->GetAFDB()->SetImageFilename("Support_"+support, "seg/Support_"+support+".mha");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-WriteImageStation(std::string station)
-{
- writeImage<MaskImageType>(m_ListOfStations[station], GetAFDB()->GetPath()+"/seg/Station"+station+".mha");
- GetAFDB()->SetImageFilename("Station"+station, "seg/Station"+station+".mha");
- WriteAFDB();
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-ComputeOverlapWithRef(std::string station)
-{
- if (GetComputeStation(station)) {
- MaskImagePointer ref = this->GetAFDB()->template GetImage <MaskImageType>("Station"+station+"_Ref");
- typedef clitk::LabelImageOverlapMeasureFilter<MaskImageType> FilterType;
- typename FilterType::Pointer filter = FilterType::New();
- filter->SetInput(0, m_ListOfStations[station]);
- filter->SetInput(1, ref);
- filter->Update();
- }
-}
-//--------------------------------------------------------------------
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-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
-
+++ /dev/null
-/*=========================================================================
- 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 ArgsInfoType>
- class ITK_EXPORT ExtractLymphStationsGenericFilter:
- public ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> >
- {
-
- public:
- //--------------------------------------------------------------------
- ExtractLymphStationsGenericFilter();
-
- //--------------------------------------------------------------------
- typedef ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> > Superclass;
- typedef ExtractLymphStationsGenericFilter Self;
- typedef itk::SmartPointer<Self> Pointer;
- typedef itk::SmartPointer<const Self> ConstPointer;
-
- //--------------------------------------------------------------------
- itkNewMacro(Self);
- itkTypeMacro(ExtractLymphStationsGenericFilter, LightObject);
-
- //--------------------------------------------------------------------
- // Options for the GenericFilter
- void SetArgsInfo(const ArgsInfoType & a);
-
- //--------------------------------------------------------------------
- // Options for the Filter
- template<class FilterType>
- void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
-
- //--------------------------------------------------------------------
- // Main function called each time the filter is updated
- template<class ImageType>
- void UpdateWithInputImageType();
-
- protected:
- template<unsigned int Dim> 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
+++ /dev/null
-/*=========================================================================
- 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<class ArgsInfoType>
-clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::ExtractLymphStationsGenericFilter():
- ImageToImageGenericFilter<Self>("ExtractLymphStations")
-{
- // Default values
- cmdline_parser_clitkExtractLymphStations_init(&mArgsInfo);
- InitializeImageType<3>(); // Only for 3D images
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template<class ArgsInfoType>
-template<unsigned int Dim>
-void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::InitializeImageType()
-{
- ADD_IMAGE_TYPE(Dim, short); // Can add float later
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template<class ArgsInfoType>
-void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::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<class ArgsInfoType>
-template<class FilterType>
-void
-clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::
-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; i<mArgsInfo.station_given; i++)
- f->AddComputeStation(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; i<mArgsInfo.relpos_given; i++)
- f->AddRelativePositionListFilename(mArgsInfo.relpos_arg[i]);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-// Update with the number of dimensions and the pixeltype
-//--------------------------------------------------------------------
-template<class ArgsInfoType>
-template<class ImageType>
-void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
-{
- // Reading input
- typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
-
- // Create filter
- typedef clitk::ExtractLymphStationsFilter<ImageType> FilterType;
- typename FilterType::Pointer filter = FilterType::New();
-
- // Set global Options
- filter->SetInput(input);
- SetOptionsFromArgsInfoToFilter<FilterType>(filter);
-
- // Go !
- filter->Update();
-
- // Write/Save results
- typedef uchar MaskImagePixelType;
- typedef itk::Image<MaskImagePixelType, 3> OutputImageType;
- typename OutputImageType::Pointer output = filter->GetOutput();
- this->template SetNextOutput<OutputImageType>(output);
-}
-//--------------------------------------------------------------------
-
-#endif //#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX