X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=segmentation%2FclitkExtractLymphStation_7.txx;h=d6df42895faa021bd9298d4dc95cc11bdbc47402;hb=5a7da4aedae5c204bc55c187717193e5950f9a44;hp=c5811661712d1a16ebffc34bbebcf47933cc5c11;hpb=765020625fbc092d283e221e36c83e60a1844cb7;p=clitk.git diff --git a/segmentation/clitkExtractLymphStation_7.txx b/segmentation/clitkExtractLymphStation_7.txx index c581166..d6df428 100644 --- a/segmentation/clitkExtractLymphStation_7.txx +++ b/segmentation/clitkExtractLymphStation_7.txx @@ -1,20 +1,3 @@ -/*========================================================================= - 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://www.centreleonberard.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 -===========================================================================*/ //-------------------------------------------------------------------- template @@ -22,38 +5,81 @@ void clitk::ExtractLymphStationsFilter:: ExtractStation_7_SetDefaultValues() { - SetFuzzyThresholdForS7("Bronchi", 0.1); - SetFuzzyThresholdForS7("LeftSuperiorPulmonaryVein", 0.3); - SetFuzzyThresholdForS7("RightSuperiorPulmonaryVein", 0.2); - SetFuzzyThresholdForS7("RightPulmonaryArtery", 0.3); - SetFuzzyThresholdForS7("LeftPulmonaryArtery", 0.5); - SetFuzzyThresholdForS7("SVC", 0.2); + 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:: -SetFuzzyThresholdForS7(std::string tag, double value) -{ - m_FuzzyThresholdForS7[tag] = value; +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 -double +void clitk::ExtractLymphStationsFilter:: -GetFuzzyThresholdForS7(std::string tag) +ExtractStation_7_SI_Limits() { - if (m_FuzzyThresholdForS7.find(tag) != m_FuzzyThresholdForS7.end()) { - return m_FuzzyThresholdForS7[tag]; - } - else { - clitkExceptionMacro("Could not find options "+tag+" in the m_FuzzyThresholdForS7 list"); - } + 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; } //-------------------------------------------------------------------- @@ -62,46 +88,167 @@ GetFuzzyThresholdForS7(std::string tag) template void clitk::ExtractLymphStationsFilter:: -ExtractStation_7_SI_Limits() +ExtractStation_7_RL_Interior_Limits() { - StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLLBronchus"); - // Get Inputs - MaskImagePointer Trachea = GetAFDB()->template GetImage ("Trachea"); + // ---------------------------------------------------------------- + StartNewStep("[Station7] RL limits with bronchi"); - // We suppoe that CarinaZ was already computed (S8) - double m_CarinaZ = GetAFDB()->GetDouble("CarinaZ"); + /* + 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 + } - // double m_OriginOfRightMiddleLobeBronchusZ = GetAFDB()->GetPoint3D("OriginOfRightMiddleLobeBronchus", 2); - // DD(m_OriginOfRightMiddleLobeBronchusZ); - MaskImagePointer UpperBorderOfLLLBronchus = GetAFDB()->template GetImage("UpperBorderOfLLLBronchus"); + // Joint slices + m_LeftBronchus = clitk::JoinSlices(slices_leftbronchus, m_LeftBronchus, 2); + m_RightBronchus = clitk::JoinSlices(slices_rightbronchus, m_RightBronchus, 2); - // Search most inf point (WHY ? IS IT THE RIGHT STRUCTURE ??) - MaskImagePointType ps = UpperBorderOfLLLBronchus->GetOrigin(); // initialise to avoid warning - clitk::FindExtremaPointInAGivenDirection(UpperBorderOfLLLBronchus, GetBackgroundValue(), 2, true, ps); - double m_UpperBorderOfLLLBronchusZ = ps[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); + } + } - /* - std::vector centroids; - clitk::ComputeCentroids(UpperBorderOfLLLBronchus, GetBackgroundValue(), centroids); - double m_UpperBorderOfLLLBronchusZ = centroids[1][2]; - DD(m_UpperBorderOfLLLBronchusZ) - */ + // 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); - /* Crop support */ + // Also remove what is at right of the Right bronchus (left respectively) m_Working_Support = - clitk::CropImageAlongOneAxis(m_Working_Support, 2, - m_UpperBorderOfLLLBronchusZ, - m_CarinaZ, true, - GetBackgroundValue()); - /* Crop trachea */ - m_Working_Trachea = - clitk::CropImageAlongOneAxis(Trachea, 2, - m_UpperBorderOfLLLBronchusZ, - m_CarinaZ, true, - GetBackgroundValue()); + 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); - m_ListOfStations["7"] = m_Working_Support; } //-------------------------------------------------------------------- @@ -110,7 +257,7 @@ ExtractStation_7_SI_Limits() template void clitk::ExtractLymphStationsFilter:: -ExtractStation_7_RL_Limits() +ExtractStation_7_RL_Limits_OLD() { // ---------------------------------------------------------------- StartNewStep("[Station7] Limits with bronchus : RightTo the left bronchus"); @@ -125,6 +272,10 @@ ExtractStation_7_RL_Limits() 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); @@ -175,7 +326,7 @@ ExtractStation_7_RL_Limits() m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, - GetFuzzyThresholdForS7("Bronchi"), "RightTo", + GetFuzzyThreshold("7", "Bronchi"), "RightTo", false, 3, false); StopCurrentStep(m_Working_Support); @@ -184,7 +335,7 @@ ExtractStation_7_RL_Limits() StartNewStep("[Station7] Limits with bronchus : LeftTo the right bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, - GetFuzzyThresholdForS7("Bronchi"), "LeftTo", + GetFuzzyThreshold("7", "Bronchi"), "LeftTo", false, 3, false); StopCurrentStep(m_Working_Support); @@ -198,12 +349,12 @@ ExtractStation_7_RL_Limits() sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(LeftSuperiorPulmonaryVein); sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThresholdForS7("LeftSuperiorPulmonaryVein")); + sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein")); sliceRelPosFilter->AddOrientationTypeString("NotLeftTo"); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySlice(false); + sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); @@ -223,13 +374,13 @@ ExtractStation_7_RL_Limits() sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(RightSuperiorPulmonaryVein); sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThresholdForS7("RightSuperiorPulmonaryVein")); + sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "RightSuperiorPulmonaryVein")); sliceRelPosFilter->AddOrientationTypeString("NotRightTo"); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->AddOrientationTypeString("NotPostTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySlice(false); + sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); @@ -248,11 +399,11 @@ ExtractStation_7_RL_Limits() sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(RightPulmonaryArtery); sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThresholdForS7("RightPulmonaryArtery")); + sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "RightPulmonaryArtery")); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySlice(false); + sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); @@ -266,11 +417,11 @@ ExtractStation_7_RL_Limits() sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(LeftPulmonaryArtery); sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThresholdForS7("LeftPulmonaryArtery")); + sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "LeftPulmonaryArtery")); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySlice(false); + sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(false); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); @@ -283,12 +434,12 @@ ExtractStation_7_RL_Limits() sliceRelPosFilter->SetInput(m_Working_Support); sliceRelPosFilter->SetInputObject(SVC); sliceRelPosFilter->SetDirection(2); - sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThresholdForS7("SVC")); + sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("7", "SVC")); sliceRelPosFilter->AddOrientationTypeString("NotRightTo"); sliceRelPosFilter->AddOrientationTypeString("NotAntTo"); sliceRelPosFilter->SetIntermediateSpacingFlag(true); sliceRelPosFilter->SetIntermediateSpacing(3); - sliceRelPosFilter->SetUniqueConnectedComponentBySlice(false); + sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(false); sliceRelPosFilter->SetAutoCropFlag(true); sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn(); sliceRelPosFilter->Update(); @@ -386,14 +537,23 @@ ExtractStation_7_Remove_Structures() //-------------------------------------------------------------------- StartNewStep("[Station7] remove some structures"); - Remove_Structures("AzygousVein"); - Remove_Structures("Aorta"); - Remove_Structures("Esophagus"); - Remove_Structures("RightPulmonaryArtery"); - Remove_Structures("LeftPulmonaryArtery"); - Remove_Structures("LeftSuperiorPulmonaryVein"); - Remove_Structures("PulmonaryTrunk"); - Remove_Structures("VertebralBody"); + 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);