X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=segmentation%2FclitkExtractLymphStation_Supports.txx;h=f480d842b2990cc3c16156b2500b5add84281ed7;hb=b2fd61648c05339dd302e102361c22c4b11d48ff;hp=903948dafbaae16e4f8daf4ad6969ef6dbf47ffe;hpb=a27c5cbbf1db44ddc5f519710cddcc1001c15f35;p=clitk.git diff --git a/segmentation/clitkExtractLymphStation_Supports.txx b/segmentation/clitkExtractLymphStation_Supports.txx index 903948d..f480d84 100644 --- a/segmentation/clitkExtractLymphStation_Supports.txx +++ b/segmentation/clitkExtractLymphStation_Supports.txx @@ -8,67 +8,587 @@ void clitk::ExtractLymphStationsFilter:: ExtractStationSupports() { - DD("ExtractStationSupports"); - // Get initial Mediastinum - m_Working_Support = m_Mediastinum = GetAFDB()->template GetImage("Mediastinum", true); - - // Superior limits: CricoidCartilag - // Inferior limits: lung - // (the Mediastinum support already stop at this limit) - - // Consider above Carina - m_CarinaZ = FindCarinaSlicePosition(); - MaskImagePointer m_Support_Superior_to_Carina = - clitk::CropImageRemoveLowerThan(m_Working_Support, 2, - m_CarinaZ, true, GetBackgroundValue()); - MaskImagePointer m_Support_Inferior_to_Carina = - clitk::CropImageRemoveGreaterThan(m_Working_Support, 2, - m_CarinaZ, true, GetBackgroundValue()); - - // Consider only Superior to Carina - m_Working_Support = m_Support_Superior_to_Carina; - - // Step : S1RL - StartNewStep("[Support] sup-inf S1RL"); + m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage("Mediastinum", true); + + // Remove some computed structures + this->GetAFDB()->RemoveTag("CarinaZ"); + this->GetAFDB()->RemoveTag("ApexOfTheChestZ"); + + // Superior and inferior limits. + Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0); + Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]); + + // Read all support limits in a file and apply them + ReadSupportLimits(GetSupportLimitsFilename()); + for(unsigned int i=0; iGetSpacing()[2]); + } + + // S1RL + Support_LeftRight_S1R_S1L(); + + // S2RL + Support_LeftRight_S2R_S2L(); + + // S4RL + Support_LeftRight_S4R_S4L(); + + // Post limits of S1,S2,S4 + Support_Post_S2S4(); + + // S3P : "the anterior border is an imaginary horizontal line + // extending along the posterior wall of the trachea" + StartNewStep("[Support] Ant limits of S3P with trachea"); + m_ListOfSupports["S3P"] = LimitsWithTrachea(m_ListOfSupports["S3P"], 1, 0, 10); + + // S3A : "Posteriorly, the station is limited by station 2R and 2L, + // but excludes the great vessels. An imaginary line joins the + // midpoint of the vessel in the anterior to posterior plane. It is + // here that station 2 contacts station 3a" ===> here limit with + // trachea only + StartNewStep("[Support] Ant limits of S3A with trachea"); + m_ListOfSupports["S3A"] = LimitsWithTrachea(m_ListOfSupports["S3A"], 1, 0, -10); + + // S1RL - posterior limits when SI overlap with S3P + Support_Post_S1_S3P(); + + // S1RL - posterior limits with S2RL above sternal notch + Support_Post_S1_Ant_S2RL(); + + // I will do it later + // Below Carina S7,8,9,10 + m_ListOfSupports["S7"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); + m_ListOfSupports["S8"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); + m_ListOfSupports["S9"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); + m_ListOfSupports["S10"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); + m_ListOfSupports["S11"] = clitk::Clone(m_ListOfSupports["Inf_to_Carina"]); + + // Store image filenames into AFDB + WriteImageSupport("S1R"); WriteImageSupport("S1L"); + WriteImageSupport("S2R"); WriteImageSupport("S2L"); + WriteImageSupport("S3A"); WriteImageSupport("S3P"); + WriteImageSupport("S4R"); WriteImageSupport("S4L"); + WriteImageSupport("S5"); + WriteImageSupport("S6"); + WriteImageSupport("S7"); + WriteImageSupport("S8"); + WriteImageSupport("S9"); + WriteImageSupport("S10"); + WriteImageSupport("S11"); + WriteAFDB(); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_SI_Limit(const std::string station_limit, const std::string station, + const std::string structure_limit, const std::string structure, + const double offset) +{ + if (!GetCheckSupportFlag()) + StartNewStep("[Support] "+station_limit+" limit of "+station+" is "+structure_limit+" limit of "+structure); + + // Check + if ((station_limit != "superior") && (station_limit != "inferior")) { + clitkExceptionMacro("Error station_limit must be 'inferior' or 'superior', not '"<< station_limit); + } + if ((structure_limit != "superior") && (structure_limit != "inferior")) { + clitkExceptionMacro("Error structure_limit must be 'inferior' or 'superior', not '"<< structure_limit); + } + + // Get current support + if (m_ListOfSupports.find(station) == m_ListOfSupports.end()) { + // std::cerr << "Warning: support " << station << " not initialized" << std::endl; + m_ListOfSupports[station] = m_Mediastinum; + } + m_Working_Support = m_ListOfSupports[station]; + + // Get structure or structureZ + double z=0.; + int found=0; + std::string file; + + // Try to load structure and compute extrema point + if (this->GetAFDB()->TagExist(structure)) { + MaskImagePointer Structure = this->GetAFDB()->template GetImage (structure); + file = this->GetAFDB()->GetTagValue(structure); + MaskImagePointType p; + p[0] = p[1] = p[2] = 0.0; // to avoid warning + if (structure_limit == "superior") + clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, false, p); + else + clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, true, p); + z = p[2]; + found=1; + } + + // Try to load structureZ + if ((found==0) && (this->GetAFDB()->TagExist(structure+"Z"))) { + z = this->GetAFDB()->GetDouble(structure+"Z"); + found=2; + } + + // Try to load structurePoint + if ((found==0) && (this->GetAFDB()->TagExist(structure+"Point"))) { + MaskImagePointType p; + this->GetAFDB()->GetPoint3D(structure+"Point", p); + z = p[2]; + found=3; + } + + // Try to see if it is an already computed support + if (found==0) { + if (m_ListOfSupports.find(structure) != m_ListOfSupports.end()) { + MaskImagePointer Structure = m_ListOfSupports[structure]; + MaskImagePointType p; + if (structure_limit == "superior") + clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, false, p); + else + clitk::FindExtremaPointInAGivenDirection(Structure, GetBackgroundValue(), 2, true, p); + z = p[2]; + found=4; + } + } + + // Try special case : "FindApexOfTheChest" + if (structure == "FindApexOfTheChest") { + z = FindApexOfTheChest(); + found=5; + } + if (structure == "FindInferiorBorderOfAorticArch") { + z = FindInferiorBorderOfAorticArch(); + found=6; + } + if (structure == "FindSuperiorBorderOfAorticArch") { + z = FindSuperiorBorderOfAorticArch(); + found=6; + } + + // If we find anything + if (found == 0) { + std::cerr << "ERROR : I could not find " << structure << " nor " << structure << "Z nor " + << structure << "Point" << std::endl; + exit(EXIT_FAILURE); + } + + // Apply offset + z += offset; + + // Remove Lower or greater + if (station_limit == "inferior") { + m_Working_Support = + clitk::CropImageRemoveLowerThan(m_Working_Support, 2, z, true, GetBackgroundValue()); + } + else { + m_Working_Support = + clitk::CropImageRemoveGreaterThan(m_Working_Support, 2, z, true, GetBackgroundValue()); + } + + // Check: if reference station is given, display information + if (GetCheckSupportFlag()) { + try { + MaskImagePointer Ref = this->GetAFDB()->template GetImage (station+"_Ref"); + MaskImagePointType p_support; + MaskImagePointType p_ref; + if (station_limit == "superior") { + clitk::FindExtremaPointInAGivenDirection(Ref, GetBackgroundValue(), 2, false, p_ref); + clitk::FindExtremaPointInAGivenDirection(m_Working_Support, GetBackgroundValue(), 2, false, p_support); + } + else { + clitk::FindExtremaPointInAGivenDirection(Ref, GetBackgroundValue(), 2, true, p_ref); + clitk::FindExtremaPointInAGivenDirection(m_Working_Support, GetBackgroundValue(), 2, true, p_support); + } + std::ostringstream os; + os << "[Support] \t" << station << "\t" << station_limit << " " + << "Z = " << z << std::setprecision(2) << std::fixed + << "\tSupport = " << p_support[2] + << "\tRef = " << p_ref[2] + << "\tdiff = " << p_support[2]-p_ref[2] << "\t" + << structure << " " << structure_limit; + if (found==1) os << " (S "+file+")"; + if (found==2) os << " (Z)"; + if (found==3) os << " (P)"; + if (found==4) os << " (p)"; + if (found==5) os << " (Apex)"; + if (found==6) os << " (AorticArch)"; + StartNewStep(os.str()); + } catch(clitk::ExceptionObject e) { } + } + + // Set support + m_ListOfSupports[station] = m_Working_Support; + StopCurrentStep(m_Working_Support); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_LeftRight_S1R_S1L() +{ /* - Lower border: clavicles bilaterally and, in the midline, the upper - border of the manubrium, 1R designates right-sided nodes, 1L, - left-sided nodes in this region - - 2R: Upper border: apex of the right lung and pleural space, and in - the midline, the upper border of the manubrium - - 2L: Upper border: apex of the left lung and pleural space, and in the - midline, the upper border of the manubrium + Medially, station 1R and 1L are separated by the midline of the + trachea, whilst excluding the thyroid gland. */ + // Step S1RL : Left-Right + StartNewStep("[Support] Left-Right S1R S1L"); + std::vector A; + std::vector B; + // Search for centroid positions of trachea + MaskImagePointer Trachea = this->GetAFDB()->template GetImage ("Trachea"); + MaskImagePointer S1RL = m_ListOfSupports["S1R"]; + Trachea = clitk::ResizeImageLike(Trachea, S1RL, GetBackgroundValue()); + std::vector slices; + clitk::ExtractSlices(Trachea, 2, slices); + for(uint i=0; i(slices[i], 0, false, 10); + std::vector c; + clitk::ComputeCentroids(slices[i], GetBackgroundValue(), c); + ImagePointType a,b; + clitk::PointsUtils::Convert2DTo3D(c[1], Trachea, i, a); + A.push_back(a); + b = a; + b[1] += 50; + B.push_back(b); + } + clitk::WriteListOfLandmarks(A, "S1LR_A.txt"); + clitk::WriteListOfLandmarks(B, "S1LR_B.txt"); + // Clone support + MaskImagePointer S1R = clitk::Clone(S1RL); + MaskImagePointer S1L = clitk::Clone(S1RL); + // Right part + clitk::SliceBySliceSetBackgroundFromLineSeparation(S1R, A, B, + GetBackgroundValue(), 0, -10); + S1R = clitk::AutoCrop(S1R, GetBackgroundValue()); + m_ListOfSupports["S1R"] = S1R; + // Left part + clitk::SliceBySliceSetBackgroundFromLineSeparation(S1L, A, B, + GetBackgroundValue(), 0, 10); + S1L = clitk::AutoCrop(S1L, GetBackgroundValue()); + m_ListOfSupports["S1L"] = S1L; + StopCurrentStep(m_ListOfSupports["S1L"]); +} +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_LeftRight_S2R_S2L() +{ + // --------------------------------------------------------------------------- + /* Step : S2RL LeftRight As for lymph node station 4R, 2R includes + nodes extending to the left lateral border of the trachea. + Rod says: "For station 2 there is a shift in the IASLC definition + dividing 2R from 2L, from the midline to the left lateral + tracheal border. This is represented in the atlas as a vertical + line passing tangentially along the left lateral tracheal border + " + */ + StartNewStep("[Support] Separate 2R/2L according to Trachea"); + MaskImagePointer S2R = m_ListOfSupports["S2R"]; + MaskImagePointer S2L = m_ListOfSupports["S2L"]; + S2R = LimitsWithTrachea(S2R, 0, 1, -10); + S2L = LimitsWithTrachea(S2L, 0, 1, 10); + S2R = clitk::AutoCrop(S2R, GetBackgroundValue()); + S2L = clitk::AutoCrop(S2L, GetBackgroundValue()); + m_ListOfSupports["S2R"] = S2R; + m_ListOfSupports["S2L"] = S2L; + this->GetAFDB()->template ReleaseImage("Trachea"); +} +//-------------------------------------------------------------------- - // // LeftRight cut along trachea - // MaskImagePointer Trachea = GetAFDB()->GetImage("Trachea"); - // // build a ant-post line for each slice +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_LeftRight_S4R_S4L() +{ + // --------------------------------------------------------------------------- + /* + The medial border of station 4R is defined as an imaginary line + running vertically from the left lateral tracheal border. This is + the same medial border as was described for station 2R. + */ + StartNewStep("[Support] Left Right separation of 4R/4L"); - // MaskImagePointer m_Support_SupRight = - // clitk::CropImageRemoveLowerThan(m_Working_Support, 2, - // m_CarinaZ, true, GetBackgroundValue()); + MaskImagePointer S4R = m_ListOfSupports["S4R"]; + MaskImagePointer S4L = m_ListOfSupports["S4L"]; + S4R = LimitsWithTrachea(S4R, 0, 1, -10); + S4L = LimitsWithTrachea(S4L, 0, 1, 10); + m_ListOfSupports["S4R"] = S4R; + m_ListOfSupports["S4L"] = S4L; +} +//-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +typename clitk::ExtractLymphStationsFilter::MaskImagePointer +clitk::ExtractLymphStationsFilter:: +LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection, + double offset) +{ + MaskImagePointType min, max; + GetMinMaxBoundary(input, min, max); + return LimitsWithTrachea(input, extremaDirection, lineDirection, offset, max[2]); +} +template +typename clitk::ExtractLymphStationsFilter::MaskImagePointer +clitk::ExtractLymphStationsFilter:: +LimitsWithTrachea(MaskImageType * input, int extremaDirection, int lineDirection, + double offset, double maxSupPosition) +{ + /* + Take the input mask, consider the trachea and limit according to + Left border of the trachea. Keep at Left or at Right according to + the offset + */ + // Read the trachea + MaskImagePointer Trachea = this->GetAFDB()->template GetImage("Trachea"); + // Find extrema post positions + std::vector tracheaLeftPositionsA; + std::vector tracheaLeftPositionsB; + // Crop Trachea only on the Sup-Inf axes, without autocrop + // Trachea = clitk::ResizeImageLike(Trachea, input, GetBackgroundValue()); + MaskImagePointType min, max; + GetMinMaxBoundary(input, min, max); + Trachea = clitk::CropImageAlongOneAxis(Trachea, 2, min[2], max[2], + false, GetBackgroundValue()); + + // Select the main CCL (because of bronchus) + Trachea = SliceBySliceKeepMainCCL(Trachea, GetBackgroundValue(), GetForegroundValue()); - // Store image filenames into AFDB - m_ListOfSupports["S1R"] = m_Working_Support; - writeImage(m_ListOfSupports["S1R"], "seg/Support_S1R.mhd"); - GetAFDB()->SetImageFilename("Support_S1R", "seg/Support_S1R.mhd"); - WriteAFDB(); + // Slice by slice, build the separation line + clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(Trachea, + GetBackgroundValue(), 2, + extremaDirection, false, // Left + lineDirection, // Vertical line + -1, // margins + tracheaLeftPositionsA, + tracheaLeftPositionsB); + // Do not consider trachea above the limit + int indexMax=tracheaLeftPositionsA.size(); + for(uint i=0; i maxSupPosition) { + indexMax = i; + i = tracheaLeftPositionsA.size(); // stop loop + } + } + tracheaLeftPositionsA.erase(tracheaLeftPositionsA.begin()+indexMax, tracheaLeftPositionsA.end()); + tracheaLeftPositionsB.erase(tracheaLeftPositionsB.begin()+indexMax, tracheaLeftPositionsB.end()); + + // Cut post to this line + clitk::SliceBySliceSetBackgroundFromLineSeparation(input, + tracheaLeftPositionsA, + tracheaLeftPositionsB, + GetBackgroundValue(), + extremaDirection, offset); + MaskImagePointer output = clitk::AutoCrop(input, GetBackgroundValue()); + return output; } //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_Post_S2S4() +{ + StartNewStep("[Support] Post limits of S2RL, S4RL"); + + double m_ApexOfTheChest = FindApexOfTheChest(); + + // Post limits with Trachea + // MaskImagePointer S1R = m_ListOfSupports["S1R"]; + // MaskImagePointer S1L = m_ListOfSupports["S1L"]; + MaskImagePointer S2R = m_ListOfSupports["S2R"]; + MaskImagePointer S2L = m_ListOfSupports["S2L"]; + MaskImagePointer S4R = m_ListOfSupports["S4R"]; + MaskImagePointer S4L = m_ListOfSupports["S4L"]; + // m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest); + // m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest); + m_ListOfSupports["S2R"] = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest); + m_ListOfSupports["S2L"] = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest); + m_ListOfSupports["S4R"] = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest); + m_ListOfSupports["S4L"] = LimitsWithTrachea(S4L, 1, 0, -10, m_ApexOfTheChest); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_Post_S1_S3P() +{ + StartNewStep("[Support] If S1RL and S3P have Sup-Inf overlap, define S1RL posterior limits with S3P anterior limits (post wall trachea)"); + + // Get current supports + MaskImagePointer S1R = m_ListOfSupports["S1R"]; + MaskImagePointer S1L = m_ListOfSupports["S1L"]; + + // Find extrema ant positions for 3P + std::vector A; + std::vector B; + + // Crop S3P like S1R + MaskImagePointer S3P = clitk::Clone(m_ListOfSupports["S3P"]); + S3P = clitk::ResizeImageLike(S3P, S1R, GetBackgroundValue()); + + // Slice by slice, build the separation line + clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(S3P, + GetBackgroundValue(), 2, + 1, true, // Ant-Post + 0, // Horizontal line + 0, // margins + A, B); + + // clitk::WriteListOfLandmarks(A, "A-S1S3P.txt"); + // clitk::WriteListOfLandmarks(B, "B-S1S3P.txt"); + + // Cut post to this line + clitk::SliceBySliceSetBackgroundFromLineSeparation(S1R, A, B, + GetBackgroundValue(), + 1, -10); + + // Crop S3P like S1L (Redo for S1L) + S3P = clitk::Clone(m_ListOfSupports["S3P"]); + S3P = clitk::ResizeImageLike(S3P, S1L, GetBackgroundValue()); + + // Slice by slice, build the separation line + A.clear(); + B.clear(); + clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(S3P, + GetBackgroundValue(), 2, + 1, true, // Ant-Post + 0, // Horizontal line + 0, // margins + A, B); + // Cut post to this line + clitk::SliceBySliceSetBackgroundFromLineSeparation(S1L, A, B, + GetBackgroundValue(), + 1, -10); + + // Crop both images + S1R = clitk::AutoCrop(S1R, GetBackgroundValue()); + S1L = clitk::AutoCrop(S1L, GetBackgroundValue()); + + StopCurrentStep(S1R); + + m_ListOfSupports["S1R"] = S1R; + m_ListOfSupports["S1L"] = S1L; +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +Support_Post_S1_Ant_S2RL() +{ + StartNewStep("[Support] Define S1RL posterior limits with S2RL anterior limits when overlap"); + + // Get RightLung + MaskImagePointer RightLung = this->GetAFDB()->template GetImage("RightLung"); + + // Find common area between S1 and S2 + MaskImagePointType p_min; + MaskImagePointType p_max; + clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S2R"], + GetBackgroundValue(), 2, false, p_max); + clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S1R"], + GetBackgroundValue(), 2, true, p_min); + p_min[2] -= RightLung->GetSpacing()[2]; // consider the slice below (remove lower or equal) + p_max[2] += RightLung->GetSpacing()[2]; // consider the slice abov (remove greater or equal) + + if (p_min[2] > p_max[2]) { + + // Crop RightLung + RightLung = clitk::Clone(RightLung); + RightLung = clitk::ResizeImageLike(RightLung, m_ListOfSupports["S1R"], GetBackgroundValue()); + RightLung = clitk::CropImageRemoveLowerThan(RightLung, 2, p_min[2], true, GetBackgroundValue()); + RightLung = clitk::CropImageRemoveGreaterThan(RightLung, 2, p_max[2], true, GetBackgroundValue()); + + // Find extrema ant positions for RightLung + std::vector A; + std::vector B; + clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(RightLung, + GetBackgroundValue(), 2, + 1, true, // Ant-Post + 0, // Horizontal line + 0, // margins + A, B); + clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S1R"], + A, B, + GetBackgroundValue(), + 1, -10); + // I add one pixel to abupt S2R to S1R + for(int i=0; iGetSpacing()[1]; + B[i][1] -= RightLung->GetSpacing()[1]; + } + clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S2R"], + A, B, + GetBackgroundValue(), + 1, 10); + } + + // Get LeftLung, crop + MaskImagePointer LeftLung = this->GetAFDB()->template GetImage("LeftLung"); + clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S2L"], + GetBackgroundValue(), 2, false, p_max); + clitk::FindExtremaPointInAGivenDirection(m_ListOfSupports["S1L"], + GetBackgroundValue(), 2, true, p_min); + p_min[2] -= LeftLung->GetSpacing()[2]; // consider the slice below (remove lower or equal) + p_max[2] += LeftLung->GetSpacing()[2]; // consider the slice abov (remove greater or equal) + + if (p_min[2] > p_max[2]) { + LeftLung = clitk::ResizeImageLike(LeftLung, m_ListOfSupports["S1L"], GetBackgroundValue()); + LeftLung = clitk::CropImageRemoveLowerThan(LeftLung, 2, p_min[2], true, GetBackgroundValue()); + LeftLung = clitk::CropImageRemoveGreaterThan(LeftLung, 2, p_max[2], true, GetBackgroundValue()); + + // Find extrema ant positions for LeftLung + std::vector A; + std::vector B; + clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition(LeftLung, + GetBackgroundValue(), 2, + 1, true, // Ant-Post + 0, // Horizontal line + 0, // margins + A, B); + clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S1L"], + A, B, + GetBackgroundValue(), + 1, -10); + // I add one pixel to abupt S2R to S1R + for(int i=0; iGetSpacing()[1]; + B[i][1] -= LeftLung->GetSpacing()[1]; + } + clitk::SliceBySliceSetBackgroundFromLineSeparation(m_ListOfSupports["S2L"], + A, B, + GetBackgroundValue(), + 1, 10); + } +} +//--------------------------------------------------------------------