+
+//--------------------------------------------------------------------
+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);
+}
+//--------------------------------------------------------------------
+
+
//--------------------------------------------------------------------
template <class TImageType>
void
clitk::ExtractLymphStationsFilter<TImageType>::
ExtractStation_7_SI_Limits()
{
- // Local variables
- double m_CarinaZPositionInMM;
- double m_MiddleLobeBronchusZPositionInMM;
-
+ StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLLBronchus");
// Get Inputs
- m_Trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");
- m_CarinaZPositionInMM = GetAFDB()->GetPoint3D("carina", 2);
- DD(m_CarinaZPositionInMM);
- m_MiddleLobeBronchusZPositionInMM = GetAFDB()->GetPoint3D("rightMiddleLobeBronchus", 2);
- DD(m_MiddleLobeBronchusZPositionInMM);
-
- /* Crop support :
- Superior limit = carina
- Inferior limit = origin right middle lobe bronchus */
- StartNewStep("Inf/Sup mediastinum limits with carina/bronchus");
+ MaskImagePointer Trachea = GetAFDB()->template GetImage <MaskImageType>("Trachea");
+
+ // We suppoe that CarinaZ was already computed (S8)
+ double m_CarinaZ = GetAFDB()->GetDouble("CarinaZ");
+
+ // double m_OriginOfRightMiddleLobeBronchusZ = GetAFDB()->GetPoint3D("OriginOfRightMiddleLobeBronchus", 2);
+ // DD(m_OriginOfRightMiddleLobeBronchusZ);
+ MaskImagePointer UpperBorderOfLLLBronchus = GetAFDB()->template GetImage<MaskImageType>("UpperBorderOfLLLBronchus");
+
+ // Search most inf point (WHY ? IS IT THE RIGHT STRUCTURE ??)
+ MaskImagePointType ps = UpperBorderOfLLLBronchus->GetOrigin(); // initialise to avoid warning
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(UpperBorderOfLLLBronchus, GetBackgroundValue(), 2, true, ps);
+ double m_UpperBorderOfLLLBronchusZ = ps[2];
+
+ /*
+ std::vector<MaskImagePointType> centroids;
+ clitk::ComputeCentroids<MaskImageType>(UpperBorderOfLLLBronchus, GetBackgroundValue(), centroids);
+ double m_UpperBorderOfLLLBronchusZ = centroids[1][2];
+ DD(m_UpperBorderOfLLLBronchusZ)
+ */
+
+ /* Crop support */
m_Working_Support =
- clitk::CropImageAlongOneAxis<MaskImageType>(m_Support, 2,
- m_MiddleLobeBronchusZPositionInMM,
- m_CarinaZPositionInMM, true,
+ clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2,
+ m_UpperBorderOfLLLBronchusZ,
+ m_CarinaZ, true,
GetBackgroundValue());
- StopCurrentStep<MaskImageType>(m_Working_Support);
-
- /* Crop trachea
- Superior limit = carina
- Inferior limit = origin right middle lobe bronchus*/
- StartNewStep("Inf/Sup trachea limits with carina/bronchus");
- m_working_trachea =
- clitk::CropImageAlongOneAxis<MaskImageType>(m_Trachea, 2,
- m_MiddleLobeBronchusZPositionInMM,
- m_CarinaZPositionInMM, true,
+ /* Crop trachea */
+ m_Working_Trachea =
+ clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2,
+ m_UpperBorderOfLLLBronchusZ,
+ m_CarinaZ, true,
GetBackgroundValue());
- StopCurrentStep<MaskImageType>(m_working_trachea);
- m_Station7 = m_Working_Support;
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["7"] = m_Working_Support;
}
//--------------------------------------------------------------------
+
//--------------------------------------------------------------------
template <class TImageType>
void
ExtractStation_7_RL_Limits()
{
// ----------------------------------------------------------------
- // Separate trachea in two CCL
- StartNewStep("Separate trachea under carina");
-
- // Labelize and consider two main labels
- m_working_trachea = Labelize<MaskImageType>(m_working_trachea, 0, true, 1);
-
- // Carina position must at the first slice that separate the two main bronchus (not superiorly)
- // Check that upper slice is composed of at least two labels
- typedef itk::ImageSliceIteratorWithIndex<MaskImageType> SliceIteratorType;
- SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
- iter.SetFirstDirection(0);
- iter.SetSecondDirection(1);
- iter.GoToReverseBegin(); // Start from the end (because image is IS not SI)
- int maxLabel=0;
- while (!iter.IsAtReverseEndOfSlice()) {
- while (!iter.IsAtReverseEndOfLine()) {
- // DD(iter.GetIndex());
- if (iter.Get() > maxLabel) maxLabel = iter.Get();
- --iter;
- }
- iter.PreviousLine();
+ 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);
+
+ // 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
}
- if (maxLabel < 2) {
- clitkExceptionMacro("First slice form Carina does not seems to seperate the two main bronchus. Abort");
+
+ 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);
- // Compute centroid of both parts to identify the left from the right bronchus
- typedef long LabelType;
- static const unsigned int Dim = ImageType::ImageDimension;
- typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType;
- typedef itk::LabelMap< LabelObjectType > LabelMapType;
- typedef itk::LabelImageToLabelMapFilter<MaskImageType, LabelMapType> ImageToMapFilterType;
- typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New();
- typedef itk::ShapeLabelMapFilter<LabelMapType, MaskImageType> ShapeFilterType;
- typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New();
- imageToLabelFilter->SetBackgroundValue(GetBackgroundValue());
- imageToLabelFilter->SetInput(m_working_trachea);
- statFilter->SetInput(imageToLabelFilter->GetOutput());
- statFilter->Update();
- typename LabelMapType::Pointer labelMap = statFilter->GetOutput();
-
- ImagePointType C1 = labelMap->GetLabelObject(1)->GetCentroid();
- ImagePointType C2 = labelMap->GetLabelObject(2)->GetCentroid();
-
- ImagePixelType leftLabel;
- ImagePixelType rightLabel;
- if (C1[0] < C2[0]) { leftLabel = 1; rightLabel = 2; }
- else { leftLabel = 2; rightLabel = 1; }
- DD(leftLabel);
- DD(rightLabel);
-
- StopCurrentStep<MaskImageType>(m_working_trachea);
-
- //-----------------------------------------------------
- StartNewStep("Left limits with bronchus (slice by slice)");
- // Select LeftLabel (set one label to Backgroundvalue)
- m_LeftBronchus =
- SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea,
- rightLabel, GetBackgroundValue());
- m_RightBronchus =
- SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea,
- leftLabel, GetBackgroundValue());
- writeImage<MaskImageType>(m_LeftBronchus, "left.mhd");
- writeImage<MaskImageType>(m_RightBronchus, "right.mhd");
+ 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(), "RightTo",
- true, 4);
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support,
- m_RightBronchus,
- 2, GetFuzzyThreshold(), "LeftTo",
- true, 4);
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support,
- m_LeftBronchus,
- 2, GetFuzzyThreshold(), "AntTo",
- true, 4, true); // NOT
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support,
- m_RightBronchus,
- 2, GetFuzzyThreshold(), "AntTo",
- true, 4, true);
- m_Working_Support =
- clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support,
- m_LeftBronchus,
- 2, GetFuzzyThreshold(), "PostTo",
- true, 4, true);
+ 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(), "PostTo",
- true, 4, true);
- m_Station7 = m_Working_Support;
- StopCurrentStep<MaskImageType>(m_Station7);
+ 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->SetUniqueConnectedComponentBySlice(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->SetUniqueConnectedComponentBySlice(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->SetUniqueConnectedComponentBySlice(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->SetUniqueConnectedComponentBySlice(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->SetUniqueConnectedComponentBySlice(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;
}
//--------------------------------------------------------------------
clitk::ExtractLymphStationsFilter<TImageType>::
ExtractStation_7_Posterior_Limits()
{
- StartNewStep("Posterior limits");
-
- // Left Bronchus slices
- typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
- typedef typename ExtractSliceFilterType::SliceType SliceType;
- typename ExtractSliceFilterType::Pointer
- extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(m_LeftBronchus);
- extractSliceFilter->SetDirection(2);
- extractSliceFilter->Update();
- std::vector<typename SliceType::Pointer> leftBronchusSlices;
- extractSliceFilter->GetOutputSlices(leftBronchusSlices);
-
- // Right Bronchus slices
- extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(m_RightBronchus);
- extractSliceFilter->SetDirection(2);
- extractSliceFilter->Update();
- std::vector<typename SliceType::Pointer> rightBronchusSlices ;
- extractSliceFilter->GetOutputSlices(rightBronchusSlices);
-
- assert(leftBronchusSlices.size() == rightBronchusSlices.size());
+ 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);
+ */
- std::vector<MaskImageType::PointType> leftPoints;
- std::vector<MaskImageType::PointType> rightPoints;
- for(uint i=0; i<leftBronchusSlices.size(); i++) {
- // Keep main CCL
- leftBronchusSlices[i] = Labelize<SliceType>(leftBronchusSlices[i], 0, true, 10);
- leftBronchusSlices[i] = KeepLabels<SliceType>(leftBronchusSlices[i],
- GetBackgroundValue(),
- GetForegroundValue(), 1, 1, true);
- rightBronchusSlices[i] = Labelize<SliceType>(rightBronchusSlices[i], 0, true, 10);
- rightBronchusSlices[i] = KeepLabels<SliceType>(rightBronchusSlices[i],
- GetBackgroundValue(),
- GetForegroundValue(), 1, 1, true);
- double distance_max_from_center_point = 15;
-
- // ------- Find point in left Bronchus -------
- // find right most point in left = rightMost
- SliceType::PointType a;
- SliceType::PointType rightMost =
- clitk::FindExtremaPointInAGivenDirection<SliceType>(leftBronchusSlices[i],
- GetBackgroundValue(),
- 0, false, a, 0);
- // find post most point in left, not far away from rightMost
- SliceType::PointType p =
- clitk::FindExtremaPointInAGivenDirection<SliceType>(leftBronchusSlices[i],
- GetBackgroundValue(),
- 1, false, rightMost,
- distance_max_from_center_point);
- MaskImageType::PointType pp;
- pp[0] = p[0]; pp[1] = p[1];
- pp[2] = i*m_LeftBronchus->GetSpacing()[2] + m_LeftBronchus->GetOrigin()[2];
- leftPoints.push_back(pp);
-
- // ------- Find point in right Bronchus -------
- // find left most point in right = leftMost
- SliceType::PointType leftMost =
- clitk::FindExtremaPointInAGivenDirection<SliceType>(rightBronchusSlices[i],
- GetBackgroundValue(),
- 0, true, a, 0);
- // find post most point in left, not far away from leftMost
- p = clitk::FindExtremaPointInAGivenDirection<SliceType>(rightBronchusSlices[i],
- GetBackgroundValue(),
- 1, false, leftMost,
- distance_max_from_center_point);
- pp[0] = p[0]; pp[1] = p[1];
- pp[2] = i*m_RightBronchus->GetSpacing()[2] + m_RightBronchus->GetOrigin()[2];
- rightPoints.push_back(pp);
- }
+ // 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 osl;
- openFileForWriting(osl, "left.txt");
- osl << "LANDMARKS1" << std::endl;
- std::ofstream osr;
- openFileForWriting(osr, "right.txt");
- osr << "LANDMARKS1" << std::endl;
- for(uint i=0; i<leftBronchusSlices.size(); i++) {
- osl << i << " " << leftPoints[i][0] << " " << leftPoints[i][1]
- << " " << leftPoints[i][2] << " 0 0 " << std::endl;
- osr << i << " " << rightPoints[i][0] << " " << rightPoints[i][1]
- << " " << rightPoints[i][2] << " 0 0 " << std::endl;
+ 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;
}
- osl.close();
- osr.close();
- // Now uses these points to limit, slice by slice
- // http://www.gamedev.net/community/forums/topic.asp?topic_id=542870
- /*
- Assuming the points are (Ax,Ay) (Bx,By) and (Cx,Cy), you need to compute:
- (Bx - Ax) * (Cy - Ay) - (By - Ay) * (Cx - Ax)
- This will equal zero if the point C is on the line formed by
- points A and B, and will have a different sign depending on the
- side. Which side this is depends on the orientation of your (x,y)
- coordinates, but you can plug test values for A,B and C into this
- formula to determine whether negative values are to the left or to
- the right.
- => to accelerate, start with formula, when change sign -> stop and fill
- */
- typedef itk::ImageSliceIteratorWithIndex<MaskImageType> SliceIteratorType;
- SliceIteratorType iter = SliceIteratorType(m_Working_Support,
- m_Working_Support->GetLargestPossibleRegion());
- iter.SetFirstDirection(0);
- iter.SetSecondDirection(1);
- iter.GoToBegin();
- int i=0;
- MaskImageType::PointType A;
- MaskImageType::PointType B;
- MaskImageType::PointType C;
- while (!iter.IsAtEnd()) {
- A = leftPoints[i];
- B = rightPoints[i];
- C = A;
- C[1] -= 10; // I know I must keep this point
- double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
- bool isPositive = s<0;
- while (!iter.IsAtEndOfSlice()) {
- while (!iter.IsAtEndOfLine()) {
- // Very slow, I know ... but image should be very small
- m_Working_Support->TransformIndexToPhysicalPoint(iter.GetIndex(), C);
- double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
- if (s == 0) iter.Set(2);
- if (isPositive) {
- if (s > 0) iter.Set(GetBackgroundValue());
- }
- else {
- if (s < 0) iter.Set(GetBackgroundValue());
- }
- ++iter;
- }
- iter.NextLine();
- }
- iter.NextSlice();
- ++i;
+ 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();
- //-----------------------------------------------------
- // StartNewStep("Anterior limits");
-
+ clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
+ m_PostMostInRightBronchus,
+ m_PostMostInLeftBronchus,
+ GetBackgroundValue(), 1, -10);
+ // If needed -> can do the same with AntMost.
- // MISSING FROM NOW
-
- // Station 4R, Station 4L, the right pulmonary artery, and/or the
- // left superior pulmonary vein
+ // End
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["7"] = m_Working_Support;
+}
+//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStation_7_Remove_Structures()
+{
- //-----------------------------------------------------
- //-----------------------------------------------------
- // ALSO SUBSTRACT ARTERY/VEIN (initially in the support)
+ //--------------------------------------------------------------------
+ StartNewStep("[Station7] remove some structures");
+ Remove_Structures("7", "AzygousVein");
+ Remove_Structures("7", "Aorta");
+ Remove_Structures("7", "Esophagus");
+ Remove_Structures("7", "RightPulmonaryArtery");
+ Remove_Structures("7", "LeftPulmonaryArtery");
+ Remove_Structures("7", "LeftSuperiorPulmonaryVein");
+ Remove_Structures("7", "PulmonaryTrunk");
+ Remove_Structures("7", "VertebralBody");
- // Set output
- m_Station7 = m_Working_Support;
+ // END
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["7"] = m_Working_Support;
+ return;
}
//--------------------------------------------------------------------
+
+
+