//-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_SetDefaultValues() { SetFuzzyThreshold("7", "Bronchi", 0.1); SetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein", 0.3); SetFuzzyThreshold("7", "RightSuperiorPulmonaryVein", 0.2); SetFuzzyThreshold("7", "RightPulmonaryArtery", 0.3); SetFuzzyThreshold("7", "LeftPulmonaryArtery", 0.5); SetFuzzyThreshold("7", "SVC", 0.2); SetS7_UseMostInferiorPartOnlyFlag(false); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7() { if (CheckForStation("7")) { ExtractStation_7_SI_Limits(); ExtractStation_7_RL_Interior_Limits(); // ExtractStation_7_Posterior_Limits(); ExtractStation_8_Single_CCL_Limits(); ExtractStation_7_Remove_Structures(); // Store image filenames into AFDB writeImage(m_ListOfStations["7"], "seg/Station7.mhd"); GetAFDB()->SetImageFilename("Station7", "seg/Station7.mhd"); WriteAFDB(); } } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_SI_Limits() { StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLL-RMLBronchus"); // Get Inputs MaskImagePointer Trachea = GetAFDB()->template GetImage ("Trachea"); // Create line from A to B with // A = upper border of LLL at left // B = lower border of bronchus intermedius (BI) or RightMiddleLobeBronchus ImagePointType A; ImagePointType B; FindLineForS7S8Separation(A, B); // // if option -> replace A[0] with B[0] // if (GetS7_UseMostInferiorPartOnlyFlag()) { // A[0] = B[0]; // } // Use line to remove the inferior part m_Working_Support = SliceBySliceSetBackgroundFromSingleLine(m_Working_Support, GetBackgroundValue(), A, B, 2, 0, false); // Get the CarinaZ position double m_CarinaZ = FindCarina(); // Crop support m_Working_Support = clitk::CropImageAlongOneAxis(m_Working_Support, 2, A[2], m_CarinaZ, true, GetBackgroundValue()); // Crop trachea m_Working_Trachea = clitk::CropImageAlongOneAxis(Trachea, 2, A[2], m_CarinaZ, true, GetBackgroundValue()); StopCurrentStep(m_Working_Support); m_ListOfStations["7"] = m_Working_Support; } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_RL_Interior_Limits() { // ---------------------------------------------------------------- StartNewStep("[Station7] RL limits with bronchi"); /* Slice by Slice, consider most Left point of the Right bronchus. Remove the Ant/Right corner */ // First consider bronchi FindLeftAndRightBronchi(); m_RightBronchus = GetAFDB()->template GetImage ("RightBronchus"); m_LeftBronchus = GetAFDB()->template GetImage ("LeftBronchus"); // Resize like m_Working_Support m_LeftBronchus = clitk::ResizeImageLike(m_LeftBronchus, m_Working_Support, GetBackgroundValue()); m_RightBronchus = clitk::ResizeImageLike(m_RightBronchus, m_Working_Support, GetBackgroundValue()); // Extract slices, Label, compute centroid, keep most central connected component std::vector slices_leftbronchus; std::vector slices_rightbronchus; std::vector slices_support; clitk::ExtractSlices(m_LeftBronchus, 2, slices_leftbronchus); clitk::ExtractSlices(m_RightBronchus, 2, slices_rightbronchus); clitk::ExtractSlices(m_Working_Support, 2, slices_support); // Keep only the CCL of the bronchus with the closest to the center // Loop on slices for left bronchus for(uint i=0; i(slices_leftbronchus[i], 0, false, 10); std::vector c; clitk::ComputeCentroids(slices_leftbronchus[i], GetBackgroundValue(), c); if (c.size() > 1) { double most_at_left = c[1][0]; int most_at_left_index=1; for(uint j=1; j(slices_leftbronchus[i], most_at_left_index, most_at_left_index, GetBackgroundValue(), GetForegroundValue()); } // end c.size } // Loop on slices for right bronchus for(uint i=0; i(slices_rightbronchus[i], 0, false, 10); std::vector c; clitk::ComputeCentroids(slices_rightbronchus[i], GetBackgroundValue(), c); if (c.size() > 1) { double most_at_right = c[1][0]; int most_at_right_index=1; for(uint j=1; j most_at_right) { most_at_right = c[j][0]; most_at_right_index = j; } } // Put all other CCL to Background slices_rightbronchus[i] = clitk::Binarize(slices_rightbronchus[i], most_at_right_index, most_at_right_index, GetBackgroundValue(), GetForegroundValue()); } // end c.size } // Joint slices m_LeftBronchus = clitk::JoinSlices(slices_leftbronchus, m_LeftBronchus, 2); m_RightBronchus = clitk::JoinSlices(slices_rightbronchus, m_RightBronchus, 2); // For Right bronchus, Find most Left point. Remove corner Ant/Right corner for(uint i=0; i(slices_rightbronchus[i], GetBackgroundValue(), 0, false, p_left); if (b) { b = clitk::FindExtremaPointInAGivenDirection(slices_rightbronchus[i], GetBackgroundValue(), 1, false, p_post); } if (b) { MaskSlicePointType p = p_left; p[1] = p_post[1]; MaskSliceIndexType pi; slices_rightbronchus[i]->TransformPhysicalPointToIndex(p, pi); // Build region to remove MaskSliceRegionType region = slices_rightbronchus[i]->GetLargestPossibleRegion(); MaskSliceIndexType index = region.GetIndex(); MaskSliceSizeType size = region.GetSize(); size[0] = pi[0] - index[0]; size[1] = pi[1] - index[1]; region.SetSize(size); // Fill region with Background value clitk::FillRegionWithValue(slices_support[i], GetBackgroundValue(), region); } } // For Left bronchus, Find most Right point. Remove corner Ant/Left corner for(uint i=0; i(slices_leftbronchus[i], GetBackgroundValue(), 0, true, p_right); if (b) { b = clitk::FindExtremaPointInAGivenDirection(slices_rightbronchus[i], GetBackgroundValue(), 1, false, p_post); } if (b) { MaskSlicePointType p = p_right; p[1] = p_post[1]; MaskSliceIndexType pi; slices_leftbronchus[i]->TransformPhysicalPointToIndex(p, pi); /* typedef itk::ImageRegionIterator IteratorType; IteratorType iter(input, region); iter.GoToBegin(); while (!iter.IsAtEnd()) { MaskSliceIndexType index = iter.GetIndex(); if (index[0] > pi[0]) && (index[1] > pi[1]) iter.Set(GetBackgroundValue()); ++iter; } */ // Build region to remove MaskSliceRegionType region = slices_leftbronchus[i]->GetLargestPossibleRegion(); MaskSliceIndexType index = region.GetIndex(); MaskSliceSizeType size = region.GetSize(); index[0] = pi[0]; size[0] = slices_leftbronchus[i]->GetLargestPossibleRegion().GetSize()[0] - pi[0]; size[1] = pi[1] - index[1]; region.SetSize(size); region.SetIndex(index); // Fill region with Background value clitk::FillRegionWithValue(slices_support[i], GetBackgroundValue(), region); } } m_Working_Support = clitk::JoinSlices(slices_support, m_Working_Support, 2); // Also remove what is at right of the Right bronchus (left respectively) m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, GetFuzzyThreshold("7", "Bronchi"), "NotLeftTo", false, 3, false); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, GetFuzzyThreshold("7", "Bronchi"), "NotRightTo", false, 3, false); // SECOND PART StopCurrentStep(m_Working_Support); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_RL_Limits_OLD() { // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with bronchus : RightTo the left bronchus"); // First consider bronchus and keep the main CCL by slice m_RightBronchus = GetAFDB()->template GetImage ("RightBronchus"); m_LeftBronchus = GetAFDB()->template GetImage ("LeftBronchus"); // Extract slices, Label, compute centroid, keep most central connected component std::vector slices_leftbronchus; std::vector slices_rightbronchus; clitk::ExtractSlices(m_LeftBronchus, 2, slices_leftbronchus); clitk::ExtractSlices(m_RightBronchus, 2, slices_rightbronchus); // Version #1 with limit = centroid of the bronchus (OUTDATED) // Step1 = keep only the CCL of the bronchus with the closest to the center // Step2 = SliceBySlice Rel pos to both bronchi // Loop on slices for(uint i=0; i(slices_leftbronchus[i], 0, false, 10); std::vector c; clitk::ComputeCentroids(slices_leftbronchus[i], GetBackgroundValue(), c); if (c.size() > 1) { double most_at_left = c[1][0]; int most_at_left_index=1; for(uint j=1; j(slices_leftbronchus[i], most_at_left_index, most_at_left_index, GetBackgroundValue(), GetForegroundValue()); } // end c.size } for(uint i=0; i(slices_rightbronchus[i], 0, false, 10); std::vector c; clitk::ComputeCentroids(slices_rightbronchus[i], GetBackgroundValue(), c); if (c.size() > 1) { double most_at_right = c[1][0]; int most_at_right_index=1; for(uint j=1; j most_at_right) { most_at_right = c[j][0]; most_at_right_index = j; } } // Put all other CCL to Background slices_rightbronchus[i] = clitk::Binarize(slices_rightbronchus[i], most_at_right_index, most_at_right_index, GetBackgroundValue(), GetForegroundValue()); } // end c.size } // Joint slices m_LeftBronchus = clitk::JoinSlices(slices_leftbronchus, m_LeftBronchus, 2); m_RightBronchus = clitk::JoinSlices(slices_rightbronchus, m_RightBronchus, 2); writeImage(m_LeftBronchus, "step-left.mhd"); writeImage(m_RightBronchus, "step-right.mhd"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, GetFuzzyThreshold("7", "Bronchi"), "RightTo", false, 3, false); StopCurrentStep(m_Working_Support); // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with bronchus : LeftTo the right bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, GetFuzzyThreshold("7", "Bronchi"), "LeftTo", false, 3, false); StopCurrentStep(m_Working_Support); // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with LeftSuperiorPulmonaryVein"); try { MaskImagePointer LeftSuperiorPulmonaryVein = GetAFDB()->template GetImage("LeftSuperiorPulmonaryVein"); typedef SliceBySliceRelativePositionFilter SliceRelPosFilterType; typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(LeftSuperiorPulmonaryVein); sliceRelPosFilter->SetDirection(2); sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein")); sliceRelPosFilter->AddOrientationTypeString("NotLeftTo"); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); m_Working_Support = sliceRelPosFilter->GetOutput(); StopCurrentStep(m_Working_Support); } catch (clitk::ExceptionObject e) { std::cout << "Not LeftSuperiorPulmonaryVein, skip" << std::endl; } // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with RightSuperiorPulmonaryVein"); try { MaskImagePointer RightSuperiorPulmonaryVein = GetAFDB()->template GetImage("RightSuperiorPulmonaryVein"); typedef SliceBySliceRelativePositionFilter SliceRelPosFilterType; typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(RightSuperiorPulmonaryVein); sliceRelPosFilter->SetDirection(2); sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "RightSuperiorPulmonaryVein")); sliceRelPosFilter->AddOrientationTypeString("NotRightTo"); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->AddOrientationTypeString("NotPostTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); m_Working_Support = sliceRelPosFilter->GetOutput(); StopCurrentStep(m_Working_Support); } catch (clitk::ExceptionObject e) { std::cout << "Not RightSuperiorPulmonaryVein, skip" << std::endl; } // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with RightPulmonaryArtery"); MaskImagePointer RightPulmonaryArtery = GetAFDB()->template GetImage("RightPulmonaryArtery"); typedef SliceBySliceRelativePositionFilter SliceRelPosFilterType; typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New(); sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(RightPulmonaryArtery); sliceRelPosFilter->SetDirection(2); sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "RightPulmonaryArtery")); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); m_Working_Support = sliceRelPosFilter->GetOutput(); StopCurrentStep(m_Working_Support); // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with LeftPulmonaryArtery"); MaskImagePointer LeftPulmonaryArtery = GetAFDB()->template GetImage("LeftPulmonaryArtery"); sliceRelPosFilter = SliceRelPosFilterType::New(); sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(LeftPulmonaryArtery); sliceRelPosFilter->SetDirection(2); sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "LeftPulmonaryArtery")); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); m_Working_Support = sliceRelPosFilter->GetOutput(); StopCurrentStep(m_Working_Support); StartNewStep("[Station7] Limits with SVC"); MaskImagePointer SVC = GetAFDB()->template GetImage("SVC"); sliceRelPosFilter = SliceRelPosFilterType::New(); sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(SVC); sliceRelPosFilter->SetDirection(2); sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "SVC")); sliceRelPosFilter->AddOrientationTypeString("NotRightTo"); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(true); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); m_Working_Support = sliceRelPosFilter->GetOutput(); StopCurrentStep(m_Working_Support); // End m_ListOfStations["7"] = m_Working_Support; } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_Posterior_Limits() { StartNewStep("[Station7] Posterior limits -> must be AntTo post wall of the bronchi (OLD CLASSIF)"); // Search for points that are the most left/post/ant and most // right/post/ant of the left and right bronchus // extract, loop slices, label/keep, find extrema x 3 /* FindExtremaPointsInBronchus(m_LeftBronchus, 0, 15, m_RightMostInLeftBronchus, m_AntMostInLeftBronchus, m_PostMostInLeftBronchus); FindExtremaPointsInBronchus(m_RightBronchus, 1, 15, m_LeftMostInRightBronchus, m_AntMostInRightBronchus, m_PostMostInRightBronchus); */ // First cut bronchus to the correct sup/inf support MaskImagePointer RightBronchus = clitk::ResizeImageLike(m_RightBronchus, m_Working_Support, GetBackgroundValue()); MaskImagePointer LeftBronchus = clitk::ResizeImageLike(m_LeftBronchus, m_Working_Support, GetBackgroundValue()); // Find extrema points FindExtremaPointsInBronchus(RightBronchus, 0, 10, m_LeftMostInRightBronchus, m_AntMostInRightBronchus, m_PostMostInRightBronchus); FindExtremaPointsInBronchus(LeftBronchus, 1, 10, m_RightMostInLeftBronchus, m_AntMostInLeftBronchus, m_PostMostInLeftBronchus); // DEBUG std::ofstream osrl; openFileForWriting(osrl, "osrl.txt"); osrl << "LANDMARKS1" << std::endl; std::ofstream osal; openFileForWriting(osal, "osal.txt"); osal << "LANDMARKS1" << std::endl; std::ofstream ospl; openFileForWriting(ospl, "ospl.txt"); ospl << "LANDMARKS1" << std::endl; std::ofstream osrr; openFileForWriting(osrr, "osrr.txt"); osrr << "LANDMARKS1" << std::endl; std::ofstream osar; openFileForWriting(osar, "osar.txt"); osar << "LANDMARKS1" << std::endl; std::ofstream ospr; openFileForWriting(ospr, "ospr.txt"); ospr << "LANDMARKS1" << std::endl; for(uint i=0; i(m_Working_Support, m_PostMostInRightBronchus, m_PostMostInLeftBronchus, GetBackgroundValue(), 1, -10); // If needed -> can do the same with AntMost. // End StopCurrentStep(m_Working_Support); m_ListOfStations["7"] = m_Working_Support; } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_Remove_Structures() { //-------------------------------------------------------------------- StartNewStep("[Station7] remove some structures"); Remove_Structures("7", "AzygousVein"); Remove_Structures("7", "Aorta"); Remove_Structures("7", "RightPulmonaryArtery"); Remove_Structures("7", "LeftPulmonaryArtery"); Remove_Structures("7", "LeftSuperiorPulmonaryVein"); Remove_Structures("7", "PulmonaryTrunk"); Remove_Structures("7", "VertebralBody"); // Keep only one CCL by slice (before removing Esophagus) // DD("SliceBySliceKeepMainCCL"); // TODO -> replace by keep the one that contains point at the middle of the line between the bronchus // -> new function "keep/select" the ccl that contains this point (2D) //m_Working_Support = clitk::SliceBySliceKeepMainCCL(m_Working_Support, GetBackgroundValue(), GetForegroundValue()); Remove_Structures("7", "Esophagus"); // END StopCurrentStep(m_Working_Support); m_ListOfStations["7"] = m_Working_Support; return; } //--------------------------------------------------------------------