From d30d301ddbebb5f290f8d9c0104dc6448ea531e1 Mon Sep 17 00:00:00 2001 From: dsarrut Date: Tue, 15 Feb 2011 11:29:37 +0000 Subject: [PATCH] correct options scheme --- segmentation/clitkExtractAirwaysTreeInfo.cxx | 1 - .../clitkExtractAirwaysTreeInfoFilter.h | 4 - .../clitkExtractAirwaysTreeInfoFilter.txx | 20 +- ...clitkExtractAirwaysTreeInfoGenericFilter.h | 2 + ...itkExtractAirwaysTreeInfoGenericFilter.txx | 18 +- segmentation/clitkExtractBones.ggo | 1 + segmentation/clitkExtractBonesFilter.h | 23 +- segmentation/clitkExtractBonesFilter.txx | 37 +- segmentation/clitkExtractBonesGenericFilter.h | 2 + .../clitkExtractBonesGenericFilter.txx | 46 ++- segmentation/clitkExtractLung.cxx | 1 - segmentation/clitkExtractLung.ggo | 25 +- segmentation/clitkExtractLungFilter.h | 59 ++- segmentation/clitkExtractLungFilter.txx | 343 +++++++++--------- segmentation/clitkExtractLungGenericFilter.h | 2 + .../clitkExtractLungGenericFilter.txx | 53 ++- segmentation/clitkExtractLymphStation_4RL.txx | 302 ++++++++++++--- segmentation/clitkExtractLymphStation_7.txx | 224 +++++------- segmentation/clitkExtractLymphStations.ggo | 8 +- .../clitkExtractLymphStationsFilter.h | 61 +++- .../clitkExtractLymphStationsFilter.txx | 178 +++++++-- .../clitkExtractLymphStationsGenericFilter.h | 6 +- ...clitkExtractLymphStationsGenericFilter.txx | 43 ++- segmentation/clitkExtractMediastinum.ggo | 1 + segmentation/clitkExtractMediastinumFilter.h | 24 +- .../clitkExtractMediastinumFilter.txx | 274 +++++--------- .../clitkExtractMediastinumGenericFilter.h | 6 + .../clitkExtractMediastinumGenericFilter.txx | 53 ++- segmentation/clitkExtractPatientFilter.h | 19 - segmentation/clitkExtractPatientFilter.txx | 43 +-- 30 files changed, 1060 insertions(+), 819 deletions(-) diff --git a/segmentation/clitkExtractAirwaysTreeInfo.cxx b/segmentation/clitkExtractAirwaysTreeInfo.cxx index 8e3fee4..35f00c5 100644 --- a/segmentation/clitkExtractAirwaysTreeInfo.cxx +++ b/segmentation/clitkExtractAirwaysTreeInfo.cxx @@ -23,7 +23,6 @@ //-------------------------------------------------------------------- int main(int argc, char * argv[]) { - // Init command line GGO(clitkExtractAirwaysTreeInfo, args_info); CLITK_INIT; diff --git a/segmentation/clitkExtractAirwaysTreeInfoFilter.h b/segmentation/clitkExtractAirwaysTreeInfoFilter.h index 2b4d8fc..bf133e9 100644 --- a/segmentation/clitkExtractAirwaysTreeInfoFilter.h +++ b/segmentation/clitkExtractAirwaysTreeInfoFilter.h @@ -131,10 +131,6 @@ namespace clitk { /** Connect inputs */ void SetInput(const ImageType * image); - // Set all options at a time - template - void SetArgsInfo(ArgsInfoType arg); - // Background / Foreground itkGetConstMacro(BackgroundValue, ImagePixelType); itkGetConstMacro(ForegroundValue, ImagePixelType); diff --git a/segmentation/clitkExtractAirwaysTreeInfoFilter.txx b/segmentation/clitkExtractAirwaysTreeInfoFilter.txx index da32e04..46a801d 100644 --- a/segmentation/clitkExtractAirwaysTreeInfoFilter.txx +++ b/segmentation/clitkExtractAirwaysTreeInfoFilter.txx @@ -62,22 +62,6 @@ SetInput(const ImageType * image) //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractAirwaysTreeInfoFilter:: -SetArgsInfo(ArgsInfoType mArgsInfo) -{ - SetVerboseOption_GGO(mArgsInfo); - SetVerboseStep_GGO(mArgsInfo); - SetWriteStep_GGO(mArgsInfo); - SetVerboseWarningOff_GGO(mArgsInfo); - SetAFDBFilename_GGO(mArgsInfo); -} -//-------------------------------------------------------------------- - - //-------------------------------------------------------------------- template void @@ -183,7 +167,7 @@ GenerateData() StopCurrentStep(); // Reput FG instead of label in the skeleton image - skeleton = clitk::SetBackground(skeleton, skeleton, label, GetForegroundValue()); + skeleton = clitk::SetBackground(skeleton, skeleton, label, GetForegroundValue(), true); // Debug typename StructuralTreeType::iterator sit = mStructuralSkeletonTree.begin(); @@ -400,7 +384,7 @@ GenerateData() carina_position); // Set and save Carina position - if (GetVerboseStep()) { + if (GetVerboseStepFlag()) { std::cout << "\t Found carina at " << carina_position << " mm" << std::endl; } GetAFDB()->SetPoint3D("carina", carina_position); diff --git a/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.h b/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.h index f730e33..76b19da 100644 --- a/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.h +++ b/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.h @@ -47,6 +47,8 @@ namespace clitk itkTypeMacro(ExtractAirwaysTreeInfoGenericFilter, LightObject); //-------------------------------------------------------------------- + template + void SetOptionsFromArgsInfoToFilter(FilterType * f); void SetArgsInfo(const ArgsInfoType & a); //-------------------------------------------------------------------- diff --git a/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.txx b/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.txx index 3f802fc..208663b 100644 --- a/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.txx +++ b/segmentation/clitkExtractAirwaysTreeInfoGenericFilter.txx @@ -59,6 +59,22 @@ void clitk::ExtractAirwaysTreeInfoGenericFilter::SetArgsInfo(const //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +template +void clitk::ExtractAirwaysTreeInfoGenericFilter:: +SetOptionsFromArgsInfoToFilter(FilterType * f) +{ + f->SetVerboseOptionFlag(mArgsInfo.verboseOption_flag); + f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag); + f->SetWriteStepFlag(mArgsInfo.writeStep_flag); + f->SetVerboseWarningFlag(!mArgsInfo.verboseWarningOff_flag); + if (mArgsInfo.afdb_given) + f->SetAFDBFilename(mArgsInfo.afdb_arg); +} +//-------------------------------------------------------------------- + + //-------------------------------------------------------------------- // Update with the number of dimensions and the pixeltype //-------------------------------------------------------------------- @@ -77,8 +93,8 @@ void clitk::ExtractAirwaysTreeInfoGenericFilter::UpdateWithInputIm this->SetFilterBase(filter); // Set global Options - filter->SetArgsInfo(mArgsInfo); filter->SetInput(input); + SetOptionsFromArgsInfoToFilter(filter); // Go ! filter->Update(); diff --git a/segmentation/clitkExtractBones.ggo b/segmentation/clitkExtractBones.ggo index fa265ef..d7a737c 100644 --- a/segmentation/clitkExtractBones.ggo +++ b/segmentation/clitkExtractBones.ggo @@ -10,6 +10,7 @@ option "verboseStep" - "Verbose each step" flag off option "writeStep" w "Write image at each step" flag off option "verboseOption" - "Display options values" flag off option "verboseWarningOff" - "Do not display warning" flag off +option "verboseMemory" - "Display memory usage" flag off section "I/O" diff --git a/segmentation/clitkExtractBonesFilter.h b/segmentation/clitkExtractBonesFilter.h index 2205ea3..b10ed2f 100644 --- a/segmentation/clitkExtractBonesFilter.h +++ b/segmentation/clitkExtractBonesFilter.h @@ -33,7 +33,8 @@ namespace clitk { //-------------------------------------------------------------------- /* - Extract bony anatomy through thresholding and connected component labelling. + Extract bony anatomy through thresholding and connected component + labelling. */ //-------------------------------------------------------------------- @@ -86,88 +87,68 @@ namespace clitk { /** Connect inputs */ void SetInput(const InputImageType * image); - // Set all options at a time - template - void SetArgsInfo(ArgsInfoType arg); - // Background / Foreground itkGetConstMacro(BackgroundValue, MaskImagePixelType); itkGetConstMacro(ForegroundValue, MaskImagePixelType); itkSetMacro(MinimalComponentSize, int); itkGetConstMacro(MinimalComponentSize, int); - GGO_DefineOption(minSize, SetMinimalComponentSize, int); // Output filename (for AFBD) itkSetMacro(OutputBonesFilename, std::string); itkGetMacro(OutputBonesFilename, std::string); - GGO_DefineOption(output, SetOutputBonesFilename, std::string); // Step 0 itkBooleanMacro(InitialSmoothing); itkSetMacro(InitialSmoothing, bool); itkGetMacro(InitialSmoothing, bool); - GGO_DefineOption_Flag(smooth, SetInitialSmoothing); itkSetMacro(SmoothingConductanceParameter, double); itkGetConstMacro(SmoothingConductanceParameter, double); - GGO_DefineOption(cond, SetSmoothingConductanceParameter, double); itkSetMacro(SmoothingNumberOfIterations, int); itkGetConstMacro(SmoothingNumberOfIterations, int); - GGO_DefineOption(iter, SetSmoothingNumberOfIterations, int); itkSetMacro(SmoothingTimeStep, double); itkGetConstMacro(SmoothingTimeStep, double); - GGO_DefineOption(time, SetSmoothingTimeStep, double); itkSetMacro(SmoothingUseImageSpacing, bool); itkGetConstMacro(SmoothingUseImageSpacing, bool); itkBooleanMacro(SmoothingUseImageSpacing); - GGO_DefineOption_Flag(spacing, SetSmoothingUseImageSpacing); // Step 1 itkSetMacro(UpperThreshold1, InputImagePixelType); itkGetMacro(UpperThreshold1, InputImagePixelType); - GGO_DefineOption(upper1, SetUpperThreshold1, InputImagePixelType); itkSetMacro(LowerThreshold1, InputImagePixelType); itkGetMacro(LowerThreshold1, InputImagePixelType); - GGO_DefineOption(lower1, SetLowerThreshold1, InputImagePixelType); itkSetMacro(FullConnectivity, bool); itkGetConstMacro(FullConnectivity, bool); itkBooleanMacro(FullConnectivity); - GGO_DefineOption_Flag(full, SetFullConnectivity); // Step 2 itkSetMacro(UpperThreshold2, InputImagePixelType); itkGetMacro(UpperThreshold2, InputImagePixelType); - GGO_DefineOption(upper2, SetUpperThreshold2, InputImagePixelType); itkSetMacro(LowerThreshold2, InputImagePixelType); itkGetMacro(LowerThreshold2, InputImagePixelType); - GGO_DefineOption(lower2, SetLowerThreshold2, InputImagePixelType); itkSetMacro(Radius2, InputImageSizeType); itkGetConstMacro(Radius2, InputImageSizeType); - GGO_DefineOption_Vector(radius2, SetRadius2, InputImageSizeType, ImageDimension, true); itkSetMacro(SampleRate2, int); itkGetConstMacro(SampleRate2, int); - GGO_DefineOption(sampleRate2, SetSampleRate2, int); // Step fill holes itkSetMacro(FillHoles, bool); itkGetConstMacro(FillHoles, bool); itkBooleanMacro(FillHoles); - GGO_DefineOption_Flag(doNotFillHoles, SetFillHoles); // Step Auto Crop itkSetMacro(AutoCrop, bool); itkGetConstMacro(AutoCrop, bool); itkBooleanMacro(AutoCrop); - GGO_DefineOption_Flag(noAutoCrop, SetAutoCrop); protected: ExtractBonesFilter(); diff --git a/segmentation/clitkExtractBonesFilter.txx b/segmentation/clitkExtractBonesFilter.txx index 7f59e92..baa8fe8 100644 --- a/segmentation/clitkExtractBonesFilter.txx +++ b/segmentation/clitkExtractBonesFilter.txx @@ -80,41 +80,6 @@ SetInput(const TInputImageType * image) //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractBonesFilter:: -SetArgsInfo(ArgsInfoType mArgsInfo) -{ - SetVerboseOption_GGO(mArgsInfo); - SetVerboseStep_GGO(mArgsInfo); - SetWriteStep_GGO(mArgsInfo); - SetVerboseWarningOff_GGO(mArgsInfo); - - SetAFDBFilename_GGO(mArgsInfo); - SetOutputBonesFilename_GGO(mArgsInfo); - - SetInitialSmoothing_GGO(mArgsInfo); - SetSmoothingConductanceParameter_GGO(mArgsInfo); - SetSmoothingNumberOfIterations_GGO(mArgsInfo); - SetSmoothingTimeStep_GGO(mArgsInfo); - SetSmoothingUseImageSpacing_GGO(mArgsInfo); - - SetMinimalComponentSize_GGO(mArgsInfo); - SetUpperThreshold1_GGO(mArgsInfo); - SetLowerThreshold1_GGO(mArgsInfo); - SetFullConnectivity_GGO(mArgsInfo); - - SetUpperThreshold2_GGO(mArgsInfo); - SetLowerThreshold2_GGO(mArgsInfo); - SetRadius2_GGO(mArgsInfo); - SetSampleRate2_GGO(mArgsInfo); - SetAutoCrop_GGO(mArgsInfo); - SetFillHoles_GGO(mArgsInfo); -} -//-------------------------------------------------------------------- - //-------------------------------------------------------------------- template @@ -313,7 +278,7 @@ GenerateData() { this->GraftOutput(caster->GetOutput()); // Store image filenames into AFDB - GetAFDB()->SetImageFilename("bones", this->GetOutputBonesFilename()); + GetAFDB()->SetImageFilename("Bones", this->GetOutputBonesFilename()); WriteAFDB(); return; } diff --git a/segmentation/clitkExtractBonesGenericFilter.h b/segmentation/clitkExtractBonesGenericFilter.h index 9093ac6..2d81e15 100644 --- a/segmentation/clitkExtractBonesGenericFilter.h +++ b/segmentation/clitkExtractBonesGenericFilter.h @@ -48,6 +48,8 @@ namespace clitk //-------------------------------------------------------------------- void SetArgsInfo(const ArgsInfoType & a); + template + void SetOptionsFromArgsInfoToFilter(FilterType * f); //-------------------------------------------------------------------- // Main function called each time the filter is updated diff --git a/segmentation/clitkExtractBonesGenericFilter.txx b/segmentation/clitkExtractBonesGenericFilter.txx index 285842e..9c99893 100644 --- a/segmentation/clitkExtractBonesGenericFilter.txx +++ b/segmentation/clitkExtractBonesGenericFilter.txx @@ -58,6 +58,50 @@ void clitk::ExtractBonesGenericFilter::SetArgsInfo(const ArgsInfoT //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +template +void clitk::ExtractBonesGenericFilter:: +SetOptionsFromArgsInfoToFilter(FilterType * f) +{ + f->SetVerboseOptionFlag(mArgsInfo.verboseOption_flag); + f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag); + f->SetWriteStepFlag(mArgsInfo.writeStep_flag); + f->SetVerboseWarningFlag(!mArgsInfo.verboseWarningOff_flag); + f->SetVerboseMemoryFlag(mArgsInfo.verboseMemory_flag); + + if (mArgsInfo.afdb_given) + f->SetAFDBFilename(mArgsInfo.afdb_arg); + + f->SetOutputBonesFilename(mArgsInfo.output_arg); + + f->SetInitialSmoothing(mArgsInfo.smooth_flag); + f->SetSmoothingConductanceParameter(mArgsInfo.cond_arg); + f->SetSmoothingNumberOfIterations(mArgsInfo.iter_arg); + f->SetSmoothingTimeStep(mArgsInfo.time_arg); + f->SetSmoothingUseImageSpacing(mArgsInfo.spacing_flag); + + f->SetMinimalComponentSize(mArgsInfo.minSize_arg); + f->SetUpperThreshold1(mArgsInfo.upper1_arg); + f->SetLowerThreshold1(mArgsInfo.lower1_arg); + f->SetFullConnectivity(mArgsInfo.full_flag); + + f->SetUpperThreshold2(mArgsInfo.upper2_arg); + f->SetLowerThreshold2(mArgsInfo.lower2_arg); + + typename FilterType::InputImageSizeType s; + if (mArgsInfo.radius2_given) { + ConvertOptionMacro(mArgsInfo.radius2, s, 3, false); + f->SetRadius2(s); + } + + f->SetSampleRate2(mArgsInfo.sampleRate2_arg); + f->SetAutoCrop(!mArgsInfo.noAutoCrop_flag); + f->SetFillHoles(!mArgsInfo.doNotFillHoles_flag); +} +//-------------------------------------------------------------------- + + //-------------------------------------------------------------------- // Update with the number of dimensions and the pixeltype //-------------------------------------------------------------------- @@ -76,8 +120,8 @@ void clitk::ExtractBonesGenericFilter::UpdateWithInputImageType() typename FilterType::Pointer filter = FilterType::New(); // Set global Options - filter->SetArgsInfo(mArgsInfo); filter->SetInput(input); + SetOptionsFromArgsInfoToFilter(filter); // Go ! filter->Update(); diff --git a/segmentation/clitkExtractLung.cxx b/segmentation/clitkExtractLung.cxx index 6f92ef0..b39f621 100644 --- a/segmentation/clitkExtractLung.cxx +++ b/segmentation/clitkExtractLung.cxx @@ -23,7 +23,6 @@ //-------------------------------------------------------------------- int main(int argc, char * argv[]) { - // Init command line GGO(clitkExtractLung, args_info); CLITK_INIT; diff --git a/segmentation/clitkExtractLung.ggo b/segmentation/clitkExtractLung.ggo index ddc1fe7..1865086 100644 --- a/segmentation/clitkExtractLung.ggo +++ b/segmentation/clitkExtractLung.ggo @@ -10,6 +10,7 @@ option "verboseStep" - "Verbose each step" flag off option "writeStep" w "Write image at each step" flag off option "verboseOption" - "Display options values" flag off option "verboseWarningOff" - "Do not display warning" flag off +option "verboseMemory" - "Display memory usage" flag off section "I/O" @@ -20,12 +21,12 @@ option "outputTrachea" t "Output trachea mask filename" string no section "Step 1 : Air remove" -option "lower" - "Initial lower threshold" double no -option "upper" - "Initial upper threshold" double no default="-300" +option "lower" - "Initial lower threshold" int no +option "upper" - "Initial upper threshold" int no default="-300" option "minSize" - "Minimum component size in voxels" int no default="100" -option "remove1" - "Labels not to keep in air mask (lungs)" int no multiple default="2" -option "firstKeep1" - "First label to keep" int no default="1" -option "lastKeep1" - "Last label to keep" int no +#option "remove1" - "Labels not to keep in air mask (lungs)" int no multiple default="2" +#option "firstKeep1" - "First label to keep" int no default="1" +#option "lastKeep1" - "Last label to keep" int no section "Step 2 : find trachea" @@ -34,20 +35,22 @@ option "upperThresholdForTrachea" - "Initial upper threshold for trachea" do option "multiplierForTrachea" - "Multiplier for the region growing" double no default="5" option "thresholdStepSizeForTrachea" - "Threshold step size" int no default="64" option "seed" - "Index of the trachea seed point" int no multiple +option "doNotCheckTracheaVolume" - "If set, do not check the trachea volume" flag off +option "verboseRG" - "Verbose RegionGrowing" flag off section "Step 3 : auto extract lung" option "bins" - "Number of bins to use for the Otsu thresholding" int no default="500" -option "remove2" - "Labels not to keep in air mask (gas)" int no multiple -option "firstKeep2" - "First label to keep" int no default="1" -option "lastKeep2" - "Last label to keep" int no +# option "remove2" - "Labels not to keep in air mask (gas)" int no multiple +# option "firstKeep2" - "First label to keep" int no default="1" +# option "lastKeep2" - "Last label to keep" int no section "Step 4 : remove trachea" option "radius" - "Radius for dilation" int no default="1" -option "remove3" - "Labels not to keep in lungs mask (trachea)" int no multiple -option "firstKeep3" - "First label to keep" int no default="1" -option "lastKeep3" - "Last label to keep" int no default="2" +# option "remove3" - "Labels not to keep in lungs mask (trachea)" int no multiple +# option "firstKeep3" - "First label to keep" int no default="1" +# option "lastKeep3" - "Last label to keep" int no default="2" section "Step 5 : [optional] openclose" option "openclose" - "Perform an OpenClose operation" flag off diff --git a/segmentation/clitkExtractLungFilter.h b/segmentation/clitkExtractLungFilter.h index 3183457..76e2640 100644 --- a/segmentation/clitkExtractLungFilter.h +++ b/segmentation/clitkExtractLungFilter.h @@ -97,7 +97,8 @@ namespace clitk { typedef typename MaskImageType::PointType MaskImagePointType; itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); - typedef int InternalPixelType; + // typedef int InternalPixelType; + typedef uchar InternalPixelType; typedef itk::Image InternalImageType; typedef typename InternalImageType::Pointer InternalImagePointer; typedef typename InternalImageType::IndexType InternalIndexType; @@ -107,20 +108,13 @@ namespace clitk { void SetInput(const ImageType * image); itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType); itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType); - GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType); // Output filename (for AFBD) itkSetMacro(OutputLungFilename, std::string); itkGetMacro(OutputLungFilename, std::string); - GGO_DefineOption(output, SetOutputLungFilename, std::string); itkSetMacro(OutputTracheaFilename, std::string); itkGetMacro(OutputTracheaFilename, std::string); - GGO_DefineOption(outputTrachea, SetOutputTracheaFilename, std::string); - - // Set all options at a time - template - void SetArgsInfo(ArgsInfoType arg); // Get output (only availabe after update !) typename MaskImageType::Pointer GetTracheaImage() { return trachea; } @@ -132,78 +126,70 @@ namespace clitk { // For common segmentation processes itkSetMacro(MinimalComponentSize, int); itkGetConstMacro(MinimalComponentSize, int); - GGO_DefineOption(minSize, SetMinimalComponentSize, int); // Step 1 options RemoveAir itkSetMacro(UpperThreshold, InputImagePixelType); itkGetConstMacro(UpperThreshold, InputImagePixelType); - GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType); itkSetMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int); itkGetConstMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int); - GGO_DefineOption(skipslices, SetNumberOfSlicesToSkipBeforeSearchingSeed, int); itkSetMacro(LowerThreshold, InputImagePixelType); itkGetConstMacro(LowerThreshold, InputImagePixelType); itkSetMacro(UseLowerThreshold, bool); itkGetConstMacro(UseLowerThreshold, bool); itkBooleanMacro(UseLowerThreshold); - GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold); void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; } itkGetConstMacro(LabelizeParameters1, LabelParamType*); - GGO_DefineOption_LabelParam(1, SetLabelizeParameters1, LabelParamType); // Step 2 options FindTrachea itkSetMacro(UpperThresholdForTrachea, InputImagePixelType); itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType); - GGO_DefineOption(upperThresholdForTrachea, SetUpperThresholdForTrachea, InputImagePixelType); itkSetMacro(MultiplierForTrachea, double); itkGetConstMacro(MultiplierForTrachea, double); - GGO_DefineOption(multiplierForTrachea, SetMultiplierForTrachea, double); itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType); itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType); - GGO_DefineOption(thresholdStepSizeForTrachea, SetThresholdStepSizeForTrachea, InputImagePixelType); void AddSeed(InternalIndexType s); std::vector & GetSeeds() { return m_Seeds; } - GGO_DefineOption_Vector(seed, AddSeed, InternalIndexType, ImageType::ImageDimension, true); + + itkSetMacro(TracheaVolumeMustBeCheckedFlag, bool); + itkGetConstMacro(TracheaVolumeMustBeCheckedFlag, bool); + itkBooleanMacro(TracheaVolumeMustBeCheckedFlag); + + itkSetMacro(VerboseRegionGrowingFlag, bool); + itkGetConstMacro(VerboseRegionGrowingFlag, bool); + itkBooleanMacro(VerboseRegionGrowingFlag); // Step 3 options ExtractLung itkSetMacro(NumberOfHistogramBins, int); itkGetConstMacro(NumberOfHistogramBins, int); - GGO_DefineOption(bins, SetNumberOfHistogramBins, int); void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; } itkGetConstMacro(LabelizeParameters2, LabelParamType*); - GGO_DefineOption_LabelParam(2, SetLabelizeParameters2, LabelParamType); // Step 4 options RemoveTrachea itkSetMacro(RadiusForTrachea, int); itkGetConstMacro(RadiusForTrachea, int); - GGO_DefineOption(radius, SetRadiusForTrachea, int); void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; } itkGetConstMacro(LabelizeParameters3, LabelParamType*); - GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType); // Step 5 final openclose - itkSetMacro(OpenClose, bool); - itkGetConstMacro(OpenClose, bool); - itkBooleanMacro(OpenClose); - GGO_DefineOption_Flag(openclose, SetOpenClose); + itkSetMacro(OpenCloseFlag, bool); + itkGetConstMacro(OpenCloseFlag, bool); + itkBooleanMacro(OpenCloseFlag); itkSetMacro(OpenCloseRadius, int); itkGetConstMacro(OpenCloseRadius, int); - GGO_DefineOption(opencloseRadius, SetOpenCloseRadius, int); // Step 6 fill holes - itkSetMacro(FillHoles, bool); - itkGetConstMacro(FillHoles, bool); - itkBooleanMacro(FillHoles); - GGO_DefineOption_Flag(doNotFillHoles, SetFillHoles); + itkSetMacro(FillHolesFlag, bool); + itkGetConstMacro(FillHolesFlag, bool); + itkBooleanMacro(FillHolesFlag); protected: ExtractLungFilter(); @@ -211,14 +197,12 @@ namespace clitk { // Main members InputImageConstPointer input; - MaskImageConstPointer patient; + MaskImagePointer patient; InputImagePointer working_input; std::string m_OutputLungFilename; std::string m_OutputTracheaFilename; - typename InternalImageType::Pointer working_image; - typename InternalImageType::Pointer trachea_tmp; + MaskImagePointer working_mask; MaskImagePointer trachea; - MaskImagePointer output; unsigned int m_MaxSeedNumber; // Global options @@ -241,6 +225,8 @@ namespace clitk { double m_MultiplierForTrachea; std::vector m_Seeds; int m_NumberOfSlicesToSkipBeforeSearchingSeed; + bool m_TracheaVolumeMustBeCheckedFlag; + bool m_VerboseRegionGrowingFlag; // Step 3 int m_NumberOfHistogramBins; @@ -251,15 +237,16 @@ namespace clitk { LabelParamType* m_LabelizeParameters3; // Step 5 - bool m_OpenClose; + bool m_OpenCloseFlag; int m_OpenCloseRadius; // Step 6 - bool m_FillHoles; + bool m_FillHolesFlag; InputImageSizeType m_FillHolesDirections; // Main functions virtual void GenerateOutputInformation(); + virtual void GenerateInputRequestedRegion(); virtual void GenerateData(); // Functions for trachea extraction diff --git a/segmentation/clitkExtractLungFilter.txx b/segmentation/clitkExtractLungFilter.txx index 52276f4..fda0203 100644 --- a/segmentation/clitkExtractLungFilter.txx +++ b/segmentation/clitkExtractLungFilter.txx @@ -26,6 +26,7 @@ #include "clitkAutoCropFilter.h" #include "clitkCropLikeImageFilter.h" #include "clitkFillMaskFilter.h" +#include "clitkMemoryUsage.h" // itk #include "itkBinaryThresholdImageFilter.h" @@ -54,6 +55,7 @@ ExtractLungFilter(): SetBackgroundValue(0); // Must be zero SetForegroundValue(1); SetMinimalComponentSize(100); + VerboseRegionGrowingFlagOff(); // Step 1 default values SetUpperThreshold(-300); @@ -70,6 +72,7 @@ ExtractLungFilter(): SetMultiplierForTrachea(5); SetThresholdStepSizeForTrachea(64); SetNumberOfSlicesToSkipBeforeSearchingSeed(0); + TracheaVolumeMustBeCheckedFlagOn(); // Step 3 default values SetNumberOfHistogramBins(500); @@ -88,11 +91,11 @@ ExtractLungFilter(): SetLabelizeParameters3(p3); // Step 5 - OpenCloseOff(); + OpenCloseFlagOff(); SetOpenCloseRadius(1); // Step 6 - FillHolesOn(); + FillHolesFlagOn(); } //-------------------------------------------------------------------- @@ -119,58 +122,13 @@ AddSeed(InternalIndexType s) //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractLungFilter:: -SetArgsInfo(ArgsInfoType mArgsInfo) -{ - SetVerboseOption_GGO(mArgsInfo); - SetVerboseStep_GGO(mArgsInfo); - SetWriteStep_GGO(mArgsInfo); - SetVerboseWarningOff_GGO(mArgsInfo); - - SetAFDBFilename_GGO(mArgsInfo); - SetOutputLungFilename_GGO(mArgsInfo); - SetOutputTracheaFilename_GGO(mArgsInfo); - - SetUpperThreshold_GGO(mArgsInfo); - SetLowerThreshold_GGO(mArgsInfo); - SetNumberOfSlicesToSkipBeforeSearchingSeed_GGO(mArgsInfo); - SetLabelizeParameters1_GGO(mArgsInfo); - if (!mArgsInfo.remove1_given) { - GetLabelizeParameters1()->AddLabelToRemove(2); - if (GetVerboseOption()) VerboseOption("remove1", 2); - } - - SetUpperThresholdForTrachea_GGO(mArgsInfo); - SetMultiplierForTrachea_GGO(mArgsInfo); - SetThresholdStepSizeForTrachea_GGO(mArgsInfo); - AddSeed_GGO(mArgsInfo); - - SetMinimalComponentSize_GGO(mArgsInfo); - - SetNumberOfHistogramBins_GGO(mArgsInfo); - SetLabelizeParameters2_GGO(mArgsInfo); - - SetRadiusForTrachea_GGO(mArgsInfo); - SetLabelizeParameters3_GGO(mArgsInfo); - - SetOpenCloseRadius_GGO(mArgsInfo); - SetOpenClose_GGO(mArgsInfo); - - SetFillHoles_GGO(mArgsInfo); -} -//-------------------------------------------------------------------- - - //-------------------------------------------------------------------- template void clitk::ExtractLungFilter:: GenerateOutputInformation() { + clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK Superclass::GenerateOutputInformation(); // Read DB @@ -178,27 +136,41 @@ GenerateOutputInformation() // Get input pointers input = dynamic_cast(itk::ProcessObject::GetInput(0)); - patient = GetAFDB()->template GetImage ("patient"); + patient = GetAFDB()->template GetImage ("Patient"); + PrintMemory(GetVerboseMemoryFlag(), "After reading patient"); // OK //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Crop input like patient image (must have the same spacing) - StartNewStep("Crop input image to 'patient' extends"); + // It copy the input if the same are the same + StartNewStep("Copy and crop input image to 'patient' extends"); typedef clitk::CropLikeImageFilter CropImageFilter; typename CropImageFilter::Pointer cropFilter = CropImageFilter::New(); + // cropFilter->ReleaseDataFlagOn(); // NO=seg fault !! cropFilter->SetInput(input); cropFilter->SetCropLikeImage(patient); cropFilter->Update(); working_input = cropFilter->GetOutput(); - DD(working_input->GetLargestPossibleRegion()); + // cropFilter->Delete(); // NO !!!! if yes, sg fault, Cropfilter is buggy !?? StopCurrentStep(working_input); - + PrintMemory(GetVerboseMemoryFlag(), "After crop"); // OK, slightly more than a copy of input + //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Set background to initial image"); working_input = SetBackground - (working_input, patient, GetPatientMaskBackgroundValue(), -1000); + (working_input, patient, GetPatientMaskBackgroundValue(), -1000, true); StopCurrentStep(working_input); + PrintMemory(GetVerboseMemoryFlag(), "After set bg"); // OK, additional mem = 0 + + /* + // We do not need patient mask anymore, release memory + GetAFDB()->template ReleaseImage("Patient"); + DD(patient->GetReferenceCount()); + PrintMemory(GetVerboseMemoryFlag(), "After delete patient"); // OK, additional mem = 0 + patient->Delete(); + PrintMemory(GetVerboseMemoryFlag(), "After delete patient"); // OK, additional mem = 0 + */ //-------------------------------------------------------------------- //-------------------------------------------------------------------- @@ -210,33 +182,41 @@ GenerateOutputInformation() } } // Threshold to get air - typedef itk::BinaryThresholdImageFilter InputBinarizeFilterType; - typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New(); + typedef itk::BinaryThresholdImageFilter InputBinarizeFilterType; + typename InputBinarizeFilterType::Pointer binarizeFilter = InputBinarizeFilterType::New(); binarizeFilter->SetInput(working_input); if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(m_LowerThreshold); + // binarizeFilter->CanRunInPlace() is false binarizeFilter->SetUpperThreshold(m_UpperThreshold); - binarizeFilter ->SetInsideValue(this->GetForegroundValue()); - binarizeFilter ->SetOutsideValue(this->GetBackgroundValue()); + binarizeFilter->SetInsideValue(this->GetForegroundValue()); + binarizeFilter->SetOutsideValue(this->GetBackgroundValue()); binarizeFilter->Update(); - working_image = binarizeFilter->GetOutput(); - - // Labelize and keep right labels - working_image = Labelize(working_image, GetBackgroundValue(), true, GetMinimalComponentSize()); + working_mask = binarizeFilter->GetOutput(); + PrintMemory(GetVerboseMemoryFlag(), "After Binarizefilter"); // OK, additional mem is one mask image - working_image = RemoveLabels - (working_image, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove()); + // Labelize and keep right labels + working_mask = + Labelize + (working_mask, GetBackgroundValue(), true, GetMinimalComponentSize()); + PrintMemory(GetVerboseMemoryFlag(), "After Labelize"); // BUG ? additional mem around 1 time the input ? + + working_mask = RemoveLabels + (working_mask, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove()); + PrintMemory(GetVerboseMemoryFlag(), "After RemoveLabels"); // OK additional mem = 0 - typename InternalImageType::Pointer air = KeepLabels - (working_image, + working_mask = KeepLabels + (working_mask, GetBackgroundValue(), GetForegroundValue(), GetLabelizeParameters1()->GetFirstKeep(), GetLabelizeParameters1()->GetLastKeep(), GetLabelizeParameters1()->GetUseLastKeep()); + PrintMemory(GetVerboseMemoryFlag(), "After KeepLabels to create the 'air'"); // Set Air to BG - working_input = SetBackground - (working_input, air, this->GetForegroundValue(), this->GetBackgroundValue()); + working_input = SetBackground + (working_input, working_mask, this->GetForegroundValue(), this->GetBackgroundValue(), true); + PrintMemory(GetVerboseMemoryFlag(), "After SetBackground"); // End StopCurrentStep(working_input); @@ -245,29 +225,31 @@ GenerateOutputInformation() //-------------------------------------------------------------------- StartNewStep("Search for the trachea"); SearchForTrachea(); + PrintMemory(GetVerboseMemoryFlag(), "After SearchForTrachea"); //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Extract the lung with Otsu filter"); // Automated Otsu thresholding and relabeling - typedef itk::OtsuThresholdImageFilter OtsuThresholdImageFilterType; + typedef itk::OtsuThresholdImageFilter OtsuThresholdImageFilterType; typename OtsuThresholdImageFilterType::Pointer otsuFilter=OtsuThresholdImageFilterType::New(); otsuFilter->SetInput(working_input); otsuFilter->SetNumberOfHistogramBins(GetNumberOfHistogramBins()); otsuFilter->SetInsideValue(this->GetForegroundValue()); otsuFilter->SetOutsideValue(this->GetBackgroundValue()); otsuFilter->Update(); - working_image = otsuFilter->GetOutput(); + working_mask = otsuFilter->GetOutput(); // Set output - StopCurrentStep(working_image); + StopCurrentStep(working_mask); + PrintMemory(GetVerboseMemoryFlag(), "After Otsufilter"); //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Select labels"); // Keep right labels - working_image = LabelizeAndSelectLabels - (working_image, + working_mask = LabelizeAndSelectLabels + (working_mask, GetBackgroundValue(), GetForegroundValue(), false, @@ -275,15 +257,17 @@ GenerateOutputInformation() GetLabelizeParameters2()); // Set output - StopCurrentStep(working_image); + StopCurrentStep(working_mask); + PrintMemory(GetVerboseMemoryFlag(), "After LabelizeAndSelectLabels"); //-------------------------------------------------------------------- //-------------------------------------------------------------------- if (m_Seeds.size() != 0) { // if ==0 ->no trachea found StartNewStep("Remove the trachea"); // Set the trachea - working_image = SetBackground - (working_image, trachea_tmp, 1, -1); + working_mask = SetBackground + (working_mask, trachea, 1, -1, true); + PrintMemory(GetVerboseMemoryFlag(), "After SetBackground"); // Dilate the trachea static const unsigned int Dim = ImageType::ImageDimension; @@ -291,27 +275,28 @@ GenerateOutputInformation() KernelType structuringElement; structuringElement.SetRadius(GetRadiusForTrachea()); structuringElement.CreateStructuringElement(); - typedef clitk::ConditionalBinaryDilateImageFilter ConditionalBinaryDilateImageFilterType; + typedef clitk::ConditionalBinaryDilateImageFilter ConditionalBinaryDilateImageFilterType; typename ConditionalBinaryDilateImageFilterType::Pointer dilateFilter = ConditionalBinaryDilateImageFilterType::New(); dilateFilter->SetBoundaryToForeground(false); dilateFilter->SetKernel(structuringElement); dilateFilter->SetBackgroundValue (1); dilateFilter->SetForegroundValue (-1); - dilateFilter->SetInput (working_image); + dilateFilter->SetInput (working_mask); dilateFilter->Update(); - working_image = dilateFilter->GetOutput(); + working_mask = dilateFilter->GetOutput(); + PrintMemory(GetVerboseMemoryFlag(), "After dilate"); // Set trachea with dilatation - trachea_tmp = SetBackground - (trachea_tmp, working_image, -1, this->GetForegroundValue()); + trachea = SetBackground + (trachea, working_mask, -1, this->GetForegroundValue(), true); // Remove the trachea - working_image = SetBackground - (working_image, working_image, -1, this->GetBackgroundValue()); + working_mask = SetBackground + (working_mask, working_mask, -1, this->GetBackgroundValue(), true); // Label - working_image = LabelizeAndSelectLabels - (working_image, + working_mask = LabelizeAndSelectLabels + (working_mask, GetBackgroundValue(), GetForegroundValue(), false, @@ -319,41 +304,33 @@ GenerateOutputInformation() GetLabelizeParameters3()); // Set output - StopCurrentStep(working_image); + StopCurrentStep(working_mask); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- - typedef clitk::AutoCropFilter AutoCropFilterType; - typename AutoCropFilterType::Pointer autocropFilter = AutoCropFilterType::New(); + PrintMemory(GetVerboseMemoryFlag(), "before autocropfilter"); if (m_Seeds.size() != 0) { // if ==0 ->no trachea found - StartNewStep("Cropping trachea"); - autocropFilter->SetInput(trachea_tmp); - autocropFilter->Update(); // Needed - typedef itk::CastImageFilter CastImageFilterType; - typename CastImageFilterType::Pointer caster= CastImageFilterType::New(); - caster->SetInput(autocropFilter->GetOutput()); - caster->Update(); - trachea = caster->GetOutput(); + trachea = clitk::AutoCrop(trachea, GetBackgroundValue()); StopCurrentStep(trachea); + PrintMemory(GetVerboseMemoryFlag(), "after delete trachea"); } + PrintMemory(GetVerboseMemoryFlag(), "after delete trachea"); //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Cropping lung"); - typename AutoCropFilterType::Pointer autocropFilter2 = AutoCropFilterType::New(); // Needed to reset pipeline - autocropFilter2->SetInput(working_image); - autocropFilter2->Update(); - working_image = autocropFilter2->GetOutput(); - DD(working_image->GetLargestPossibleRegion()); - StopCurrentStep(working_image); + PrintMemory(GetVerboseMemoryFlag(), "Before Autocropfilter"); + working_mask = clitk::AutoCrop(working_mask, GetBackgroundValue()); + StopCurrentStep(working_mask); //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Final OpenClose - if (GetOpenClose()) { + if (GetOpenCloseFlag()) { StartNewStep("Open/Close"); - + PrintMemory(GetVerboseMemoryFlag(), "Before OpenClose"); + // Structuring element typedef itk::BinaryBallStructuringElement KernelType; KernelType structuringElement; @@ -361,66 +338,72 @@ GenerateOutputInformation() structuringElement.CreateStructuringElement(); // Open - typedef itk::BinaryMorphologicalOpeningImageFilter OpenFilterType; + typedef itk::BinaryMorphologicalOpeningImageFilter OpenFilterType; typename OpenFilterType::Pointer openFilter = OpenFilterType::New(); - openFilter->SetInput(working_image); + openFilter->SetInput(working_mask); openFilter->SetBackgroundValue(GetBackgroundValue()); openFilter->SetForegroundValue(GetForegroundValue()); openFilter->SetKernel(structuringElement); // Close - typedef itk::BinaryMorphologicalClosingImageFilter CloseFilterType; + typedef itk::BinaryMorphologicalClosingImageFilter CloseFilterType; typename CloseFilterType::Pointer closeFilter = CloseFilterType::New(); closeFilter->SetInput(openFilter->GetOutput()); closeFilter->SetSafeBorder(true); closeFilter->SetForegroundValue(GetForegroundValue()); closeFilter->SetKernel(structuringElement); closeFilter->Update(); - working_image = closeFilter->GetOutput(); + working_mask = closeFilter->GetOutput(); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- // Fill Lungs - if (GetFillHoles()) { + if (GetFillHolesFlag()) { StartNewStep("Fill Holes"); - typedef clitk::FillMaskFilter FillMaskFilterType; + PrintMemory(GetVerboseMemoryFlag(), "Before Fill Holes"); + typedef clitk::FillMaskFilter FillMaskFilterType; typename FillMaskFilterType::Pointer fillMaskFilter = FillMaskFilterType::New(); - fillMaskFilter->SetInput(working_image); + fillMaskFilter->SetInput(working_mask); fillMaskFilter->AddDirection(2); //fillMaskFilter->AddDirection(1); fillMaskFilter->Update(); - working_image = fillMaskFilter->GetOutput(); - StopCurrentStep(working_image); + working_mask = fillMaskFilter->GetOutput(); + StopCurrentStep(working_mask); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- StartNewStep("Separate Left/Right lungs"); + PrintMemory(GetVerboseMemoryFlag(), "Before Separate"); // Initial label - working_image = Labelize(working_image, - GetBackgroundValue(), - false, - GetMinimalComponentSize()); + working_mask = Labelize(working_mask, + GetBackgroundValue(), + false, + GetMinimalComponentSize()); + + PrintMemory(GetVerboseMemoryFlag(), "After Labelize"); // Count the labels - typedef itk::StatisticsImageFilter StatisticsImageFilterType; + typedef itk::StatisticsImageFilter StatisticsImageFilterType; typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New(); - statisticsImageFilter->SetInput(working_image); + statisticsImageFilter->SetInput(working_mask); statisticsImageFilter->Update(); unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum(); - working_image = statisticsImageFilter->GetOutput(); + working_mask = statisticsImageFilter->GetOutput(); + + DD(initialNumberOfLabels); + PrintMemory(GetVerboseMemoryFlag(), "After count label"); // Decompose the first label static const unsigned int Dim = ImageType::ImageDimension; if (initialNumberOfLabels<2) { - DD(initialNumberOfLabels); // Structuring element radius typename ImageType::SizeType radius; for (unsigned int i=0;i DecomposeAndReconstructFilterType; + typedef clitk::DecomposeAndReconstructImageFilter DecomposeAndReconstructFilterType; typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New(); - decomposeAndReconstructFilter->SetInput(working_image); + decomposeAndReconstructFilter->SetInput(working_mask); decomposeAndReconstructFilter->SetVerbose(true); decomposeAndReconstructFilter->SetRadius(radius); decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2); @@ -431,29 +414,37 @@ GenerateOutputInformation() decomposeAndReconstructFilter->SetFullyConnected(true); decomposeAndReconstructFilter->SetNumberOfNewLabels(1); decomposeAndReconstructFilter->Update(); - working_image = decomposeAndReconstructFilter->GetOutput(); + working_mask = decomposeAndReconstructFilter->GetOutput(); } + PrintMemory(GetVerboseMemoryFlag(), "After decomposeAndReconstructFilter"); // Retain labels ('1' is largset lung, so right. '2' is left) - typedef itk::ThresholdImageFilter ThresholdImageFilterType; + typedef itk::ThresholdImageFilter ThresholdImageFilterType; typename ThresholdImageFilterType::Pointer thresholdFilter = ThresholdImageFilterType::New(); - thresholdFilter->SetInput(working_image); + thresholdFilter->SetInput(working_mask); thresholdFilter->ThresholdAbove(2); thresholdFilter->SetOutsideValue(this->GetBackgroundValue()); thresholdFilter->Update(); - working_image = thresholdFilter->GetOutput(); - StopCurrentStep (working_image); - - // Final Cast - StartNewStep("Cast the lung mask"); - typedef itk::CastImageFilter CastImageFilterType; - typename CastImageFilterType::Pointer caster= CastImageFilterType::New(); - caster->SetInput(working_image); - caster->Update(); - output = caster->GetOutput(); + working_mask = thresholdFilter->GetOutput(); + StopCurrentStep (working_mask); + PrintMemory(GetVerboseMemoryFlag(), "After Thresholdfilter"); // Update output info - this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion()); + // output = working_mask; + //this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion()); + + // this->GetOutput(0)->SetRegions(working_mask->GetLargestPossibleRegion()); + +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLungFilter:: +GenerateInputRequestedRegion() { + // DD("GenerateInputRequestedRegion (nothing?)"); } //-------------------------------------------------------------------- @@ -465,10 +456,11 @@ clitk::ExtractLungFilter:: GenerateData() { // Set the output - this->GraftOutput(output); // not SetNthOutput + // this->GraftOutput(output); // not SetNthOutput + this->GraftOutput(working_mask); // not SetNthOutput // Store image filenames into AFDB - GetAFDB()->SetImageFilename("lungs", this->GetOutputLungFilename()); - GetAFDB()->SetImageFilename("trachea", this->GetOutputTracheaFilename()); + GetAFDB()->SetImageFilename("Lungs", this->GetOutputLungFilename()); + GetAFDB()->SetImageFilename("Trachea", this->GetOutputTracheaFilename()); WriteAFDB(); } //-------------------------------------------------------------------- @@ -507,7 +499,7 @@ SearchForTracheaSeed(int skip) // if we do not found : restart stop = (m_Seeds.size() != 0); if (!stop) { - if (GetVerboseStep()) { + if (GetVerboseStepFlag()) { std::cout << "\t No seed found this time. I skip some slices and restart." << std::endl; } if (skip > 0.5 * working_input->GetLargestPossibleRegion().GetSize()[2]) { @@ -517,6 +509,10 @@ SearchForTracheaSeed(int skip) } skip += 5; } + else { + // DD(m_Seeds[0]); + // DD(m_Seeds.size()); + } } } return (m_Seeds.size() != 0); @@ -531,10 +527,10 @@ clitk::ExtractLungFilter:: TracheaRegionGrowing() { // Explosion controlled region growing - typedef clitk::ExplosionControlledThresholdConnectedImageFilter ImageFilterType; + PrintMemory(GetVerboseMemoryFlag(), "Before ExplosionControlledThresholdConnectedImageFilter"); + typedef clitk::ExplosionControlledThresholdConnectedImageFilter ImageFilterType; typename ImageFilterType::Pointer f= ImageFilterType::New(); f->SetInput(working_input); - f->SetVerbose(false); f->SetLower(-2000); f->SetUpper(GetUpperThresholdForTrachea()); f->SetMinimumLowerThreshold(-2000); @@ -547,24 +543,25 @@ TracheaRegionGrowing() f->SetMultiplier(GetMultiplierForTrachea()); f->SetThresholdStepSize(GetThresholdStepSizeForTrachea()); f->SetMinimumThresholdStepSize(1); - f->VerboseOn(); + f->SetVerbose(GetVerboseRegionGrowingFlag()); for(unsigned int i=0; iAddSeed(m_Seeds[i]); // DD(m_Seeds[i]); } f->Update(); - - writeImage(f->GetOutput(), "trg.mhd"); - + PrintMemory(GetVerboseMemoryFlag(), "After RG update"); + // take first (main) connected component - trachea_tmp = Labelize(f->GetOutput(), - GetBackgroundValue(), - true, - GetMinimalComponentSize()); - trachea_tmp = KeepLabels(trachea_tmp, + trachea = Labelize(f->GetOutput(), + GetBackgroundValue(), + true, + 1000);//GetMinimalComponentSize()); + PrintMemory(GetVerboseMemoryFlag(), "After Labelize"); + trachea = KeepLabels(trachea, GetBackgroundValue(), GetForegroundValue(), 1, 1, false); + PrintMemory(GetVerboseMemoryFlag(), "After KeepLabels"); } //-------------------------------------------------------------------- @@ -576,7 +573,7 @@ clitk::ExtractLungFilter:: ComputeTracheaVolume() { typedef itk::ImageRegionConstIterator IteratorType; - IteratorType iter(trachea_tmp, trachea_tmp->GetLargestPossibleRegion()); + IteratorType iter(trachea, trachea->GetLargestPossibleRegion()); iter.GoToBegin(); double volume = 0.0; while (!iter.IsAtEnd()) { @@ -584,7 +581,7 @@ ComputeTracheaVolume() ++iter; } - double voxelsize = trachea_tmp->GetSpacing()[0]*trachea_tmp->GetSpacing()[1]*trachea_tmp->GetSpacing()[2]; + double voxelsize = trachea->GetSpacing()[0]*trachea->GetSpacing()[1]*trachea->GetSpacing()[2]; return volume*voxelsize; } //-------------------------------------------------------------------- @@ -611,30 +608,38 @@ SearchForTrachea() if (stop) { TracheaRegionGrowing(); volume = ComputeTracheaVolume()/1000; // assume mm3, so divide by 1000 to get cc - if ((volume > 10) && (volume < 55 )) { // it is ok - // Typical volume 22.59 cm 3 (± 7.69 cm 3 ) [ Leader 2004 ] - if (GetVerboseStep()) { - std::cout << "\t Found trachea with volume " << volume << " cc." << std::endl; - } - stop = true; + if (GetWriteStepFlag()) { + writeImage(trachea, "step-trachea-"+toString(skip)+".mhd"); + } + if (GetTracheaVolumeMustBeCheckedFlag()) { + if ((volume > 10) && (volume < 65 )) { // depend on image size ... + // Typical volume 22.59 cm 3 (± 7.69 cm 3 ) [ Leader 2004 ] + if (GetVerboseStepFlag()) { + std::cout << "\t Found trachea with volume " << volume << " cc." << std::endl; + } + stop = true; + } + else { + if (GetVerboseStepFlag()) { + std::cout << "\t The volume of the trachea (" << volume + << " cc) seems not correct. I skip some slices (" << skip << ") and restart to find seeds." + << std::endl; + } + skip += 5; + stop = false; + // empty the list of seed + m_Seeds.clear(); + } } else { - if (GetVerboseStep()) { - std::cout << "\t The volume of the trachea (" << volume - << " cc) seems not correct. I skip some slices (" << skip << ") and restart to find seeds." - << std::endl; - } - skip += 5; - stop = false; - // empty the list of seed - m_Seeds.clear(); + stop = true; } } } if (volume != 0.0) { // Set output - StopCurrentStep(trachea_tmp); + StopCurrentStep(trachea); } else { // Trachea not found this->SetWarning("* WARNING * No seed found for trachea."); diff --git a/segmentation/clitkExtractLungGenericFilter.h b/segmentation/clitkExtractLungGenericFilter.h index bc7b581..6ca0d1b 100644 --- a/segmentation/clitkExtractLungGenericFilter.h +++ b/segmentation/clitkExtractLungGenericFilter.h @@ -48,6 +48,8 @@ namespace clitk //-------------------------------------------------------------------- void SetArgsInfo(const ArgsInfoType & a); + template + void SetOptionsFromArgsInfoToFilter(FilterType * f); //-------------------------------------------------------------------- // Main function called each time the filter is updated diff --git a/segmentation/clitkExtractLungGenericFilter.txx b/segmentation/clitkExtractLungGenericFilter.txx index 64e7fb8..9aa0343 100644 --- a/segmentation/clitkExtractLungGenericFilter.txx +++ b/segmentation/clitkExtractLungGenericFilter.txx @@ -60,6 +60,57 @@ void clitk::ExtractLungGenericFilter::SetArgsInfo(const ArgsInfoTy //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +template +void clitk::ExtractLungGenericFilter:: +SetOptionsFromArgsInfoToFilter(FilterType * f) +{ + //f->SetVerboseFlag(mArgsInfo.verbose_flag); + f->SetVerboseOptionFlag(mArgsInfo.verboseOption_flag); + f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag); + f->SetWriteStepFlag(mArgsInfo.writeStep_flag); + f->SetVerboseWarningFlag(!mArgsInfo.verboseWarningOff_flag); + f->SetVerboseMemoryFlag(mArgsInfo.verboseMemory_flag); + + if (mArgsInfo.afdb_given) + f->SetAFDBFilename(mArgsInfo.afdb_arg); + f->SetOutputLungFilename(mArgsInfo.output_arg); + f->SetOutputTracheaFilename(mArgsInfo.outputTrachea_arg); + + f->SetUpperThreshold(mArgsInfo.upper_arg); + f->SetLowerThreshold(mArgsInfo.lower_arg); + + f->SetNumberOfSlicesToSkipBeforeSearchingSeed(mArgsInfo.skipslices_arg); + + f->SetTracheaVolumeMustBeCheckedFlag(!mArgsInfo.doNotCheckTracheaVolume_flag); + f->SetVerboseRegionGrowingFlag(mArgsInfo.verboseRG_flag); + + f->SetUpperThresholdForTrachea(mArgsInfo.upperThresholdForTrachea_arg); + f->SetMultiplierForTrachea(mArgsInfo.multiplierForTrachea_arg); + f->SetThresholdStepSizeForTrachea(mArgsInfo.thresholdStepSizeForTrachea_arg); + + typename FilterType::InputImageIndexType s; + if (mArgsInfo.seed_given) { + ConvertOptionMacro(mArgsInfo.seed, s, 3, false); + f->AddSeed(s); + } + + f->SetMinimalComponentSize(mArgsInfo.minSize_arg); + f->SetNumberOfHistogramBins(mArgsInfo.bins_arg); + f->SetRadiusForTrachea(mArgsInfo.radius_arg); + + f->SetOpenCloseFlag(mArgsInfo.openclose_flag); + f->SetOpenCloseRadius(mArgsInfo.opencloseRadius_arg); + + if (mArgsInfo.doNotFillHoles_given) + f->SetFillHolesFlag(false); + else + f->SetFillHolesFlag(true); +} +//-------------------------------------------------------------------- + + //-------------------------------------------------------------------- // Update with the number of dimensions and the pixeltype //-------------------------------------------------------------------- @@ -81,8 +132,8 @@ void clitk::ExtractLungGenericFilter::UpdateWithInputImageType() this->SetFilterBase(filter); // Set global Options - filter->SetArgsInfo(mArgsInfo); filter->SetInput(input); + SetOptionsFromArgsInfoToFilter(filter); // Go ! filter->Update(); diff --git a/segmentation/clitkExtractLymphStation_4RL.txx b/segmentation/clitkExtractLymphStation_4RL.txx index a4478a6..462ae9d 100644 --- a/segmentation/clitkExtractLymphStation_4RL.txx +++ b/segmentation/clitkExtractLymphStation_4RL.txx @@ -4,9 +4,33 @@ void clitk::ExtractLymphStationsFilter:: ExtractStation_4RL_SI_Limits() { + + /* + Station 4R: right lower paratracheal nodes From superior to + inferior, the delineation of Station 4R starts at the top of the + aortic arch (Fig. 2D) and ends at the upper lobe bronchus or where the + right pulmonary artery crosses the midline of the mediastinum + (Fig. 3E,F). On the left side, Station 4R is defined by the midline of + the trachea (Fig. 2D). On the right side, it is contained within the + pleural envelope in the upper part, medial to the superior vena cava + and the arch of the azygos vein in the intermediate section (Fig. 2I + and 3A,B) and the right upper lobe pulmonary vein in its very caudal + part. Anteriorly, it is limited most supe- riorly by the right + brachiocephalic vein (Fig. 2D–H), fol- lowed by the superior vena cava + and the arch or ascending section of the aorta (Figs. 2I and 3A–E). In + between the superior vena cava and the aorta, we recommend delineating + Station 4R so that it extends halfway between the two vessels where it + will contact Station 3A or 6 (Figs. 2H,I and 3A–D). Posteriorly, + Station 4R is defined at its superior extent by an imaginary horizontal + line running along the posterior wall of the trachea + (Fig. 2E). Inferiorly, it remains anterior to the right main stem + bronchus, filling the soft- tissue space between the vessels. + */ + + StartNewStep("[Station 4R]Inf/Sup mediastinum limits with aortic arch/upperLBronchus"); /* SupInf limits : - - top of aortic arch - - ends at the upper lobe bronchus or where the right pulmonary artery crosses the midline of the mediastinum + - top of aortic arch + - ends at the upper lobe bronchus or where the right pulmonary artery crosses the midline of the mediastinum */ // Local variables @@ -15,24 +39,21 @@ ExtractStation_4RL_SI_Limits() double m_RightPulmoArteyrCrossesMidMediastinumZPositionInMM; // Get Inputs - m_TopOfAorticArchInMM = GetAFDB()->GetPoint3D("topOfAorticArch", 2); + m_TopOfAorticArchInMM = GetAFDB()->GetPoint3D("TopOfAorticArch", 2); DD(m_TopOfAorticArchInMM); - m_UpperLobeBronchusZPositionInMM = GetAFDB()->GetPoint3D("rightUpperLobeBronchus", 2); + m_UpperLobeBronchusZPositionInMM = GetAFDB()->GetPoint3D("RightUpperLobeBronchus", 2); DD(m_UpperLobeBronchusZPositionInMM); - m_RightPulmoArteyrCrossesMidMediastinumZPositionInMM = GetAFDB()->GetPoint3D("rightPulmoArteryCrossesMidMediastinum", 2); + m_RightPulmoArteyrCrossesMidMediastinumZPositionInMM = GetAFDB()->GetPoint3D("RightPulmoArteryCrossesMidMediastinum", 2); DD(m_RightPulmoArteyrCrossesMidMediastinumZPositionInMM); /* Crop support */ - StartNewStep("Inf/Sup mediastinum limits with aortic arch/upperLBronchus"); double inf = std::max(m_UpperLobeBronchusZPositionInMM, m_RightPulmoArteyrCrossesMidMediastinumZPositionInMM); m_Working_Support = - clitk::CropImageAlongOneAxis(m_Support, 2, + clitk::CropImageAlongOneAxis(m_Mediastinum, 2, inf, m_TopOfAorticArchInMM, true, GetBackgroundValue()); StopCurrentStep(m_Working_Support); - - m_Station4RL = m_Working_Support; } //-------------------------------------------------------------------- @@ -51,50 +72,249 @@ ExtractStation_4RL_LR_Limits() // - very caudal part : right upper lobe pulmonary vein" // AAV ?? - // Constraint at right from the SVC - MaskImagePointer svc = GetAFDB()->template GetImage("SVC"); - typedef clitk::AddRelativePositionConstraintToLabelImageFilter RelPosFilterType; - typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); - relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - relPosFilter->VerboseStepOff(); - relPosFilter->WriteStepOff(); - relPosFilter->SetInput(m_Working_Support); - relPosFilter->SetInputObject(svc); - relPosFilter->SetOrientationType(RelPosFilterType::RightTo); - relPosFilter->SetIntermediateSpacing(2); - relPosFilter->SetFuzzyThreshold(0.3); - relPosFilter->Update(); - m_Working_Support = relPosFilter->GetOutput(); - m_Station4RL = m_Working_Support; - // Left -> midline of the trachea // slice by slice, find X coord of 2D centroid (?) // check with previous line in order to not move too fast + + + // ---------------------------------------------------------- + StartNewStep("[Station 4R] Left limits with midline of trachea "); - // skeleton ? -> need path description ? follow from slice to slice - // OR CENTROID at each slice ? - - // Crop trachea - // Extract list of slice from trachea - // Loop slice -> Get centroid crop along line (BB limit) -> two supports + /* + Two possible approaches + 1) use trachea skeleton (clitkExtractAirwaysTreeInfo) + -> but need to analyse the tree to remove "false" bifurcation + -> need to track from top to bottom, with each bronchus + -> how to stay on the main path ? + + 2) analyse slice by slice the trachea, labelize and take the first + or two first connected components -> find centroids. + -> not really "smooth" when bronchus slicing lead to "splated" region + + ==> we choose 2 + */ // Crop the trachea like the current support + MaskImagePointer Trachea = GetAFDB()->template GetImage ("Trachea"); MaskImagePointer crop_trachea = - clitk::ResizeImageLike(m_Trachea, m_Working_Support, GetBackgroundValue()); + clitk::ResizeImageLike(Trachea, m_Working_Support, GetBackgroundValue()); writeImage(crop_trachea, "croptrachea.mhd"); // Extract all the slices - typedef clitk::ExtractSliceFilter ExtractSliceFilterType; - typedef typename ExtractSliceFilterType::SliceType SliceType; - typename ExtractSliceFilterType::Pointer - extractSliceFilter = ExtractSliceFilterType::New(); - extractSliceFilter->SetInput(crop_trachea); - extractSliceFilter->SetDirection(2); - extractSliceFilter->Update(); - std::vector trachea_slices; - extractSliceFilter->GetOutputSlices(trachea_slices); + std::vector bronchi_slices; + clitk::ExtractSlices(crop_trachea, 2, bronchi_slices); + + // List of midpoints + std::vector midpoints; + + // Add mid points below carina, from foot to head + for(uint i=0; iGetLargestPossibleRegion().GetIndex(); + for(uint i=0; i<3; i++) { + p[i] += Trachea->GetLargestPossibleRegion().GetSize()[i]; + } + MaskImagePointType q; + Trachea->TransformIndexToPhysicalPoint(p, q); + double maxZ = q[2]; + double m_CarinaZ = GetAFDB()->GetPoint3D("Carina", 2); + MaskImagePointer m_above_carina = + clitk::CropImageAlongOneAxis(Trachea, 2, + m_CarinaZ, + maxZ, true, + GetBackgroundValue()); + writeImage(m_above_carina, "above.mhd"); + + // Extract all the slices + std::vector trachea_slices; + clitk::ExtractSlices(m_above_carina, 2, trachea_slices); + + // Find centroid of the trachea in each slice + std::vector points; + typedef typename MaskSliceType::PointType SlicePointType; + SlicePointType previous; + // Start from patient top (head) + for(uint i=0; i(trachea_slices[i], GetBackgroundValue(), true, 10); + // Get centroid + std::vector c; + clitk::ComputeCentroids(trachea_slices[i], GetBackgroundValue(), c); + // Keep first one (first connected component label) and convert to 3D + MaskImagePointType p; + p[2] = m_above_carina->GetOrigin()[2] + i*m_above_carina->GetSpacing()[2]; + p[0] = c[1][0]; + p[1] = c[1][1]; + midpoints.push_back(p); + } + + // DEBUG POINTS + std::ofstream osp; + openFileForWriting(osp, "mp.txt"); + osp << "LANDMARKS1" << std::endl; + for(uint i=0; i(m_Working_Support); + m_RightSupport = clitk::NewImageLike(m_Working_Support); + + // Loop on current support, slice by slice + typedef itk::ImageSliceIteratorWithIndex SliceIteratorType; + SliceIteratorType iter = SliceIteratorType(m_Working_Support, + m_Working_Support->GetLargestPossibleRegion()); + SliceIteratorType iterL = SliceIteratorType(m_LeftSupport, + m_LeftSupport->GetLargestPossibleRegion()); + SliceIteratorType iterR = SliceIteratorType(m_RightSupport, + m_RightSupport->GetLargestPossibleRegion()); + iter.SetFirstDirection(0); + iter.SetSecondDirection(1); + iter.GoToBegin(); + iterL.SetFirstDirection(0); + iterL.SetSecondDirection(1); + iterL.GoToBegin(); + iterR.SetFirstDirection(0); + iterR.SetSecondDirection(1); + iterR.GoToBegin(); + + int slice=0; + // Assert starting of image has the same Z than first midpoints + while (midpoints[slice][2] != m_Working_Support->GetOrigin()[2]) { + slice++; + if ((uint)slice >= midpoints.size()) { + clitkExceptionMacro("Bug while searching for first midpoint to use"); + } + } + + // Start loop + while (!iter.IsAtEnd()) { + ImageIndexType index; + m_Working_Support->TransformPhysicalPointToIndex(midpoints[slice], index); + while (!iter.IsAtEndOfSlice()) { + // convert into index + while (!iter.IsAtEndOfLine()) { + // if indexcourant (m_LeftSupport, GetBackgroundValue()); + m_RightSupport = clitk::AutoCrop(m_RightSupport, GetBackgroundValue()); + writeImage(m_LeftSupport, "lsac.mhd"); + writeImage(m_RightSupport, "rsac.mhd"); + + StopCurrentStep(m_RightSupport); + + // ------------------------------------------------------------------------- + // Constraint at right from the SVC. Must be after MidTrachea limits + // (if not, bronchus can be split, midposition is false) + StartNewStep("[Station 4R] R limits with SVC "); + MaskImagePointer svc = GetAFDB()->template GetImage("SVC"); + typedef clitk::AddRelativePositionConstraintToLabelImageFilter RelPosFilterType; + typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); + /* relPosFilter->SetVerboseStep(false); + relPosFilter->SetInput(m_RightSupport); // only right here ... + relPosFilter->SetInputObject(svc); + relPosFilter->SetOrientationType(RelPosFilterType::RightTo); + relPosFilter->SetIntermediateSpacing(2); + relPosFilter->SetFuzzyThreshold(0.3); + relPosFilter->Update(); + m_RightSupport = relPosFilter->GetOutput(); + */ + /* + ==> TODO RIGHT TO MEDIAL TO SVC : + get centroid, cut in X direction to get medial + ==> REDO OPERATOR to find extrma points ? + centroid or skeleton ? + + */ + + relPosFilter = RelPosFilterType::New(); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->SetInput(m_RightSupport); // only right here ... + relPosFilter->SetInputObject(svc); + relPosFilter->AddOrientationType(RelPosFilterType::AntTo); + relPosFilter->InverseOrientationFlagOn(); + relPosFilter->SetIntermediateSpacing(2); // this is important to put it low + relPosFilter->SetFuzzyThreshold(0.6); + relPosFilter->Update(); + m_RightSupport = relPosFilter->GetOutput(); + + // AutoCrop + m_RightSupport = clitk::AutoCrop(m_RightSupport, GetBackgroundValue()); } //-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +ExtractStation_4RL_AP_Limits() +{ + + /* + post of S4R + - sup part -> cut line post wall trachea + - inf part (where ???) -> remains anterior to the right main stem bronchus + ==> bo + */ + + // Post (not Ant) to Aorta + MaskImagePointer aorta = GetAFDB()->template GetImage("Aorta"); + // Crop according to current support + aorta = clitk::ResizeImageLike(aorta, m_RightSupport, GetBackgroundValue()); + typedef clitk::AddRelativePositionConstraintToLabelImageFilter RelPosFilterType; + typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); + relPosFilter = RelPosFilterType::New(); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->SetInput(m_RightSupport); // only right here ... + relPosFilter->SetInputObject(aorta); + relPosFilter->AddOrientationType(RelPosFilterType::PostTo); + // relPosFilter->NotFlagOn(); + relPosFilter->SetIntermediateSpacing(2); // this is important to put it low + relPosFilter->SetFuzzyThreshold(0.6); + relPosFilter->Update(); + m_RightSupport = relPosFilter->GetOutput(); + + m_ListOfStations["4R"] = m_RightSupport; + StopCurrentStep(m_RightSupport); + + // POST -> horizontal lines bronchus --> points dectection in S7 to store. +} +//-------------------------------------------------------------------- + diff --git a/segmentation/clitkExtractLymphStation_7.txx b/segmentation/clitkExtractLymphStation_7.txx index e1cbe1f..278efc8 100644 --- a/segmentation/clitkExtractLymphStation_7.txx +++ b/segmentation/clitkExtractLymphStation_7.txx @@ -1,46 +1,41 @@ + //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7_SI_Limits() { - // Local variables - double m_CarinaZPositionInMM; - double m_MiddleLobeBronchusZPositionInMM; - // Get Inputs - m_Trachea = GetAFDB()->template GetImage ("trachea"); - m_CarinaZPositionInMM = GetAFDB()->GetPoint3D("carina", 2); - DD(m_CarinaZPositionInMM); - m_MiddleLobeBronchusZPositionInMM = GetAFDB()->GetPoint3D("rightMiddleLobeBronchus", 2); - DD(m_MiddleLobeBronchusZPositionInMM); + MaskImagePointer Trachea = GetAFDB()->template GetImage ("Trachea"); + double m_CarinaZ = GetAFDB()->GetPoint3D("Carina", 2); + DD(m_CarinaZ); + double m_OriginOfRightMiddleLobeBronchusZ = GetAFDB()->GetPoint3D("OriginOfRightMiddleLobeBronchus", 2); + DD(m_OriginOfRightMiddleLobeBronchusZ); /* Crop support : - Superior limit = carina - Inferior limit = origin right middle lobe bronchus */ - StartNewStep("Inf/Sup mediastinum limits with carina/bronchus"); + Superior limit = carina + Inferior limit = origin right middle lobe bronchus */ + StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/bronchus"); m_Working_Support = - clitk::CropImageAlongOneAxis(m_Support, 2, - m_MiddleLobeBronchusZPositionInMM, - m_CarinaZPositionInMM, true, + clitk::CropImageAlongOneAxis(m_Working_Support, 2, + m_OriginOfRightMiddleLobeBronchusZ, + m_CarinaZ, true, GetBackgroundValue()); - StopCurrentStep(m_Working_Support); - /* Crop trachea - Superior limit = carina - Inferior limit = origin right middle lobe bronchus*/ - StartNewStep("Inf/Sup trachea limits with carina/bronchus"); + Superior limit = carina + Inferior limit = origin right middle lobe bronchus*/ m_working_trachea = - clitk::CropImageAlongOneAxis(m_Trachea, 2, - m_MiddleLobeBronchusZPositionInMM, - m_CarinaZPositionInMM, true, + clitk::CropImageAlongOneAxis(Trachea, 2, + m_OriginOfRightMiddleLobeBronchusZ, + m_CarinaZ, true, GetBackgroundValue()); - StopCurrentStep(m_working_trachea); - m_Station7 = m_Working_Support; + StopCurrentStep(m_Working_Support); + m_ListOfStations["7"] = m_Working_Support; } //-------------------------------------------------------------------- + //-------------------------------------------------------------------- template void @@ -49,13 +44,14 @@ ExtractStation_7_RL_Limits() { // ---------------------------------------------------------------- // Separate trachea in two CCL - StartNewStep("Separate trachea under carina"); + StartNewStep("[Station7] Separate trachea under carina"); // Labelize and consider two main labels m_working_trachea = Labelize(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 + // 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 SliceIteratorType; SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion()); iter.SetFirstDirection(0); @@ -64,7 +60,6 @@ ExtractStation_7_RL_Limits() int maxLabel=0; while (!iter.IsAtReverseEndOfSlice()) { while (!iter.IsAtReverseEndOfLine()) { - // DD(iter.GetIndex()); if (iter.Get() > maxLabel) maxLabel = iter.Get(); --iter; } @@ -74,70 +69,65 @@ ExtractStation_7_RL_Limits() clitkExceptionMacro("First slice form Carina does not seems to seperate the two main bronchus. Abort"); } - // 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 ImageToMapFilterType; - typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); - typedef itk::ShapeLabelMapFilter 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(); + // Compute 3D centroids of both parts to identify the left from the + // right bronchus + std::vector c; + clitk::ComputeCentroids(m_working_trachea, GetBackgroundValue(), c); + ImagePointType C1 = c[1]; + ImagePointType C2 = c[2]; ImagePixelType leftLabel; ImagePixelType rightLabel; if (C1[0] < C2[0]) { leftLabel = 1; rightLabel = 2; } else { leftLabel = 2; rightLabel = 1; } - DD(leftLabel); - DD(rightLabel); StopCurrentStep(m_working_trachea); //----------------------------------------------------- - StartNewStep("Left limits with bronchus (slice by slice)"); // Select LeftLabel (set one label to Backgroundvalue) m_LeftBronchus = SetBackground(m_working_trachea, m_working_trachea, - rightLabel, GetBackgroundValue()); + rightLabel, GetBackgroundValue(), false); m_RightBronchus = SetBackground(m_working_trachea, m_working_trachea, - leftLabel, GetBackgroundValue()); - writeImage(m_LeftBronchus, "left.mhd"); - writeImage(m_RightBronchus, "right.mhd"); + leftLabel, GetBackgroundValue(), false); + StartNewStep("[Station7] Limits with bronchus (slice by slice) : RightTo left bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, GetFuzzyThreshold(), "RightTo", true, 4); + + StartNewStep("[Station7] Limits with bronchus (slice by slice) : LeftTo right bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, GetFuzzyThreshold(), "LeftTo", true, 4); + + StartNewStep("[Station7] Limits with bronchus (slice by slice) : not AntTo left bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, GetFuzzyThreshold(), "AntTo", true, 4, true); // NOT + + StartNewStep("[Station7] Limits with bronchus (slice by slice) : not AntTo right bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, 2, GetFuzzyThreshold(), "AntTo", true, 4, true); + + StartNewStep("[Station7] Limits with bronchus (slice by slice) : not PostTo left bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_LeftBronchus, 2, GetFuzzyThreshold(), "PostTo", true, 4, true); + + StartNewStep("[Station7] Limits with bronchus (slice by slice) : not PostTo right bronchus"); m_Working_Support = clitk::SliceBySliceRelativePosition(m_Working_Support, m_RightBronchus, @@ -155,92 +145,46 @@ void clitk::ExtractLymphStationsFilter:: ExtractStation_7_Posterior_Limits() { - StartNewStep("Posterior limits"); - - // Left Bronchus slices - typedef clitk::ExtractSliceFilter ExtractSliceFilterType; - typedef typename ExtractSliceFilterType::SliceType SliceType; - typename ExtractSliceFilterType::Pointer - extractSliceFilter = ExtractSliceFilterType::New(); - extractSliceFilter->SetInput(m_LeftBronchus); - extractSliceFilter->SetDirection(2); - extractSliceFilter->Update(); - std::vector leftBronchusSlices; - extractSliceFilter->GetOutputSlices(leftBronchusSlices); - - // Right Bronchus slices - extractSliceFilter = ExtractSliceFilterType::New(); - extractSliceFilter->SetInput(m_RightBronchus); - extractSliceFilter->SetDirection(2); - extractSliceFilter->Update(); - std::vector rightBronchusSlices ; - extractSliceFilter->GetOutputSlices(rightBronchusSlices); - - assert(leftBronchusSlices.size() == rightBronchusSlices.size()); - - std::vector leftPoints; - std::vector rightPoints; - for(uint i=0; i(leftBronchusSlices[i], 0, true, 10); - leftBronchusSlices[i] = KeepLabels(leftBronchusSlices[i], - GetBackgroundValue(), - GetForegroundValue(), 1, 1, true); - rightBronchusSlices[i] = Labelize(rightBronchusSlices[i], 0, true, 10); - rightBronchusSlices[i] = KeepLabels(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(leftBronchusSlices[i], - GetBackgroundValue(), - 0, false, a, 0); - // find post most point in left, not far away from rightMost - SliceType::PointType p = - clitk::FindExtremaPointInAGivenDirection(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(rightBronchusSlices[i], - GetBackgroundValue(), - 0, true, a, 0); - // find post most point in left, not far away from leftMost - p = clitk::FindExtremaPointInAGivenDirection(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); - } + StartNewStep("[Station7] Posterior limits -> must be AntTo post wall of the bronchi"); + // 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); // 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 MaskSliceType; + /** ImageDimension constants */ itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); FILTERBASE_INIT; - /** Main options (from ggo) */ - template - void SetArgsInfo(ArgsInfoType & argsinfo); - itkGetConstMacro(BackgroundValue, MaskImagePixelType); itkGetConstMacro(ForegroundValue, MaskImagePixelType); itkSetMacro(BackgroundValue, MaskImagePixelType); itkSetMacro(ForegroundValue, MaskImagePixelType); - + + // Station 8 + itkSetMacro(DistanceMaxToAnteriorPartOfTheSpine, double); + itkGetConstMacro(DistanceMaxToAnteriorPartOfTheSpine, double); + itkSetMacro(EsophagusDiltationForAnt, MaskImagePointType); + itkGetConstMacro(EsophagusDiltationForAnt, MaskImagePointType); + itkSetMacro(EsophagusDiltationForRight, MaskImagePointType); + itkGetConstMacro(EsophagusDiltationForRight, MaskImagePointType); + itkSetMacro(FuzzyThresholdForS8, double); + itkGetConstMacro(FuzzyThresholdForS8, double); + // Station 7 itkSetMacro(FuzzyThreshold, double); itkGetConstMacro(FuzzyThreshold, double); @@ -98,32 +106,58 @@ namespace clitk { virtual void GenerateData(); ImageConstPointer m_Input; - MaskImagePointer m_Support; + MaskImagePointer m_Mediastinum; MaskImagePointer m_Working_Support; - MaskImagePointer m_Output; + std::map m_ListOfStations; MaskImagePixelType m_BackgroundValue; MaskImagePixelType m_ForegroundValue; - // Common - MaskImagePointer m_Trachea; - + // Station 8 + double m_DistanceMaxToAnteriorPartOfTheSpine; + double m_DiaphragmInferiorLimit; + double m_CarinaZ; + double m_OriginOfRightMiddleLobeBronchusZ; + double m_FuzzyThresholdForS8; + MaskImagePointType m_EsophagusDiltationForAnt; + MaskImagePointType m_EsophagusDiltationForRight; + MaskImagePointer EnlargeEsophagusDilatationRadiusInferiorly(MaskImagePointer & eso); + void ExtractStation_8(); + void ExtractStation_8_SI_Limits(); + void ExtractStation_8_AP_Limits(); + void ExtractStation_8_LR_Limits(); + // Station 7 void ExtractStation_7(); void ExtractStation_7_SI_Limits(); void ExtractStation_7_RL_Limits(); - void ExtractStation_7_Posterior_Limits(); + void ExtractStation_7_Posterior_Limits(); std::string m_Station7Filename; MaskImagePointer m_working_trachea; double m_FuzzyThreshold; MaskImagePointer m_LeftBronchus; MaskImagePointer m_RightBronchus; MaskImagePointer m_Station7; - + typedef std::vector ListOfPointsType; + ListOfPointsType m_RightMostInLeftBronchus; + ListOfPointsType m_AntMostInLeftBronchus; + ListOfPointsType m_PostMostInLeftBronchus; + ListOfPointsType m_LeftMostInRightBronchus; + ListOfPointsType m_AntMostInRightBronchus; + ListOfPointsType m_PostMostInRightBronchus; + + void FindExtremaPointsInBronchus(MaskImagePointer input, + int direction, + double distance_max_from_center_point, + ListOfPointsType & LR, + ListOfPointsType & Ant, + ListOfPointsType & Post); // Station 4RL void ExtractStation_4RL(); void ExtractStation_4RL_SI_Limits(); void ExtractStation_4RL_LR_Limits(); - MaskImagePointer m_Station4RL; + void ExtractStation_4RL_AP_Limits(); + MaskImagePointer m_RightSupport; + MaskImagePointer m_LeftSupport; private: ExtractLymphStationsFilter(const Self&); //purposely not implemented @@ -137,6 +171,7 @@ namespace clitk { #ifndef ITK_MANUAL_INSTANTIATION #include "clitkExtractLymphStationsFilter.txx" +#include "clitkExtractLymphStation_8.txx" #include "clitkExtractLymphStation_7.txx" #include "clitkExtractLymphStation_4RL.txx" #endif diff --git a/segmentation/clitkExtractLymphStationsFilter.txx b/segmentation/clitkExtractLymphStationsFilter.txx index 7b2fd2f..ea514a6 100644 --- a/segmentation/clitkExtractLymphStationsFilter.txx +++ b/segmentation/clitkExtractLymphStationsFilter.txx @@ -52,6 +52,15 @@ ExtractLymphStationsFilter(): SetBackgroundValue(0); SetForegroundValue(1); + // Station 8 + SetDistanceMaxToAnteriorPartOfTheSpine(10); + MaskImagePointType p; + p[0] = 15; p[1] = 2; p[2] = 1; + SetEsophagusDiltationForAnt(p); + p[0] = 5; p[1] = 10; p[2] = 1; + SetEsophagusDiltationForRight(p); + SetFuzzyThresholdForS8(0.5); + // Station 7 SetFuzzyThreshold(0.5); SetStation7Filename("station7.mhd"); @@ -59,17 +68,6 @@ ExtractLymphStationsFilter(): //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractLymphStationsFilter:: -SetArgsInfo(ArgsInfoType & argsinfo) { - DD("SetArgsInfo"); -} -//-------------------------------------------------------------------- - - //-------------------------------------------------------------------- template void @@ -78,28 +76,49 @@ GenerateOutputInformation() { // Get inputs LoadAFDB(); m_Input = dynamic_cast(itk::ProcessObject::GetInput(0)); - m_Support = GetAFDB()->template GetImage ("mediastinum"); - - // - typedef clitk::BooleanOperatorLabelImageFilter BFilter; - BFilter::Pointer merge = BFilter::New(); + m_Mediastinum = GetAFDB()->template GetImage ("Mediastinum"); + + // Extract Station8 + StartNewStep("Station 8"); + StartSubStep(); + ExtractStation_8(); + StopSubStep(); + + // Compute some interesting points in trachea + // ( ALTERNATIVE -> SKELETON ANALYSIS ? + // Pb : not sufficient for mostXX points ... ) + + /* ==> todo (but why ???) + ComputeTracheaCentroidsAboveCarina(); + ComputeBronchusExtremaPointsBelowCarina(); + */ - // Extract Station7 - ExtractStation_7(); - m_Output = m_Station7; + if (0) { // temporary suppress + // Extract Station7 + StartNewStep("Station 7"); + StartSubStep(); + ExtractStation_7(); + StopSubStep(); - // Extract Station4RL - ExtractStation_4RL(); + // Extract Station4RL + StartNewStep("Station 4RL"); + StartSubStep(); + //ExtractStation_4RL(); + StopSubStep(); + } - writeImage(m_Station4RL, "s4rl.mhd"); + + // + // typedef clitk::BooleanOperatorLabelImageFilter BFilter; + //BFilter::Pointer merge = BFilter::New(); // writeImage(m_Output, "ouput.mhd"); //writeImage(m_Working_Support, "ws.mhd"); /*merge->SetInput1(m_Station7); - merge->SetInput2(m_Station4RL); // support - merge->SetOperationType(BFilter::AndNot); CHANGE OPERATOR - merge->SetForegroundValue(4); - merge->Update(); - m_Output = merge->GetOutput(); + merge->SetInput2(m_Station4RL); // support + merge->SetOperationType(BFilter::AndNot); CHANGE OPERATOR + merge->SetForegroundValue(4); + merge->Update(); + m_Output = merge->GetOutput(); */ } //-------------------------------------------------------------------- @@ -123,17 +142,42 @@ GenerateData() { DD("GenerateData, graft output"); // Final Step -> graft output (if SetNthOutput => redo) - this->GraftOutput(m_Output); + this->GraftOutput(m_ListOfStations["8"]); } //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +ExtractStation_8() { + + // Check if m_ListOfStations["8"] exist. If yes -> use it as initial + // support instead of m_Mediastinum + if (m_ListOfStations["8"]) { + DD("Station 8 support already exist -> use it"); + m_Working_Support = m_ListOfStations["8"]; + } + else m_Working_Support = m_Mediastinum; + + ExtractStation_8_SI_Limits(); + ExtractStation_8_AP_Limits(); + // ExtractStation_8_LR_Limits(); +} +//-------------------------------------------------------------------- + + //-------------------------------------------------------------------- template void clitk::ExtractLymphStationsFilter:: ExtractStation_7() { - DD("ExtractStation_7"); + if (m_ListOfStations["7"]) { + DD("Station 7 support already exist -> use it"); + m_Working_Support = m_ListOfStations["7"]; + } + else m_Working_Support = m_Mediastinum; ExtractStation_7_SI_Limits(); ExtractStation_7_RL_Limits(); ExtractStation_7_Posterior_Limits(); @@ -146,19 +190,83 @@ template void clitk::ExtractLymphStationsFilter:: ExtractStation_4RL() { - DD("ExtractStation_4RL"); - writeImage(m_Support, "essai.mhd"); // OK - /* WARNING ONLY 4R FIRST !!! (not same inf limits) - */ - + */ ExtractStation_4RL_SI_Limits(); ExtractStation_4RL_LR_Limits(); - + ExtractStation_4RL_AP_Limits(); } //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +void +clitk::ExtractLymphStationsFilter:: +FindExtremaPointsInBronchus(MaskImagePointer input, + int direction, + double distance_max_from_center_point, + ListOfPointsType & LR, + ListOfPointsType & Ant, + ListOfPointsType & Post) +{ + + // Other solution ==> with auto bounding box ! (but pb to prevent to + // be too distant from the center point + + // Extract slices + std::vector slices; + clitk::ExtractSlices(input, 2, slices); + + // Loop on slices + bool found; + for(uint i=0; i(slices[i], 0, true, 10); + slices[i] = KeepLabels(slices[i], + GetBackgroundValue(), + GetForegroundValue(), 1, 1, true); + */ + + // ------- Find rightmost or leftmost point ------- + MaskSliceType::PointType LRMost; + found = + clitk::FindExtremaPointInAGivenDirection(slices[i], + GetBackgroundValue(), + 0, // axis XY + (direction==0?false:true), // right or left according to direction + LRMost); + // ------- Find postmost point ------- + MaskSliceType::PointType postMost; + found = + clitk::FindExtremaPointInAGivenDirection(slices[i], + GetBackgroundValue(), + 1, false, LRMost, + distance_max_from_center_point, + postMost); + // ------- Find antmost point ------- + MaskSliceType::PointType antMost; + found = + clitk::FindExtremaPointInAGivenDirection(slices[i], + GetBackgroundValue(), + 1, true, LRMost, + distance_max_from_center_point, + antMost); + // Only add point if found + if (found) { + // ------- Convert 2D to 3D points -------- + MaskImageType::PointType p; + clitk::PointsUtils::Convert2DTo3D(LRMost, input, i, p); + LR.push_back(p); + clitk::PointsUtils::Convert2DTo3D(antMost, input, i, p); + Ant.push_back(p); + clitk::PointsUtils::Convert2DTo3D(postMost, input, i, p); + Post.push_back(p); + } + } +} +//-------------------------------------------------------------------- #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX diff --git a/segmentation/clitkExtractLymphStationsGenericFilter.h b/segmentation/clitkExtractLymphStationsGenericFilter.h index c5a9949..afeb66b 100644 --- a/segmentation/clitkExtractLymphStationsGenericFilter.h +++ b/segmentation/clitkExtractLymphStationsGenericFilter.h @@ -47,9 +47,13 @@ namespace clitk itkTypeMacro(ExtractLymphStationsGenericFilter, LightObject); //-------------------------------------------------------------------- + // Options for the GenericFilter void SetArgsInfo(const ArgsInfoType & a); + + //-------------------------------------------------------------------- + // Options for the Filter template - void SetOptionsFromArgsInfoToFilter(FilterType * f) ; + void SetOptionsFromArgsInfoToFilter(FilterType * f) ; //-------------------------------------------------------------------- // Main function called each time the filter is updated diff --git a/segmentation/clitkExtractLymphStationsGenericFilter.txx b/segmentation/clitkExtractLymphStationsGenericFilter.txx index 9dfa850..bc5c936 100644 --- a/segmentation/clitkExtractLymphStationsGenericFilter.txx +++ b/segmentation/clitkExtractLymphStationsGenericFilter.txx @@ -63,10 +63,47 @@ void clitk::ExtractLymphStationsGenericFilter:: SetOptionsFromArgsInfoToFilter(FilterType * f) { - f->SetVerboseOption(mArgsInfo.verbose_flag); - f->SetVerboseStep(mArgsInfo.verboseStep_flag); - f->SetWriteStep(mArgsInfo.writeStep_flag); + f->SetVerboseOptionFlag(mArgsInfo.verbose_flag); + f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag); + f->SetWriteStepFlag(mArgsInfo.writeStep_flag); + f->SetVerboseMemoryFlag(mArgsInfo.verboseMemory_flag); f->SetAFDBFilename(mArgsInfo.afdb_arg); + f->SetDistanceMaxToAnteriorPartOfTheSpine(mArgsInfo.maxAntSpine_arg); + f->SetFuzzyThresholdForS8(mArgsInfo.fuzzyThresholdForS8_arg); + + // Check multiple options for radius dilatation + /* + typename FilterType::MaskImagePointType p; + SetMultipleOptionMacro(mArgsInfo, esophagusDilatation, 3, p); + default ? = set before + exception if fail + */ + typename FilterType::MaskImagePointType p; + p[0] = 7; p[1] = 5; p[2] = 0; // default value + if (mArgsInfo.esophagusDilatationForAnt_given == 3) { + for(uint i=0; i<3; i++) + p[i] = mArgsInfo.esophagusDilatationForAnt_arg[i]; + } + else { + if (mArgsInfo.esophagusDilatationForAnt_given == 1) { + for(uint i=0; i<3; i++) + p[i] = mArgsInfo.esophagusDilatationForAnt_arg[0]; + } + } + f->SetEsophagusDiltationForAnt(p); + + p[0] = 5; p[1] = 10; p[2] = 1; // default value + if (mArgsInfo.esophagusDilatationForRight_given == 3) { + for(uint i=0; i<3; i++) + p[i] = mArgsInfo.esophagusDilatationForRight_arg[i]; + } + else { + if (mArgsInfo.esophagusDilatationForRight_given == 1) { + for(uint i=0; i<3; i++) + p[i] = mArgsInfo.esophagusDilatationForRight_arg[0]; + } + } + f->SetEsophagusDiltationForRight(p); } //-------------------------------------------------------------------- diff --git a/segmentation/clitkExtractMediastinum.ggo b/segmentation/clitkExtractMediastinum.ggo index 48139f5..f5f740b 100644 --- a/segmentation/clitkExtractMediastinum.ggo +++ b/segmentation/clitkExtractMediastinum.ggo @@ -10,6 +10,7 @@ option "verboseStep" - "Verbose each step" flag off option "writeStep" w "Write image at each step" flag off option "verboseOption" - "Display options values" flag off option "verboseWarningOff" - "Do not display warning" flag off +option "verboseMemory" - "Display memory usage" flag off section "I/O" diff --git a/segmentation/clitkExtractMediastinumFilter.h b/segmentation/clitkExtractMediastinumFilter.h index f0d24b4..411e20f 100644 --- a/segmentation/clitkExtractMediastinumFilter.h +++ b/segmentation/clitkExtractMediastinumFilter.h @@ -91,70 +91,49 @@ namespace clitk { /** ImageDimension constants */ itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); - // Set all options at a time - template - void SetArgsInfo(ArgsInfoType arg); - // Background / Foreground itkSetMacro(BackgroundValuePatient, MaskImagePixelType); itkGetConstMacro(BackgroundValuePatient, MaskImagePixelType); - // GGO_DefineOption(patientBG, SetBackgroundValuePatient, MaskImagePixelType); itkSetMacro(BackgroundValueLung, MaskImagePixelType); itkGetConstMacro(BackgroundValueLung, MaskImagePixelType); - // GGO_DefineOption(lungBG, SetBackgroundValueLung, MaskImagePixelType); itkSetMacro(BackgroundValueBones, MaskImagePixelType); itkGetConstMacro(BackgroundValueBones, MaskImagePixelType); - // GGO_DefineOption(bonesBG, SetBackgroundValueBones, MaskImagePixelType); itkGetConstMacro(BackgroundValue, MaskImagePixelType); itkGetConstMacro(ForegroundValue, MaskImagePixelType); itkSetMacro(ForegroundValueLeftLung, MaskImagePixelType); itkGetConstMacro(ForegroundValueLeftLung, MaskImagePixelType); - // GGO_DefineOption(lungLeft, SetForegroundValueLeftLung, MaskImagePixelType); itkSetMacro(ForegroundValueRightLung, MaskImagePixelType); itkGetConstMacro(ForegroundValueRightLung, MaskImagePixelType); - // GGO_DefineOption(lungRight, SetForegroundValueRightLung, MaskImagePixelType); itkSetMacro(BackgroundValueTrachea, MaskImagePixelType); itkGetConstMacro(BackgroundValueTrachea, MaskImagePixelType); - // GGO_DefineOption(lungBG, SetBackgroundValueTrachea, MaskImagePixelType); itkSetMacro(IntermediateSpacing, double); itkGetConstMacro(IntermediateSpacing, double); - GGO_DefineOption(spacing, SetIntermediateSpacing, double); itkSetMacro(FuzzyThreshold1, double); itkGetConstMacro(FuzzyThreshold1, double); - GGO_DefineOption(fuzzy1, SetFuzzyThreshold1, double); itkSetMacro(FuzzyThreshold2, double); itkGetConstMacro(FuzzyThreshold2, double); - GGO_DefineOption(fuzzy2, SetFuzzyThreshold2, double); itkSetMacro(FuzzyThreshold3, double); itkGetConstMacro(FuzzyThreshold3, double); - GGO_DefineOption(fuzzy3, SetFuzzyThreshold3, double); - - itkSetMacro(DistanceMaxToAnteriorPartOfTheSpine, double); - itkGetConstMacro(DistanceMaxToAnteriorPartOfTheSpine, double); - GGO_DefineOption(antSpine, SetDistanceMaxToAnteriorPartOfTheSpine, double); itkBooleanMacro(UseBones); itkSetMacro(UseBones, bool); itkGetConstMacro(UseBones, bool); - GGO_DefineOption_Flag(useBones, SetUseBones); itkSetMacro(UpperThreshold, double); itkGetConstMacro(UpperThreshold, double); - GGO_DefineOption(upper, SetUpperThreshold, double); itkSetMacro(LowerThreshold, double); itkGetConstMacro(LowerThreshold, double); - GGO_DefineOption(lower, SetLowerThreshold, double); protected: ExtractMediastinumFilter(); @@ -183,8 +162,7 @@ namespace clitk { double m_FuzzyThreshold1; double m_FuzzyThreshold2; double m_FuzzyThreshold3; - double m_DistanceMaxToAnteriorPartOfTheSpine; - bool m_UseBones; + bool m_UseBones; double m_UpperThreshold; double m_LowerThreshold; diff --git a/segmentation/clitkExtractMediastinumFilter.txx b/segmentation/clitkExtractMediastinumFilter.txx index 7c77546..276c388 100644 --- a/segmentation/clitkExtractMediastinumFilter.txx +++ b/segmentation/clitkExtractMediastinumFilter.txx @@ -64,7 +64,6 @@ ExtractMediastinumFilter(): SetFuzzyThreshold2(0.6); SetFuzzyThreshold3(0.05); - SetDistanceMaxToAnteriorPartOfTheSpine(10); SetOutputMediastinumFilename("mediastinum.mhd"); UseBonesOff(); @@ -123,43 +122,16 @@ SetInputTracheaLabelImage(const MaskImageType * image, MaskImagePixelType bg) //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractMediastinumFilter:: -SetArgsInfo(ArgsInfoType mArgsInfo) -{ - SetVerboseOption_GGO(mArgsInfo); - SetVerboseStep_GGO(mArgsInfo); - SetWriteStep_GGO(mArgsInfo); - SetVerboseWarningOff_GGO(mArgsInfo); - - SetIntermediateSpacing_GGO(mArgsInfo); - SetFuzzyThreshold1_GGO(mArgsInfo); - SetFuzzyThreshold2_GGO(mArgsInfo); - SetFuzzyThreshold3_GGO(mArgsInfo); - - SetAFDBFilename_GGO(mArgsInfo); - SetDistanceMaxToAnteriorPartOfTheSpine_GGO(mArgsInfo); - SetUseBones_GGO(mArgsInfo); - - SetLowerThreshold_GGO(mArgsInfo); - SetUpperThreshold_GGO(mArgsInfo); -} -//-------------------------------------------------------------------- - - //-------------------------------------------------------------------- template void clitk::ExtractMediastinumFilter:: GenerateInputRequestedRegion() { - //DD("GenerateInputRequestedRegion"); + // DD("GenerateInputRequestedRegion"); // Do not call default - // Superclass::GenerateInputRequestedRegion(); - // DD("End GenerateInputRequestedRegion"); + // Superclass::GenerateInputRequestedRegion(); + // DD("End GenerateInputRequestedRegion"); } //-------------------------------------------------------------------- @@ -181,19 +153,24 @@ template void clitk::ExtractMediastinumFilter:: GenerateOutputInformation() { - // DD("GenerateOutputInformation"); // Do not call default - // Superclass::GenerateOutputInformation(); + // Superclass::GenerateOutputInformation(); //-------------------------------------------------------------------- // Get input pointers + clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK LoadAFDB(); ImageConstPointer input = dynamic_cast(itk::ProcessObject::GetInput(0)); - MaskImagePointer patient = GetAFDB()->template GetImage ("patient"); - MaskImagePointer lung = GetAFDB()->template GetImage ("lungs"); - MaskImagePointer bones = GetAFDB()->template GetImage ("bones"); - MaskImagePointer trachea = GetAFDB()->template GetImage ("trachea"); + MaskImagePointer patient = GetAFDB()->template GetImage ("Patient"); + MaskImagePointer lung = GetAFDB()->template GetImage ("Lungs"); + MaskImagePointer bones; + if (GetUseBones()) { + bones = GetAFDB()->template GetImage ("Bones"); + } + MaskImagePointer trachea = GetAFDB()->template GetImage ("Trachea"); + clitk::PrintMemory(GetVerboseMemoryFlag(), "After read patient, lung"); + //-------------------------------------------------------------------- // Step 1: Crop support (patient) to lung extend in RL StartNewStep("Crop support like lungs along LR"); @@ -204,7 +181,7 @@ GenerateOutputInformation() { cropFilter->Update(); output = cropFilter->GetOutput(); this->template StopCurrentStep(output); - + //-------------------------------------------------------------------- // Step 2: Crop support (previous) to bones extend in AP if (GetUseBones()) { @@ -219,7 +196,7 @@ GenerateOutputInformation() { //-------------------------------------------------------------------- // Step 3: patient minus lungs, minus bones, minus trachea - StartNewStep("Patient contours minus lungs, bones, trachea"); + StartNewStep("Patient contours minus lungs, trachea [and bones]"); typedef clitk::BooleanOperatorLabelImageFilter BoolFilterType; typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); boolFilter->InPlaceOn(); @@ -250,34 +227,41 @@ GenerateOutputInformation() { // (label must be '1' because right is greater than left). (WE DO // NOT NEED TO SEPARATE ? ) StartNewStep("Left/Right limits with lungs"); - /* - ImagePointer right_lung = clitk::SetBackground(lung, lung, 2, 0); - ImagePointer left_lung = clitk::SetBackground(lung, lung, 1, 0); - writeImage(right_lung, "right.mhd"); - writeImage(left_lung, "left.mhd"); - */ + + // The following cannot be "inplace" because mask is the same than input ... + MaskImagePointer right_lung = + clitk::SetBackground(lung, lung, 2, 0, false); + MaskImagePointer left_lung = + clitk::SetBackground(lung, lung, 1, 0, false); + right_lung = clitk::ResizeImageLike(right_lung, output, GetBackgroundValue()); + left_lung = clitk::ResizeImageLike(left_lung, output, GetBackgroundValue()); + // writeImage(right_lung, "right.mhd"); + // writeImage(left_lung, "left.mhd"); + typedef clitk::AddRelativePositionConstraintToLabelImageFilter RelPosFilterType; typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New(); relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - relPosFilter->VerboseStepOff(); - relPosFilter->WriteStepOff(); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->WriteStepFlagOff(); relPosFilter->SetInput(output); - //relPosFilter->SetInputObject(left_lung); - relPosFilter->SetInputObject(lung); - relPosFilter->SetOrientationType(RelPosFilterType::LeftTo); // warning left lung is at right ;) + relPosFilter->SetInputObject(left_lung); + // relPosFilter->SetInputObject(lung); + relPosFilter->AddOrientationType(RelPosFilterType::LeftTo); // warning left lung is at right ;) relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing()); relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1()); relPosFilter->Update(); output = relPosFilter->GetOutput(); //writeImage(right_lung, "step4-left.mhd"); + relPosFilter = RelPosFilterType::New(); relPosFilter->SetInput(output); relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - relPosFilter->VerboseStepOff(); - relPosFilter->WriteStepOff(); - //relPosFilter->SetInputObject(right_lung); - relPosFilter->SetInputObject(lung); - relPosFilter->SetOrientationType(RelPosFilterType::RightTo); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->WriteStepFlagOff(); + relPosFilter->SetInput(output); + relPosFilter->SetInputObject(right_lung); + //relPosFilter->SetInputObject(lung); + relPosFilter->AddOrientationType(RelPosFilterType::RightTo); relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing()); relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1()); relPosFilter->Update(); @@ -318,7 +302,7 @@ GenerateOutputInformation() { roiFilter->ReleaseDataFlagOff(); roiFilter->Update(); bones_ant = roiFilter->GetOutput(); - writeImage(bones_ant, "b_ant.mhd"); + // writeImage(bones_ant, "b_ant.mhd"); // POST part roiFilter = ROIFilterType::New(); index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1; @@ -330,30 +314,30 @@ GenerateOutputInformation() { roiFilter->ReleaseDataFlagOff(); roiFilter->Update(); bones_post = roiFilter->GetOutput(); - writeImage(bones_post, "b_post.mhd"); + // writeImage(bones_post, "b_post.mhd"); // Go ! relPosFilter->SetCurrentStepNumber(0); relPosFilter->ResetPipeline();// = RelPosFilterType::New(); relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - relPosFilter->VerboseStepOff(); - relPosFilter->WriteStepOff(); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->WriteStepFlagOff(); relPosFilter->SetInput(output); relPosFilter->SetInputObject(bones_post); - relPosFilter->SetOrientationType(RelPosFilterType::AntTo); + relPosFilter->AddOrientationType(RelPosFilterType::AntTo); relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing()); relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2()); relPosFilter->Update(); output = relPosFilter->GetOutput(); - writeImage(output, "post.mhd"); + // writeImage(output, "post.mhd"); relPosFilter->SetInput(relPosFilter->GetOutput()); relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - relPosFilter->VerboseStepOff(); - relPosFilter->WriteStepOff(); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->WriteStepFlagOff(); relPosFilter->SetInput(output); relPosFilter->SetInputObject(bones_ant); - relPosFilter->SetOrientationType(RelPosFilterType::PostTo); + relPosFilter->AddOrientationType(RelPosFilterType::PostTo); relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing()); relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2()); relPosFilter->Update(); @@ -370,86 +354,6 @@ GenerateOutputInformation() { GetForegroundValue(), 1, 1, 0); this->template StopCurrentStep(output); - //-------------------------------------------------------------------- - // Step 7 : Slice by Slice to optimize posterior part - // Warning slice does not necesseraly correspond between 'output' and 'bones' - typedef clitk::ExtractSliceFilter ExtractSliceFilterType; - typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New(); - typedef typename ExtractSliceFilterType::SliceType SliceType; - std::vector mSlices; - if (GetUseBones()) { - StartNewStep("Rafine posterior part according to vertebral body"); - extractSliceFilter->SetInput(bones_post); - extractSliceFilter->SetDirection(2); - extractSliceFilter->Update(); - std::vector mVertebralAntPositionBySlice; - extractSliceFilter->GetOutputSlices(mSlices); - for(unsigned int i=0; i(mSlices[i], 0, true, 10); - mSlices[i] = KeepLabels(mSlices[i], - GetBackgroundValue(), - GetForegroundValue(), 1, 2, true); // keep two first - // Find most anterior point (start of the vertebral) - typename itk::ImageRegionIteratorWithIndex - iter(mSlices[i], mSlices[i]->GetLargestPossibleRegion()); - iter.GoToBegin(); - bool stop = false; - while (!stop) { - if (iter.Get() != GetBackgroundValue()) - stop = true; // not foreground because we keep two main label - ++iter; - if (iter.IsAtEnd()) stop = true; - } - if (!iter.IsAtEnd()) { - typename SliceType::PointType p; - mSlices[i]->TransformIndexToPhysicalPoint(iter.GetIndex(),p); - mVertebralAntPositionBySlice.push_back(p[1]); - } - else { - mVertebralAntPositionBySlice.push_back(bones_post->GetOrigin()[1]+(bones->GetLargestPossibleRegion().GetSize()[1]*bones->GetSpacing()[1])); - DD(mVertebralAntPositionBySlice.back()); - DD("ERROR ?? NO FG in bones here ?"); - } - } - - // Cut Post position slice by slice - { - MaskImageRegionType region; - MaskImageSizeType size; - MaskImageIndexType start; - size[2] = 1; - start[0] = output->GetLargestPossibleRegion().GetIndex()[0]; - for(unsigned int i=0; iGetOrigin()[2]+(bones_post->GetLargestPossibleRegion().GetIndex()[2]+i)*bones_post->GetSpacing()[2]; - MaskImageIndexType index; - output->TransformPhysicalPointToIndex(point, index); - // Compute region - start[2] = index[2]; - start[1] = output->GetLargestPossibleRegion().GetIndex()[1]+index[1]; - size[0] = output->GetLargestPossibleRegion().GetSize()[0]; - size[1] = output->GetLargestPossibleRegion().GetSize()[1]-start[1]; - region.SetSize(size); - region.SetIndex(start); - // Fill Region - if (output->GetLargestPossibleRegion().IsInside(start)) { - itk::ImageRegionIteratorWithIndex it(output, region); - it.GoToBegin(); - while (!it.IsAtEnd()) { - it.Set(GetBackgroundValue()); - ++it; - } - } - } - } - this->template StopCurrentStep(output); - } //-------------------------------------------------------------------- // Step 8: Trial segmentation KMeans @@ -464,7 +368,7 @@ GenerateOutputInformation() { ImagePointer working_input = cropLikeFilter->GetOutput(); writeImage(working_input, "crop-input.mhd"); // Set bG at -1000 - working_input = clitk::SetBackground(working_input, output, GetBackgroundValue(), -1000); + working_input = clitk::SetBackground(working_input, output, GetBackgroundValue(), -1000, true); writeImage(working_input, "crop-input2.mhd"); // Kmeans typedef itk::ScalarImageKmeansImageFilter KMeansFilterType; @@ -486,7 +390,7 @@ GenerateOutputInformation() { } MaskImageType::Pointer kmeans = kmeansFilter->GetOutput(); kmeans = clitk::SetBackground(kmeans, kmeans, - 1, GetBackgroundValue()); + 1, GetBackgroundValue(), true); writeImage(kmeans, "kmeans.mhd"); // Get final results, and remove from current mask boolFilter = BoolFilterType::New(); @@ -524,8 +428,8 @@ GenerateOutputInformation() { // Not below the heart // relPosFilter = RelPosFilterType::New(); // relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - // relPosFilter->VerboseStepOff(); - // relPosFilter->WriteStepOff(); + // relPosFilter->VerboseStepFlagOff(); + // relPosFilter->WriteStepFlagOff(); // relPosFilter->SetInput(output); // relPosFilter->SetInputObject(heart); // relPosFilter->SetOrientationType(RelPosFilterType::SupTo); @@ -542,12 +446,12 @@ GenerateOutputInformation() { // TODO BOFFF ???? relPosFilter = RelPosFilterType::New(); relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId()); - relPosFilter->VerboseStepOff(); - relPosFilter->WriteStepOff(); + relPosFilter->VerboseStepFlagOff(); + relPosFilter->WriteStepFlagOff(); relPosFilter->SetInput(output); // relPosFilter->SetInputObject(left_lung); relPosFilter->SetInputObject(lung); - relPosFilter->SetOrientationType(RelPosFilterType::SupTo); + relPosFilter->AddOrientationType(RelPosFilterType::SupTo); relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing()); relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold3()); relPosFilter->Update(); @@ -560,13 +464,12 @@ GenerateOutputInformation() { StartNewStep("Slice by Slice keep only one component"); typedef clitk::ExtractSliceFilter ExtractSliceFilterType; // typename ExtractSliceFilterType::Pointer - extractSliceFilter = ExtractSliceFilterType::New(); + ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New(); extractSliceFilter->SetInput(output); extractSliceFilter->SetDirection(2); extractSliceFilter->Update(); typedef typename ExtractSliceFilterType::SliceType SliceType; - // std::vector - mSlices.clear(); + std::vector mSlices; extractSliceFilter->GetOutputSlices(mSlices); for(unsigned int i=0; i(mSlices[i], 0, true, 100); @@ -586,35 +489,37 @@ GenerateOutputInformation() { //-------------------------------------------------------------------- // Step 9: Binarize to remove too high HU // --> warning CCL slice by slice must be done before - StartNewStep("Remove hypersignal (bones and injected part"); - // Crop initial ct like current support - typedef CropLikeImageFilter CropLikeFilterType; - typename CropLikeFilterType::Pointer cropLikeFilter = CropLikeFilterType::New(); - cropLikeFilter->SetInput(input); - cropLikeFilter->SetCropLikeImage(output); - cropLikeFilter->Update(); - ImagePointer working_input = cropLikeFilter->GetOutput(); - writeImage(working_input, "crop-ct.mhd"); - // Binarize - typedef itk::BinaryThresholdImageFilter InputBinarizeFilterType; - typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New(); - binarizeFilter->SetInput(working_input); - binarizeFilter->SetLowerThreshold(GetLowerThreshold()); - binarizeFilter->SetUpperThreshold(GetUpperThreshold()); - binarizeFilter->SetInsideValue(this->GetBackgroundValue()); // opposite - binarizeFilter->SetOutsideValue(this->GetForegroundValue()); // opposite - binarizeFilter->Update(); - MaskImagePointer working_bin = binarizeFilter->GetOutput(); - writeImage(working_bin, "bin.mhd"); - // Remove from support - boolFilter = BoolFilterType::New(); - boolFilter->InPlaceOn(); - boolFilter->SetInput1(output); - boolFilter->SetInput2(working_bin); - boolFilter->SetOperationType(BoolFilterType::AndNot); - boolFilter->Update(); - output = boolFilter->GetOutput(); - StopCurrentStep(output); + if (0) { + StartNewStep("Remove hypersignal (bones and injected part"); + // Crop initial ct like current support + typedef CropLikeImageFilter CropLikeFilterType; + typename CropLikeFilterType::Pointer cropLikeFilter = CropLikeFilterType::New(); + cropLikeFilter->SetInput(input); + cropLikeFilter->SetCropLikeImage(output); + cropLikeFilter->Update(); + ImagePointer working_input = cropLikeFilter->GetOutput(); + // writeImage(working_input, "crop-ct.mhd"); + // Binarize + typedef itk::BinaryThresholdImageFilter InputBinarizeFilterType; + typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New(); + binarizeFilter->SetInput(working_input); + binarizeFilter->SetLowerThreshold(GetLowerThreshold()); + binarizeFilter->SetUpperThreshold(GetUpperThreshold()); + binarizeFilter->SetInsideValue(this->GetBackgroundValue()); // opposite + binarizeFilter->SetOutsideValue(this->GetForegroundValue()); // opposite + binarizeFilter->Update(); + MaskImagePointer working_bin = binarizeFilter->GetOutput(); + // writeImage(working_bin, "bin.mhd"); + // Remove from support + boolFilter = BoolFilterType::New(); + boolFilter->InPlaceOn(); + boolFilter->SetInput1(output); + boolFilter->SetInput2(working_bin); + boolFilter->SetOperationType(BoolFilterType::AndNot); + boolFilter->Update(); + output = boolFilter->GetOutput(); + StopCurrentStep(output); + } //-------------------------------------------------------------------- // Step 10 : AutoCrop @@ -649,10 +554,9 @@ void clitk::ExtractMediastinumFilter:: GenerateData() { - DD("GenerateData"); this->GraftOutput(output); // Store image filenames into AFDB - GetAFDB()->SetImageFilename("mediastinum", this->GetOutputMediastinumFilename()); + GetAFDB()->SetImageFilename("Mediastinum", this->GetOutputMediastinumFilename()); WriteAFDB(); } //-------------------------------------------------------------------- diff --git a/segmentation/clitkExtractMediastinumGenericFilter.h b/segmentation/clitkExtractMediastinumGenericFilter.h index 70a4532..1a20c8a 100644 --- a/segmentation/clitkExtractMediastinumGenericFilter.h +++ b/segmentation/clitkExtractMediastinumGenericFilter.h @@ -47,7 +47,13 @@ namespace clitk itkTypeMacro(ExtractMediastinumGenericFilter, LightObject); //-------------------------------------------------------------------- + // Options for the GenericFilter void SetArgsInfo(const ArgsInfoType & a); + + //-------------------------------------------------------------------- + // Options for the Filter + template + void SetOptionsFromArgsInfoToFilter(FilterType * f) ; //-------------------------------------------------------------------- // Main function called each time the filter is updated diff --git a/segmentation/clitkExtractMediastinumGenericFilter.txx b/segmentation/clitkExtractMediastinumGenericFilter.txx index 881ebba..1760cac 100644 --- a/segmentation/clitkExtractMediastinumGenericFilter.txx +++ b/segmentation/clitkExtractMediastinumGenericFilter.txx @@ -23,7 +23,8 @@ //-------------------------------------------------------------------- template -clitk::ExtractMediastinumGenericFilter::ExtractMediastinumGenericFilter(): +clitk::ExtractMediastinumGenericFilter:: +ExtractMediastinumGenericFilter(): ImageToImageGenericFilter("ExtractMediastinum") { // Default values @@ -36,33 +37,55 @@ clitk::ExtractMediastinumGenericFilter::ExtractMediastinumGenericF //-------------------------------------------------------------------- template template -void clitk::ExtractMediastinumGenericFilter::InitializeImageType() +void +clitk::ExtractMediastinumGenericFilter:: +InitializeImageType() { ADD_IMAGE_TYPE(Dim, short); - // ADD_IMAGE_TYPE(Dim, short); - // ADD_IMAGE_TYPE(Dim, int); - // ADD_IMAGE_TYPE(Dim, float); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template -void clitk::ExtractMediastinumGenericFilter::SetArgsInfo(const ArgsInfoType & a) +void +clitk::ExtractMediastinumGenericFilter:: +SetArgsInfo(const ArgsInfoType & a) { mArgsInfo=a; SetIOVerbose(mArgsInfo.verbose_flag); if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes(); if (mArgsInfo.input_given) AddInputFilename(mArgsInfo.input_arg); - //if (mArgsInfo.patient_given) AddInputFilename(mArgsInfo.patient_arg); - //if (mArgsInfo.lung_given) AddInputFilename(mArgsInfo.lung_arg); - //if (mArgsInfo.bones_given) AddInputFilename(mArgsInfo.bones_arg); - //if (mArgsInfo.trachea_given) AddInputFilename(mArgsInfo.trachea_arg); if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg); } //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +template +void +clitk::ExtractMediastinumGenericFilter:: +SetOptionsFromArgsInfoToFilter(FilterType * f) +{ + f->SetVerboseOptionFlag(mArgsInfo.verbose_flag); + f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag); + f->SetWriteStepFlag(mArgsInfo.writeStep_flag); + f->SetAFDBFilename(mArgsInfo.afdb_arg); + f->SetOutputMediastinumFilename(mArgsInfo.output_arg); + f->SetVerboseMemoryFlag(mArgsInfo.verboseMemory_flag); + + f->SetUseBones(mArgsInfo.useBones_flag); + f->SetIntermediateSpacing(mArgsInfo.spacing_arg); + f->SetFuzzyThreshold1(mArgsInfo.fuzzy1_arg); + f->SetFuzzyThreshold2(mArgsInfo.fuzzy2_arg); + f->SetFuzzyThreshold3(mArgsInfo.fuzzy3_arg); + f->SetUpperThreshold(mArgsInfo.upper_arg); + f->SetLowerThreshold(mArgsInfo.lower_arg); +} +//-------------------------------------------------------------------- + + //-------------------------------------------------------------------- // Update with the number of dimensions and the pixeltype //-------------------------------------------------------------------- @@ -72,10 +95,6 @@ void clitk::ExtractMediastinumGenericFilter::UpdateWithInputImageT { // Reading input typename ImageType::Pointer input = this->template GetInput(0); - // typename ImageType::Pointer patient = this->template GetInput(0); - // typename ImageType::Pointer lung = this->template GetInput(1); - // typename ImageType::Pointer bones = this->template GetInput(2); - // typename ImageType::Pointer trachea = this->template GetInput(3); // Create filter typedef clitk::ExtractMediastinumFilter FilterType; @@ -83,11 +102,7 @@ void clitk::ExtractMediastinumGenericFilter::UpdateWithInputImageT // Set global Options filter->SetInput(input); - // filter->SetInputPatientLabelImage(patient, mArgsInfo.patientBG_arg); - // filter->SetInputLungLabelImage(lung, mArgsInfo.lungBG_arg, mArgsInfo.lungRight_arg, mArgsInfo.lungLeft_arg); - // filter->SetInputBonesLabelImage(bones, mArgsInfo.bonesBG_arg); - filter->SetOutputMediastinumFilename(mArgsInfo.output_arg); - filter->SetArgsInfo(mArgsInfo); + SetOptionsFromArgsInfoToFilter(filter); // Go ! filter->Update(); diff --git a/segmentation/clitkExtractPatientFilter.h b/segmentation/clitkExtractPatientFilter.h index b471747..0353f9b 100644 --- a/segmentation/clitkExtractPatientFilter.h +++ b/segmentation/clitkExtractPatientFilter.h @@ -90,80 +90,61 @@ namespace clitk { void SetInput(const TInputImageType * image); itkSetMacro(OutputPatientFilename, std::string); itkGetMacro(OutputPatientFilename, std::string); - GGO_DefineOption(output, SetOutputPatientFilename, std::string); - - // Set all options at a time - template - void SetArgsInfo(ArgsInfoType arg); // Step 1 itkSetMacro(UpperThreshold, InputImagePixelType); itkGetMacro(UpperThreshold, InputImagePixelType); - GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType); itkSetMacro(LowerThreshold, InputImagePixelType); itkGetMacro(LowerThreshold, InputImagePixelType); itkSetMacro(UseLowerThreshold, bool); itkGetConstMacro(UseLowerThreshold, bool); itkBooleanMacro(UseLowerThreshold); - GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold); // Step 2 itkSetMacro(DecomposeAndReconstructDuringFirstStep, bool); itkGetConstMacro(DecomposeAndReconstructDuringFirstStep, bool); itkBooleanMacro(DecomposeAndReconstructDuringFirstStep); - GGO_DefineOption_Flag(erode1, SetDecomposeAndReconstructDuringFirstStep); itkSetMacro(Radius1, InternalImageSizeType); itkGetConstMacro(Radius1, InternalImageSizeType); - GGO_DefineOption_Vector(radius1, SetRadius1, InternalImageSizeType, ImageDimension, true); itkSetMacro(MaximumNumberOfLabels1, int); itkGetConstMacro(MaximumNumberOfLabels1, int); - GGO_DefineOption(max1, SetMaximumNumberOfLabels1, int); itkSetMacro(NumberOfNewLabels1, int); itkGetConstMacro(NumberOfNewLabels1, int); - GGO_DefineOption(new1, SetNumberOfNewLabels1, int); // Step 2 itkSetMacro(DecomposeAndReconstructDuringSecondStep, bool); itkGetConstMacro(DecomposeAndReconstructDuringSecondStep, bool); itkBooleanMacro(DecomposeAndReconstructDuringSecondStep); - GGO_DefineOption_Flag(erode2, SetDecomposeAndReconstructDuringSecondStep); itkSetMacro(Radius2, InternalImageSizeType); itkGetConstMacro(Radius2, InternalImageSizeType); - GGO_DefineOption_Vector(radius2, SetRadius2, InternalImageSizeType, ImageDimension, true) itkSetMacro(MaximumNumberOfLabels2, int); itkGetConstMacro(MaximumNumberOfLabels2, int); - GGO_DefineOption(max2, SetMaximumNumberOfLabels2, int); itkSetMacro(NumberOfNewLabels2, int); itkGetConstMacro(NumberOfNewLabels2, int); - GGO_DefineOption(new2, SetNumberOfNewLabels2, int); // Step 3 itkSetMacro(FirstKeep, int); itkGetConstMacro(FirstKeep, int); - GGO_DefineOption(firstKeep, SetFirstKeep, int); itkSetMacro(LastKeep, int); itkGetConstMacro(LastKeep, int); - GGO_DefineOption(lastKeep, SetLastKeep, int); // Step 4 itkSetMacro(FinalOpenClose, bool); itkGetConstMacro(FinalOpenClose, bool); itkBooleanMacro(FinalOpenClose); - GGO_DefineOption_Flag(openClose, SetFinalOpenClose); // Step 4 itkSetMacro(AutoCrop, bool); itkGetConstMacro(AutoCrop, bool); itkBooleanMacro(AutoCrop); - GGO_DefineOption_Flag(noAutoCrop, SetAutoCrop); protected: ExtractPatientFilter(); diff --git a/segmentation/clitkExtractPatientFilter.txx b/segmentation/clitkExtractPatientFilter.txx index bf84ef7..61de51d 100644 --- a/segmentation/clitkExtractPatientFilter.txx +++ b/segmentation/clitkExtractPatientFilter.txx @@ -24,6 +24,7 @@ #include "clitkSetBackgroundImageFilter.h" #include "clitkDecomposeAndReconstructImageFilter.h" #include "clitkAutoCropFilter.h" +#include "clitkMemoryUsage.h" // itk #include "itkBinaryThresholdImageFilter.h" @@ -89,50 +90,14 @@ SetInput(const TInputImageType * image) //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -template -template -void -clitk::ExtractPatientFilter:: -SetArgsInfo(ArgsInfoType arg) -{ - SetVerboseOption_GGO(arg); - SetVerboseStep_GGO(arg); - SetWriteStep_GGO(arg); - SetVerboseWarningOff_GGO(arg); - - SetOutputPatientFilename_GGO(arg); - - SetUpperThreshold_GGO(arg); - SetLowerThreshold_GGO(arg); - - SetDecomposeAndReconstructDuringFirstStep_GGO(arg); - SetRadius1_GGO(arg); - SetMaximumNumberOfLabels1_GGO(arg); - SetNumberOfNewLabels1_GGO(arg); - - SetDecomposeAndReconstructDuringSecondStep_GGO(arg); - SetRadius2_GGO(arg); - SetMaximumNumberOfLabels2_GGO(arg); - SetNumberOfNewLabels2_GGO(arg); - - SetFirstKeep_GGO(arg); - SetLastKeep_GGO(arg); - - SetFinalOpenClose_GGO(arg); - SetAutoCrop_GGO(arg); - - SetAFDBFilename_GGO(arg); -} -//-------------------------------------------------------------------- - - //-------------------------------------------------------------------- template void clitk::ExtractPatientFilter:: GenerateOutputInformation() { + clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK + Superclass::GenerateOutputInformation(); input = dynamic_cast(itk::ProcessObject::GetInput(0)); @@ -303,7 +268,7 @@ GenerateData() { // Final Graft this->GraftOutput(output); // Store image filename into AFDB - GetAFDB()->SetImageFilename("patient", this->GetOutputPatientFilename()); + GetAFDB()->SetImageFilename("Patient", this->GetOutputPatientFilename()); WriteAFDB(); } //-------------------------------------------------------------------- -- 2.45.1