X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=segmentation%2FclitkExtractLymphStation_3A.txx;h=8bcabc593637accf432be590f9a5177c8692d804;hb=3c86758765bc9bcba20d439424bcf97091b5af6f;hp=044691304971179c1507e3efac5ea2becd75c79e;hpb=765020625fbc092d283e221e36c83e60a1844cb7;p=clitk.git diff --git a/segmentation/clitkExtractLymphStation_3A.txx b/segmentation/clitkExtractLymphStation_3A.txx index 0446913..8bcabc5 100644 --- a/segmentation/clitkExtractLymphStation_3A.txx +++ b/segmentation/clitkExtractLymphStation_3A.txx @@ -1,30 +1,139 @@ -/*========================================================================= - 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 +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +ExtractStation_3A_SetDefaultValues() +{ + SetFuzzyThreshold("3A", "Sternum", 0.5); + SetFuzzyThreshold("3A", "SubclavianArtery", 0.5); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +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(m_Working_Support); + + ExtractStation_3A_AntPost_S5(); + ExtractStation_3A_AntPost_S6(); + ExtractStation_3A_AntPost_Superiorly(); + ExtractStation_3A_Remove_Structures(); - 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. + Remove_Structures("3A", "Aorta"); + Remove_Structures("3A", "SubclavianArteryLeft"); + Remove_Structures("3A", "SubclavianArteryRight"); + Remove_Structures("3A", "Thyroid"); + Remove_Structures("3A", "CommonCarotidArteryLeft"); + Remove_Structures("3A", "CommonCarotidArteryRight"); + Remove_Structures("3A", "BrachioCephalicArtery"); - It is distributed under dual licence + ExtractStation_3A_PostToBones(); + + // Keep a single CCL + m_ListOfStations["3A"] = + clitk::SliceBySliceKeepMainCCL(m_ListOfStations["3A"], + GetBackgroundValue(), + GetForegroundValue()); + + // Store image filenames into AFDB + writeImage(m_ListOfStations["3A"], "seg/Station3A.mhd"); + GetAFDB()->SetImageFilename("Station3A", "seg/Station3A.mhd"); + WriteAFDB(); + StopSubStep(); +} +//-------------------------------------------------------------------- - - BSD See included LICENSE.txt file - - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -===========================================================================*/ -#include -#include //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_SetDefaultValues() +ExtractStation_3A_AntPost_S5() { + StartNewStep("[Station 3A] Post limits around S5"); + + // First remove post to SVC + MaskImagePointer SVC = GetAFDB()->template GetImage ("SVC"); + + // Trial in 3D -> difficulties superiorly. Stay slice by slice. + // Slice by slice not post to SVC. Use initial spacing + m_Working_Support = + clitk::SliceBySliceRelativePosition(m_Working_Support, SVC, 2, + GetFuzzyThreshold("3A", "SVC"), + "NotPostTo", true, + SVC->GetSpacing()[0], false, false); + + // Consider Aorta, remove Left/Post part ; only around S5 + // Get S5 support and Aorta + MaskImagePointer S5 = m_ListOfSupports["S5"]; + MaskImagePointer Aorta = GetAFDB()->template GetImage ("Aorta"); + Aorta = clitk::ResizeImageLike(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. + std::vector slices; + clitk::ExtractSlices(Aorta, 2, slices); + std::vector points; + for(uint i=0; i(slices[i], GetBackgroundValue(), false, 1); + std::vector c; + clitk::ComputeCentroids(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(slices[i], slices[i], l, + GetBackgroundValue(), true); + + // Detect the most ant point + MaskSlicePointType p; + MaskImagePointType pA; + clitk::FindExtremaPointInAGivenDirection(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::Convert2DTo3D(p, Aorta, i, pA); + points.push_back(pA); + } + + // DEBUG + // MaskImagePointer o = clitk::JoinSlices(slices, Aorta, 2); + // writeImage(o, "o.mhd"); + // clitk::WriteListOfLandmarks(points, "Ant-Aorta.txt"); + + // Remove Post/Left to this point + m_Working_Support = + clitk::SliceBySliceSetBackgroundFromPoints(m_Working_Support, + GetBackgroundValue(), 2, + points, + true, // Set BG if X greater than point[x], and + true); // if Y greater than point[y] + + StopCurrentStep(m_Working_Support); + m_ListOfStations["3A"] = m_Working_Support; } //-------------------------------------------------------------------- @@ -33,28 +142,88 @@ ExtractStation_3A_SetDefaultValues() template void clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_SI_Limits() +ExtractStation_3A_AntPost_S6() { - // Apex of the chest or Sternum & Carina. - StartNewStep("[Station 3A] Inf/Sup limits with Sternum and Carina"); + StartNewStep("[Station 3A] Post limits around S6"); - // Get Carina position (has been determined in Station8) - m_CarinaZ = GetAFDB()->GetDouble("CarinaZ"); + // Consider Aorta + MaskImagePointer Aorta = GetAFDB()->template GetImage ("Aorta"); + + // Limits the support to S6 + MaskImagePointer S6 = m_ListOfSupports["S6"]; + Aorta = clitk::ResizeImageLike(Aorta, S6, GetBackgroundValue()); + + // Extend 1cm anteriorly + MaskImagePointType radius; // in mm + radius[0] = 10; + radius[1] = 10; + radius[2] = 0; // required + Aorta = clitk::Dilate(Aorta, radius, GetBackgroundValue(), GetForegroundValue(), false); - // Get Sternum and search for the upper position - MaskImagePointer Sternum = GetAFDB()->template GetImage("Sternum"); + // Not Post to + m_Working_Support = + clitk::SliceBySliceRelativePosition(m_Working_Support, Aorta, 2, + GetFuzzyThreshold("3A", "Aorta"), + "NotPostTo", true, + Aorta->GetSpacing()[0], false, false); + + StopCurrentStep(m_Working_Support); + m_ListOfStations["3A"] = m_Working_Support; +} +//-------------------------------------------------------------------- - // Search most sup point - MaskImagePointType ps = Sternum->GetOrigin(); // initialise to avoid warning - clitk::FindExtremaPointInAGivenDirection(Sternum, GetBackgroundValue(), 2, false, ps); - double m_SternumZ = ps[2]+Sternum->GetSpacing()[2]; // One more slice, because it is below this point - //* Crop support : - m_Working_Support = - clitk::CropImageAlongOneAxis(m_Working_Support, 2, - m_CarinaZ, m_SternumZ, true, - GetBackgroundValue()); +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +ExtractStation_3A_AntPost_Superiorly() +{ + StartNewStep("[Station 3A] Post limits superiorly"); + /* + MaskImagePointer BrachioCephalicVein = GetAFDB()->template GetImage ("BrachioCephalicVein"); + MaskImagePointer BrachioCephalicArtery = GetAFDB()->template GetImage ("BrachioCephalicArtery"); + MaskImagePointer CommonCarotidArteryLeft = GetAFDB()->template GetImage ("CommonCarotidArteryLeft"); + MaskImagePointer CommonCarotidArteryRight = GetAFDB()->template GetImage ("CommonCarotidArteryRight"); + MaskImagePointer SubclavianArteryLeft = GetAFDB()->template GetImage ("SubclavianArteryLeft"); + MaskImagePointer SubclavianArteryRight = GetAFDB()->template GetImage ("SubclavianArteryRight"); + + // Not Post to +#define RP(STRUCTURE) \ + m_Working_Support = \ + clitk::SliceBySliceRelativePosition(m_Working_Support, STRUCTURE, 2, \ + 0.5, \ + "NotPostTo", true, \ + STRUCTURE->GetSpacing()[0], false, false); + + // RP(BrachioCephalicVein); + RP(BrachioCephalicArtery); + RP(CommonCarotidArteryRight); + RP(CommonCarotidArteryLeft); + RP(SubclavianArteryRight); + RP(SubclavianArteryLeft); + */ + + // Get or compute the binary mask that separate Ant/Post part + // according to vessels + MaskImagePointer binarizedContour = FindAntPostVessels2(); + binarizedContour = clitk::ResizeImageLike(binarizedContour, + m_Working_Support, + GetBackgroundValue()); + + // remove from support + typedef clitk::BooleanOperatorLabelImageFilter 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(m_Working_Support); m_ListOfStations["3A"] = m_Working_Support; } @@ -65,19 +234,86 @@ ExtractStation_3A_SI_Limits() template void clitk::ExtractLymphStationsFilter:: -ExtractStation_3A_Ant_Limits() +ExtractStation_3A_Remove_Structures() { - StartNewStep("[Station 3A] Ant limits with Sternum"); + Remove_Structures("3A", "Aorta"); + Remove_Structures("3A", "SubclavianArteryLeft"); + Remove_Structures("3A", "SubclavianArteryRight"); + Remove_Structures("3A", "Thyroid"); + Remove_Structures("3A", "CommonCarotidArteryLeft"); + Remove_Structures("3A", "CommonCarotidArteryRight"); + Remove_Structures("3A", "BrachioCephalicArtery"); + // 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 ("BrachioCephalicVein"); + BrachioCephalicVein = clitk::ResizeImageLike(BrachioCephalicVein, + m_Working_Support, + GetBackgroundValue()); + std::vector slices; + std::vector slices_BCV; + clitk::ExtractSlices(m_Working_Support, 2, slices); + clitk::ExtractSlices(BrachioCephalicVein, 2, slices_BCV); + for(uint i=0; i(slices_BCV[i], 0, true, 1); + + // Compute centroids + std::vector centroids; + ComputeCentroids(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(slices_BCV[i], + slices_BCV[i], + label, + GetBackgroundValue(), + true); + } + + // Remove from the support + clitk::AndNot(slices[i], slices_BCV[i], GetBackgroundValue()); + } + + // Joint + m_Working_Support = clitk::JoinSlices(slices, m_Working_Support, 2); - // Get Sternum, keep posterior part. - MaskImagePointer Sternum = GetAFDB()->template GetImage("Sternum"); - m_Working_Support = - clitk::SliceBySliceRelativePosition(m_Working_Support, Sternum, 2, - 0.5, "PostTo", - false, 3, true, false); StopCurrentStep(m_Working_Support); m_ListOfStations["3A"] = m_Working_Support; } //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +ExtractStation_3A_PostToBones() +{ + StartNewStep("[Station 3A] Post limits with bones"); + + // limits with bones + MaskImagePointer Bones = GetAFDB()->template GetImage("Bones"); + m_Working_Support = + clitk::SliceBySliceRelativePosition(m_Working_Support, Bones, 2, + GetFuzzyThreshold("3A", "Bones"), "NotAntTo", + false, 3, true, false); + + StopCurrentStep(m_Working_Support); + m_ListOfStations["3A"] = m_Working_Support; +} +//-------------------------------------------------------------------- +