//--------------------------------------------------------------------
int main(int argc, char * argv[])
{
-
// Init command line
GGO(clitkExtractAirwaysTreeInfo, args_info);
CLITK_INIT;
/** Connect inputs */
void SetInput(const ImageType * image);
- // Set all options at a time
- template<class ArgsInfoType>
- void SetArgsInfo(ArgsInfoType arg);
-
// Background / Foreground
itkGetConstMacro(BackgroundValue, ImagePixelType);
itkGetConstMacro(ForegroundValue, ImagePixelType);
//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-template <class ImageType>
-template<class ArgsInfoType>
-void
-clitk::ExtractAirwaysTreeInfoFilter<ImageType>::
-SetArgsInfo(ArgsInfoType mArgsInfo)
-{
- SetVerboseOption_GGO(mArgsInfo);
- SetVerboseStep_GGO(mArgsInfo);
- SetWriteStep_GGO(mArgsInfo);
- SetVerboseWarningOff_GGO(mArgsInfo);
- SetAFDBFilename_GGO(mArgsInfo);
-}
-//--------------------------------------------------------------------
-
-
//--------------------------------------------------------------------
template <class ImageType>
void
StopCurrentStep();
// Reput FG instead of label in the skeleton image
- skeleton = clitk::SetBackground<ImageType, ImageType>(skeleton, skeleton, label, GetForegroundValue());
+ skeleton = clitk::SetBackground<ImageType, ImageType>(skeleton, skeleton, label, GetForegroundValue(), true);
// Debug
typename StructuralTreeType::iterator sit = mStructuralSkeletonTree.begin();
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);
itkTypeMacro(ExtractAirwaysTreeInfoGenericFilter, LightObject);
//--------------------------------------------------------------------
+ template<class FilterType>
+ void SetOptionsFromArgsInfoToFilter(FilterType * f);
void SetArgsInfo(const ArgsInfoType & a);
//--------------------------------------------------------------------
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void clitk::ExtractAirwaysTreeInfoGenericFilter<ArgsInfoType>::
+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
//--------------------------------------------------------------------
this->SetFilterBase(filter);
// Set global Options
- filter->SetArgsInfo(mArgsInfo);
filter->SetInput(input);
+ SetOptionsFromArgsInfoToFilter<FilterType>(filter);
// Go !
filter->Update();
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"
//--------------------------------------------------------------------
/*
- Extract bony anatomy through thresholding and connected component labelling.
+ Extract bony anatomy through thresholding and connected component
+ labelling.
*/
//--------------------------------------------------------------------
/** Connect inputs */
void SetInput(const InputImageType * image);
- // Set all options at a time
- template<class ArgsInfoType>
- 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();
//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-template <class TInputImageType>
-template<class ArgsInfoType>
-void
-clitk::ExtractBonesFilter<TInputImageType>::
-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 <class TInputImageType>
this->GraftOutput(caster->GetOutput());
// Store image filenames into AFDB
- GetAFDB()->SetImageFilename("bones", this->GetOutputBonesFilename());
+ GetAFDB()->SetImageFilename("Bones", this->GetOutputBonesFilename());
WriteAFDB();
return;
}
//--------------------------------------------------------------------
void SetArgsInfo(const ArgsInfoType & a);
+ template<class FilterType>
+ void SetOptionsFromArgsInfoToFilter(FilterType * f);
//--------------------------------------------------------------------
// Main function called each time the filter is updated
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void clitk::ExtractBonesGenericFilter<ArgsInfoType>::
+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
//--------------------------------------------------------------------
typename FilterType::Pointer filter = FilterType::New();
// Set global Options
- filter->SetArgsInfo(mArgsInfo);
filter->SetInput(input);
+ SetOptionsFromArgsInfoToFilter<FilterType>(filter);
// Go !
filter->Update();
//--------------------------------------------------------------------
int main(int argc, char * argv[])
{
-
// Init command line
GGO(clitkExtractLung, args_info);
CLITK_INIT;
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"
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"
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
typedef typename MaskImageType::PointType MaskImagePointType;
itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
- typedef int InternalPixelType;
+ // typedef int InternalPixelType;
+ typedef uchar InternalPixelType;
typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
typedef typename InternalImageType::Pointer InternalImagePointer;
typedef typename InternalImageType::IndexType InternalIndexType;
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<class ArgsInfoType>
- void SetArgsInfo(ArgsInfoType arg);
// Get output (only availabe after update !)
typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
// 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<InternalIndexType> & 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();
// 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
double m_MultiplierForTrachea;
std::vector<InternalIndexType> m_Seeds;
int m_NumberOfSlicesToSkipBeforeSearchingSeed;
+ bool m_TracheaVolumeMustBeCheckedFlag;
+ bool m_VerboseRegionGrowingFlag;
// Step 3
int m_NumberOfHistogramBins;
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
#include "clitkAutoCropFilter.h"
#include "clitkCropLikeImageFilter.h"
#include "clitkFillMaskFilter.h"
+#include "clitkMemoryUsage.h"
// itk
#include "itkBinaryThresholdImageFilter.h"
SetBackgroundValue(0); // Must be zero
SetForegroundValue(1);
SetMinimalComponentSize(100);
+ VerboseRegionGrowingFlagOff();
// Step 1 default values
SetUpperThreshold(-300);
SetMultiplierForTrachea(5);
SetThresholdStepSizeForTrachea(64);
SetNumberOfSlicesToSkipBeforeSearchingSeed(0);
+ TracheaVolumeMustBeCheckedFlagOn();
// Step 3 default values
SetNumberOfHistogramBins(500);
SetLabelizeParameters3(p3);
// Step 5
- OpenCloseOff();
+ OpenCloseFlagOff();
SetOpenCloseRadius(1);
// Step 6
- FillHolesOn();
+ FillHolesFlagOn();
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-template <class ImageType>
-template<class ArgsInfoType>
-void
-clitk::ExtractLungFilter<ImageType>::
-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 <class ImageType>
void
clitk::ExtractLungFilter<ImageType>::
GenerateOutputInformation()
{
+ clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK
Superclass::GenerateOutputInformation();
// Read DB
// Get input pointers
input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
- patient = GetAFDB()->template GetImage <MaskImageType>("patient");
+ patient = GetAFDB()->template GetImage <MaskImageType>("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<ImageType> 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<ImageType>(working_input);
-
+ PrintMemory(GetVerboseMemoryFlag(), "After crop"); // OK, slightly more than a copy of input
+
//--------------------------------------------------------------------
//--------------------------------------------------------------------
StartNewStep("Set background to initial image");
working_input = SetBackground<ImageType, MaskImageType>
- (working_input, patient, GetPatientMaskBackgroundValue(), -1000);
+ (working_input, patient, GetPatientMaskBackgroundValue(), -1000, true);
StopCurrentStep<ImageType>(working_input);
+ PrintMemory(GetVerboseMemoryFlag(), "After set bg"); // OK, additional mem = 0
+
+ /*
+ // We do not need patient mask anymore, release memory
+ GetAFDB()->template ReleaseImage<MaskImageType>("Patient");
+ DD(patient->GetReferenceCount());
+ PrintMemory(GetVerboseMemoryFlag(), "After delete patient"); // OK, additional mem = 0
+ patient->Delete();
+ PrintMemory(GetVerboseMemoryFlag(), "After delete patient"); // OK, additional mem = 0
+ */
//--------------------------------------------------------------------
//--------------------------------------------------------------------
}
}
// Threshold to get air
- typedef itk::BinaryThresholdImageFilter<ImageType, InternalImageType> InputBinarizeFilterType;
- typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+ typedef itk::BinaryThresholdImageFilter<ImageType, MaskImageType> 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<InternalImageType>(working_image, GetBackgroundValue(), true, GetMinimalComponentSize());
+ working_mask = binarizeFilter->GetOutput();
+ PrintMemory(GetVerboseMemoryFlag(), "After Binarizefilter"); // OK, additional mem is one mask image
- working_image = RemoveLabels<InternalImageType>
- (working_image, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove());
+ // Labelize and keep right labels
+ working_mask =
+ Labelize<MaskImageType>
+ (working_mask, GetBackgroundValue(), true, GetMinimalComponentSize());
+ PrintMemory(GetVerboseMemoryFlag(), "After Labelize"); // BUG ? additional mem around 1 time the input ?
+
+ working_mask = RemoveLabels<MaskImageType>
+ (working_mask, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove());
+ PrintMemory(GetVerboseMemoryFlag(), "After RemoveLabels"); // OK additional mem = 0
- typename InternalImageType::Pointer air = KeepLabels<InternalImageType>
- (working_image,
+ working_mask = KeepLabels<MaskImageType>
+ (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<ImageType, InternalImageType>
- (working_input, air, this->GetForegroundValue(), this->GetBackgroundValue());
+ working_input = SetBackground<ImageType, MaskImageType>
+ (working_input, working_mask, this->GetForegroundValue(), this->GetBackgroundValue(), true);
+ PrintMemory(GetVerboseMemoryFlag(), "After SetBackground");
// End
StopCurrentStep<ImageType>(working_input);
//--------------------------------------------------------------------
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<ImageType,InternalImageType> OtsuThresholdImageFilterType;
+ typedef itk::OtsuThresholdImageFilter<ImageType,MaskImageType> 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<InternalImageType>(working_image);
+ StopCurrentStep<MaskImageType>(working_mask);
+ PrintMemory(GetVerboseMemoryFlag(), "After Otsufilter");
//--------------------------------------------------------------------
//--------------------------------------------------------------------
StartNewStep("Select labels");
// Keep right labels
- working_image = LabelizeAndSelectLabels<InternalImageType>
- (working_image,
+ working_mask = LabelizeAndSelectLabels<MaskImageType>
+ (working_mask,
GetBackgroundValue(),
GetForegroundValue(),
false,
GetLabelizeParameters2());
// Set output
- StopCurrentStep<InternalImageType>(working_image);
+ StopCurrentStep<MaskImageType>(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<InternalImageType, InternalImageType>
- (working_image, trachea_tmp, 1, -1);
+ working_mask = SetBackground<MaskImageType, MaskImageType>
+ (working_mask, trachea, 1, -1, true);
+ PrintMemory(GetVerboseMemoryFlag(), "After SetBackground");
// Dilate the trachea
static const unsigned int Dim = ImageType::ImageDimension;
KernelType structuringElement;
structuringElement.SetRadius(GetRadiusForTrachea());
structuringElement.CreateStructuringElement();
- typedef clitk::ConditionalBinaryDilateImageFilter<InternalImageType, InternalImageType, KernelType> ConditionalBinaryDilateImageFilterType;
+ typedef clitk::ConditionalBinaryDilateImageFilter<MaskImageType, MaskImageType, KernelType> 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<InternalImageType, InternalImageType>
- (trachea_tmp, working_image, -1, this->GetForegroundValue());
+ trachea = SetBackground<MaskImageType, MaskImageType>
+ (trachea, working_mask, -1, this->GetForegroundValue(), true);
// Remove the trachea
- working_image = SetBackground<InternalImageType, InternalImageType>
- (working_image, working_image, -1, this->GetBackgroundValue());
+ working_mask = SetBackground<MaskImageType, MaskImageType>
+ (working_mask, working_mask, -1, this->GetBackgroundValue(), true);
// Label
- working_image = LabelizeAndSelectLabels<InternalImageType>
- (working_image,
+ working_mask = LabelizeAndSelectLabels<MaskImageType>
+ (working_mask,
GetBackgroundValue(),
GetForegroundValue(),
false,
GetLabelizeParameters3());
// Set output
- StopCurrentStep<InternalImageType>(working_image);
+ StopCurrentStep<MaskImageType>(working_mask);
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
- typedef clitk::AutoCropFilter<InternalImageType> 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<InternalImageType, MaskImageType> CastImageFilterType;
- typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
- caster->SetInput(autocropFilter->GetOutput());
- caster->Update();
- trachea = caster->GetOutput();
+ trachea = clitk::AutoCrop<MaskImageType>(trachea, GetBackgroundValue());
StopCurrentStep<MaskImageType>(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<InternalImageType>(working_image);
+ PrintMemory(GetVerboseMemoryFlag(), "Before Autocropfilter");
+ working_mask = clitk::AutoCrop<MaskImageType>(working_mask, GetBackgroundValue());
+ StopCurrentStep<MaskImageType>(working_mask);
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Final OpenClose
- if (GetOpenClose()) {
+ if (GetOpenCloseFlag()) {
StartNewStep("Open/Close");
-
+ PrintMemory(GetVerboseMemoryFlag(), "Before OpenClose");
+
// Structuring element
typedef itk::BinaryBallStructuringElement<InternalPixelType, ImageDimension> KernelType;
KernelType structuringElement;
structuringElement.CreateStructuringElement();
// Open
- typedef itk::BinaryMorphologicalOpeningImageFilter<InternalImageType, InternalImageType, KernelType> OpenFilterType;
+ typedef itk::BinaryMorphologicalOpeningImageFilter<MaskImageType, InternalImageType, KernelType> 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<InternalImageType, InternalImageType, KernelType> CloseFilterType;
+ typedef itk::BinaryMorphologicalClosingImageFilter<MaskImageType, MaskImageType, KernelType> 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<InternalImageType> FillMaskFilterType;
+ PrintMemory(GetVerboseMemoryFlag(), "Before Fill Holes");
+ typedef clitk::FillMaskFilter<MaskImageType> 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<InternalImageType>(working_image);
+ working_mask = fillMaskFilter->GetOutput();
+ StopCurrentStep<MaskImageType>(working_mask);
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
StartNewStep("Separate Left/Right lungs");
+ PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
// Initial label
- working_image = Labelize<InternalImageType>(working_image,
- GetBackgroundValue(),
- false,
- GetMinimalComponentSize());
+ working_mask = Labelize<MaskImageType>(working_mask,
+ GetBackgroundValue(),
+ false,
+ GetMinimalComponentSize());
+
+ PrintMemory(GetVerboseMemoryFlag(), "After Labelize");
// Count the labels
- typedef itk::StatisticsImageFilter<InternalImageType> StatisticsImageFilterType;
+ typedef itk::StatisticsImageFilter<MaskImageType> 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<Dim;i++) radius[i]=1;
- typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> DecomposeAndReconstructFilterType;
+ typedef clitk::DecomposeAndReconstructImageFilter<MaskImageType,MaskImageType> DecomposeAndReconstructFilterType;
typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
- decomposeAndReconstructFilter->SetInput(working_image);
+ decomposeAndReconstructFilter->SetInput(working_mask);
decomposeAndReconstructFilter->SetVerbose(true);
decomposeAndReconstructFilter->SetRadius(radius);
decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
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<InternalImageType> ThresholdImageFilterType;
+ typedef itk::ThresholdImageFilter<MaskImageType> 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<InternalImageType> (working_image);
-
- // Final Cast
- StartNewStep("Cast the lung mask");
- typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
- typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
- caster->SetInput(working_image);
- caster->Update();
- output = caster->GetOutput();
+ working_mask = thresholdFilter->GetOutput();
+ StopCurrentStep<MaskImageType> (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 <class TImageType>
+void
+clitk::ExtractLungFilter<TImageType>::
+GenerateInputRequestedRegion() {
+ // DD("GenerateInputRequestedRegion (nothing?)");
}
//--------------------------------------------------------------------
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();
}
//--------------------------------------------------------------------
// 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]) {
}
skip += 5;
}
+ else {
+ // DD(m_Seeds[0]);
+ // DD(m_Seeds.size());
+ }
}
}
return (m_Seeds.size() != 0);
TracheaRegionGrowing()
{
// Explosion controlled region growing
- typedef clitk::ExplosionControlledThresholdConnectedImageFilter<ImageType, InternalImageType> ImageFilterType;
+ PrintMemory(GetVerboseMemoryFlag(), "Before ExplosionControlledThresholdConnectedImageFilter");
+ typedef clitk::ExplosionControlledThresholdConnectedImageFilter<ImageType, MaskImageType> ImageFilterType;
typename ImageFilterType::Pointer f= ImageFilterType::New();
f->SetInput(working_input);
- f->SetVerbose(false);
f->SetLower(-2000);
f->SetUpper(GetUpperThresholdForTrachea());
f->SetMinimumLowerThreshold(-2000);
f->SetMultiplier(GetMultiplierForTrachea());
f->SetThresholdStepSize(GetThresholdStepSizeForTrachea());
f->SetMinimumThresholdStepSize(1);
- f->VerboseOn();
+ f->SetVerbose(GetVerboseRegionGrowingFlag());
for(unsigned int i=0; i<m_Seeds.size();i++) {
f->AddSeed(m_Seeds[i]);
// DD(m_Seeds[i]);
}
f->Update();
-
- writeImage<InternalImageType>(f->GetOutput(), "trg.mhd");
-
+ PrintMemory(GetVerboseMemoryFlag(), "After RG update");
+
// take first (main) connected component
- trachea_tmp = Labelize<InternalImageType>(f->GetOutput(),
- GetBackgroundValue(),
- true,
- GetMinimalComponentSize());
- trachea_tmp = KeepLabels<InternalImageType>(trachea_tmp,
+ trachea = Labelize<MaskImageType>(f->GetOutput(),
+ GetBackgroundValue(),
+ true,
+ 1000);//GetMinimalComponentSize());
+ PrintMemory(GetVerboseMemoryFlag(), "After Labelize");
+ trachea = KeepLabels<MaskImageType>(trachea,
GetBackgroundValue(),
GetForegroundValue(),
1, 1, false);
+ PrintMemory(GetVerboseMemoryFlag(), "After KeepLabels");
}
//--------------------------------------------------------------------
ComputeTracheaVolume()
{
typedef itk::ImageRegionConstIterator<InternalImageType> IteratorType;
- IteratorType iter(trachea_tmp, trachea_tmp->GetLargestPossibleRegion());
+ IteratorType iter(trachea, trachea->GetLargestPossibleRegion());
iter.GoToBegin();
double volume = 0.0;
while (!iter.IsAtEnd()) {
++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;
}
//--------------------------------------------------------------------
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<MaskImageType>(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<InternalImageType>(trachea_tmp);
+ StopCurrentStep<MaskImageType>(trachea);
}
else { // Trachea not found
this->SetWarning("* WARNING * No seed found for trachea.");
//--------------------------------------------------------------------
void SetArgsInfo(const ArgsInfoType & a);
+ template<class FilterType>
+ void SetOptionsFromArgsInfoToFilter(FilterType * f);
//--------------------------------------------------------------------
// Main function called each time the filter is updated
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void clitk::ExtractLungGenericFilter<ArgsInfoType>::
+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
//--------------------------------------------------------------------
this->SetFilterBase(filter);
// Set global Options
- filter->SetArgsInfo(mArgsInfo);
filter->SetInput(input);
+ SetOptionsFromArgsInfoToFilter<FilterType>(filter);
// Go !
filter->Update();
clitk::ExtractLymphStationsFilter<TImageType>::
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
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<MaskImageType>(m_Support, 2,
+ clitk::CropImageAlongOneAxis<MaskImageType>(m_Mediastinum, 2,
inf,
m_TopOfAorticArchInMM, true,
GetBackgroundValue());
StopCurrentStep<MaskImageType>(m_Working_Support);
-
- m_Station4RL = m_Working_Support;
}
//--------------------------------------------------------------------
// - very caudal part : right upper lobe pulmonary vein"
// AAV ??
- // Constraint at right from the SVC
- MaskImagePointer svc = GetAFDB()->template GetImage<MaskImageType>("SVC");
- typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> 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 <MaskImageType>("Trachea");
MaskImagePointer crop_trachea =
- clitk::ResizeImageLike<MaskImageType>(m_Trachea, m_Working_Support, GetBackgroundValue());
+ clitk::ResizeImageLike<MaskImageType>(Trachea, m_Working_Support, GetBackgroundValue());
writeImage<MaskImageType>(crop_trachea, "croptrachea.mhd");
// Extract all the slices
- typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
- typedef typename ExtractSliceFilterType::SliceType SliceType;
- typename ExtractSliceFilterType::Pointer
- extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(crop_trachea);
- extractSliceFilter->SetDirection(2);
- extractSliceFilter->Update();
- std::vector<typename SliceType::Pointer> trachea_slices;
- extractSliceFilter->GetOutputSlices(trachea_slices);
+ std::vector<typename MaskSliceType::Pointer> bronchi_slices;
+ clitk::ExtractSlices<MaskImageType>(crop_trachea, 2, bronchi_slices);
+
+ // List of midpoints
+ std::vector<MaskImagePointType> midpoints;
+
+ // Add mid points below carina, from foot to head
+ for(uint i=0; i<m_LeftMostInRightBronchus.size(); i++) {
+ MaskImagePointType p;
+ p[0] = (m_LeftMostInRightBronchus[i][0]+m_RightMostInLeftBronchus[i][0])/2.0;
+ p[1] = (m_LeftMostInRightBronchus[i][1]+m_RightMostInLeftBronchus[i][1])/2.0;
+ p[2] = m_LeftMostInRightBronchus[i][2];
+ midpoints.push_back(p);
+ }
+
+ // Crop the trachea above the carina. Find largest Z position
+ MaskImageIndexType p = Trachea->GetLargestPossibleRegion().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<MaskImageType>(Trachea, 2,
+ m_CarinaZ,
+ maxZ, true,
+ GetBackgroundValue());
+ writeImage<MaskImageType>(m_above_carina, "above.mhd");
+
+ // Extract all the slices
+ std::vector<typename MaskSliceType::Pointer> trachea_slices;
+ clitk::ExtractSlices<MaskImageType>(m_above_carina, 2, trachea_slices);
+
+ // Find centroid of the trachea in each slice
+ std::vector<MaskImagePointType> points;
+ typedef typename MaskSliceType::PointType SlicePointType;
+ SlicePointType previous;
+ // Start from patient top (head)
+ for(uint i=0; i<trachea_slices.size(); i++) {
+ // Labelize
+ trachea_slices[i] = Labelize<MaskSliceType>(trachea_slices[i], GetBackgroundValue(), true, 10);
+ // Get centroid
+ std::vector<SlicePointType> c;
+ clitk::ComputeCentroids<MaskSliceType>(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<midpoints.size(); i++) {
+ osp << i << " " << midpoints[i][0] << " "
+ << midpoints[i][1] << " " << midpoints[i][2] << " 0 0 " << std::endl;
+ }
+ osp.close();
+
+ // Create and allocate left and right part of the support (we create
+ // images because we will then crop them)
+ m_LeftSupport = clitk::NewImageLike<MaskImageType>(m_Working_Support);
+ m_RightSupport = clitk::NewImageLike<MaskImageType>(m_Working_Support);
+
+ // Loop on current support, slice by slice
+ typedef itk::ImageSliceIteratorWithIndex<MaskImageType> 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 <index this is Right part. Left otherwise
+ if (iter.GetIndex()[0]<index[0]) {
+ iterR.Set(iter.Get());
+ iterL.Set(GetBackgroundValue());
+ }
+ else {
+ iterL.Set(iter.Get());
+ iterR.Set(GetBackgroundValue());
+ }
+ ++iter;
+ ++iterL;
+ ++iterR;
+ }
+ iter.NextLine();
+ iterL.NextLine();
+ iterR.NextLine();
+
+ }
+ iter.NextSlice();
+ iterL.NextSlice();
+ iterR.NextSlice();
+ ++slice;
+ }
+
+ // Auto crop !
+ m_LeftSupport = clitk::AutoCrop<MaskImageType>(m_LeftSupport, GetBackgroundValue());
+ m_RightSupport = clitk::AutoCrop<MaskImageType>(m_RightSupport, GetBackgroundValue());
+ writeImage<MaskImageType>(m_LeftSupport, "lsac.mhd");
+ writeImage<MaskImageType>(m_RightSupport, "rsac.mhd");
+
+ StopCurrentStep<MaskImageType>(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<MaskImageType>("SVC");
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> 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<MaskImageType>(m_RightSupport, GetBackgroundValue());
}
//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+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<MaskImageType>("Aorta");
+ // Crop according to current support
+ aorta = clitk::ResizeImageLike<MaskImageType>(aorta, m_RightSupport, GetBackgroundValue());
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> 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<MaskImageType>(m_RightSupport);
+
+ // POST -> horizontal lines bronchus --> points dectection in S7 to store.
+}
+//--------------------------------------------------------------------
+
+
//--------------------------------------------------------------------
template <class TImageType>
void
clitk::ExtractLymphStationsFilter<TImageType>::
ExtractStation_7_SI_Limits()
{
- // Local variables
- double m_CarinaZPositionInMM;
- double m_MiddleLobeBronchusZPositionInMM;
-
// Get Inputs
- m_Trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");
- m_CarinaZPositionInMM = GetAFDB()->GetPoint3D("carina", 2);
- DD(m_CarinaZPositionInMM);
- m_MiddleLobeBronchusZPositionInMM = GetAFDB()->GetPoint3D("rightMiddleLobeBronchus", 2);
- DD(m_MiddleLobeBronchusZPositionInMM);
+ MaskImagePointer Trachea = GetAFDB()->template GetImage <MaskImageType>("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<MaskImageType>(m_Support, 2,
- m_MiddleLobeBronchusZPositionInMM,
- m_CarinaZPositionInMM, true,
+ clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2,
+ m_OriginOfRightMiddleLobeBronchusZ,
+ m_CarinaZ, true,
GetBackgroundValue());
- StopCurrentStep<MaskImageType>(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<MaskImageType>(m_Trachea, 2,
- m_MiddleLobeBronchusZPositionInMM,
- m_CarinaZPositionInMM, true,
+ clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2,
+ m_OriginOfRightMiddleLobeBronchusZ,
+ m_CarinaZ, true,
GetBackgroundValue());
- StopCurrentStep<MaskImageType>(m_working_trachea);
- m_Station7 = m_Working_Support;
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["7"] = m_Working_Support;
}
//--------------------------------------------------------------------
+
//--------------------------------------------------------------------
template <class TImageType>
void
{
// ----------------------------------------------------------------
// 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<MaskImageType>(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<MaskImageType> SliceIteratorType;
SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
iter.SetFirstDirection(0);
int maxLabel=0;
while (!iter.IsAtReverseEndOfSlice()) {
while (!iter.IsAtReverseEndOfLine()) {
- // DD(iter.GetIndex());
if (iter.Get() > maxLabel) maxLabel = iter.Get();
--iter;
}
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<MaskImageType, LabelMapType> ImageToMapFilterType;
- typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New();
- typedef itk::ShapeLabelMapFilter<LabelMapType, MaskImageType> 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<ImagePointType> c;
+ clitk::ComputeCentroids<MaskImageType>(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<MaskImageType>(m_working_trachea);
//-----------------------------------------------------
- StartNewStep("Left limits with bronchus (slice by slice)");
// Select LeftLabel (set one label to Backgroundvalue)
m_LeftBronchus =
SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea,
- rightLabel, GetBackgroundValue());
+ rightLabel, GetBackgroundValue(), false);
m_RightBronchus =
SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea,
- leftLabel, GetBackgroundValue());
- writeImage<MaskImageType>(m_LeftBronchus, "left.mhd");
- writeImage<MaskImageType>(m_RightBronchus, "right.mhd");
+ leftLabel, GetBackgroundValue(), false);
+ StartNewStep("[Station7] Limits with bronchus (slice by slice) : RightTo left bronchus");
m_Working_Support =
clitk::SliceBySliceRelativePosition<MaskImageType>(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<MaskImageType>(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<MaskImageType>(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<MaskImageType>(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<MaskImageType>(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<MaskImageType>(m_Working_Support,
m_RightBronchus,
clitk::ExtractLymphStationsFilter<TImageType>::
ExtractStation_7_Posterior_Limits()
{
- StartNewStep("Posterior limits");
-
- // Left Bronchus slices
- typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
- typedef typename ExtractSliceFilterType::SliceType SliceType;
- typename ExtractSliceFilterType::Pointer
- extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(m_LeftBronchus);
- extractSliceFilter->SetDirection(2);
- extractSliceFilter->Update();
- std::vector<typename SliceType::Pointer> leftBronchusSlices;
- extractSliceFilter->GetOutputSlices(leftBronchusSlices);
-
- // Right Bronchus slices
- extractSliceFilter = ExtractSliceFilterType::New();
- extractSliceFilter->SetInput(m_RightBronchus);
- extractSliceFilter->SetDirection(2);
- extractSliceFilter->Update();
- std::vector<typename SliceType::Pointer> rightBronchusSlices ;
- extractSliceFilter->GetOutputSlices(rightBronchusSlices);
-
- assert(leftBronchusSlices.size() == rightBronchusSlices.size());
-
- std::vector<MaskImageType::PointType> leftPoints;
- std::vector<MaskImageType::PointType> rightPoints;
- for(uint i=0; i<leftBronchusSlices.size(); i++) {
- // Keep main CCL
- leftBronchusSlices[i] = Labelize<SliceType>(leftBronchusSlices[i], 0, true, 10);
- leftBronchusSlices[i] = KeepLabels<SliceType>(leftBronchusSlices[i],
- GetBackgroundValue(),
- GetForegroundValue(), 1, 1, true);
- rightBronchusSlices[i] = Labelize<SliceType>(rightBronchusSlices[i], 0, true, 10);
- rightBronchusSlices[i] = KeepLabels<SliceType>(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<SliceType>(leftBronchusSlices[i],
- GetBackgroundValue(),
- 0, false, a, 0);
- // find post most point in left, not far away from rightMost
- SliceType::PointType p =
- clitk::FindExtremaPointInAGivenDirection<SliceType>(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<SliceType>(rightBronchusSlices[i],
- GetBackgroundValue(),
- 0, true, a, 0);
- // find post most point in left, not far away from leftMost
- p = clitk::FindExtremaPointInAGivenDirection<SliceType>(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<leftBronchusSlices.size(); i++) {
- osl << i << " " << leftPoints[i][0] << " " << leftPoints[i][1]
- << " " << leftPoints[i][2] << " 0 0 " << std::endl;
- osr << i << " " << rightPoints[i][0] << " " << rightPoints[i][1]
- << " " << rightPoints[i][2] << " 0 0 " << std::endl;
+ std::ofstream osrl; openFileForWriting(osrl, "osrl.txt"); osrl << "LANDMARKS1" << std::endl;
+ std::ofstream osal; openFileForWriting(osal, "osal.txt"); osal << "LANDMARKS1" << std::endl;
+ std::ofstream ospl; openFileForWriting(ospl, "ospl.txt"); ospl << "LANDMARKS1" << std::endl;
+ std::ofstream osrr; openFileForWriting(osrr, "osrr.txt"); osrr << "LANDMARKS1" << std::endl;
+ std::ofstream osar; openFileForWriting(osar, "osar.txt"); osar << "LANDMARKS1" << std::endl;
+ std::ofstream ospr; openFileForWriting(ospr, "ospr.txt"); ospr << "LANDMARKS1" << std::endl;
+
+ for(uint i=0; i<m_RightMostInLeftBronchus.size(); i++) {
+ osrl << i << " " << m_RightMostInLeftBronchus[i][0] << " " << m_RightMostInLeftBronchus[i][1]
+ << " " << m_RightMostInLeftBronchus[i][2] << " 0 0 " << std::endl;
+ osal << i << " " << m_AntMostInLeftBronchus[i][0] << " " << m_AntMostInLeftBronchus[i][1]
+ << " " << m_AntMostInLeftBronchus[i][2] << " 0 0 " << std::endl;
+ ospl << i << " " << m_PostMostInLeftBronchus[i][0] << " " << m_PostMostInLeftBronchus[i][1]
+ << " " << m_PostMostInLeftBronchus[i][2] << " 0 0 " << std::endl;
+
+ osrr << i << " " << m_LeftMostInRightBronchus[i][0] << " " << m_LeftMostInRightBronchus[i][1]
+ << " " << m_LeftMostInRightBronchus[i][2] << " 0 0 " << std::endl;
+ osar << i << " " << m_AntMostInRightBronchus[i][0] << " " << m_AntMostInRightBronchus[i][1]
+ << " " << m_AntMostInRightBronchus[i][2] << " 0 0 " << std::endl;
+ ospr << i << " " << m_PostMostInRightBronchus[i][0] << " " << m_PostMostInRightBronchus[i][1]
+ << " " << m_PostMostInRightBronchus[i][2] << " 0 0 " << std::endl;
}
- osl.close();
- osr.close();
+ osrl.close();
+ osal.close();
+ ospl.close();
// Now uses these points to limit, slice by slice
// http://www.gamedev.net/community/forums/topic.asp?topic_id=542870
MaskImageType::PointType B;
MaskImageType::PointType C;
while (!iter.IsAtEnd()) {
- A = leftPoints[i];
- B = rightPoints[i];
+ A = m_PostMostInLeftBronchus[i];
+ B = m_PostMostInRightBronchus[i];
C = A;
C[1] -= 10; // I know I must keep this point
double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
}
//-----------------------------------------------------
- // StartNewStep("Anterior limits");
+ // StartNewStep("[Station7] Anterior limits");
// MISSING FROM NOW
m_Station7 = m_Working_Support;
}
//--------------------------------------------------------------------
+
+
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"
option "input" i "Input filename" string no
option "output" o "Output lungs mask filename" string no
-
-
+section "Options for Station 8"
+option "maxAntSpine" - "Distance max to anterior part of the spine in mm" double no default="10"
+option "esophagusDilatationForAnt" - "Dilatation of esophagus, in mm, for 'anterior' limits (default=15,2,1)" double no multiple
+option "esophagusDilatationForRight" - "Dilatation of esophagus, in mm, for 'right' limits (default=5,10,1)" double no multiple
+option "fuzzyThresholdForS8" - "Threshold for 'Post' to dilated Esophagus" double default="0.5" no
typedef typename MaskImageType::IndexType MaskImageIndexType;
typedef typename MaskImageType::PointType MaskImagePointType;
+ typedef itk::Image<MaskImagePixelType, 2> MaskSliceType;
+
/** ImageDimension constants */
itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
FILTERBASE_INIT;
- /** Main options (from ggo) */
- template <class ArgsInfoType>
- 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);
virtual void GenerateData();
ImageConstPointer m_Input;
- MaskImagePointer m_Support;
+ MaskImagePointer m_Mediastinum;
MaskImagePointer m_Working_Support;
- MaskImagePointer m_Output;
+ std::map<std::string, MaskImagePointer> 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<MaskImageType::PointType> 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
#ifndef ITK_MANUAL_INSTANTIATION
#include "clitkExtractLymphStationsFilter.txx"
+#include "clitkExtractLymphStation_8.txx"
#include "clitkExtractLymphStation_7.txx"
#include "clitkExtractLymphStation_4RL.txx"
#endif
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");
//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-template <class TImageType>
-template <class ArgsInfoType>
-void
-clitk::ExtractLymphStationsFilter<TImageType>::
-SetArgsInfo(ArgsInfoType & argsinfo) {
- DD("SetArgsInfo");
-}
-//--------------------------------------------------------------------
-
-
//--------------------------------------------------------------------
template <class TImageType>
void
// Get inputs
LoadAFDB();
m_Input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
- m_Support = GetAFDB()->template GetImage <MaskImageType>("mediastinum");
-
- //
- typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BFilter;
- BFilter::Pointer merge = BFilter::New();
+ m_Mediastinum = GetAFDB()->template GetImage <MaskImageType>("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<MaskImageType>(m_Station4RL, "s4rl.mhd");
+
+ //
+ // typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BFilter;
+ //BFilter::Pointer merge = BFilter::New();
// writeImage<MaskImageType>(m_Output, "ouput.mhd");
//writeImage<MaskImageType>(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();
*/
}
//--------------------------------------------------------------------
DD("GenerateData, graft output");
// Final Step -> graft output (if SetNthOutput => redo)
- this->GraftOutput(m_Output);
+ this->GraftOutput(m_ListOfStations["8"]);
}
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+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 <class TImageType>
void
clitk::ExtractLymphStationsFilter<TImageType>::
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();
void
clitk::ExtractLymphStationsFilter<TImageType>::
ExtractStation_4RL() {
- DD("ExtractStation_4RL");
- writeImage<MaskImageType>(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 <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+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<typename MaskSliceType::Pointer> slices;
+ clitk::ExtractSlices<MaskImageType>(input, 2, slices);
+
+ // Loop on slices
+ bool found;
+ for(uint i=0; i<slices.size(); i++) {
+ /*
+ // Keep main CCL
+ slices[i] = Labelize<MaskSliceType>(slices[i], 0, true, 10);
+ slices[i] = KeepLabels<MaskSliceType>(slices[i],
+ GetBackgroundValue(),
+ GetForegroundValue(), 1, 1, true);
+ */
+
+ // ------- Find rightmost or leftmost point -------
+ MaskSliceType::PointType LRMost;
+ found =
+ clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskSliceType>(slices[i],
+ GetBackgroundValue(),
+ 1, false, LRMost,
+ distance_max_from_center_point,
+ postMost);
+ // ------- Find antmost point -------
+ MaskSliceType::PointType antMost;
+ found =
+ clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(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<MaskImageType>::Convert2DTo3D(LRMost, input, i, p);
+ LR.push_back(p);
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(antMost, input, i, p);
+ Ant.push_back(p);
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(postMost, input, i, p);
+ Post.push_back(p);
+ }
+ }
+}
+//--------------------------------------------------------------------
#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
itkTypeMacro(ExtractLymphStationsGenericFilter, LightObject);
//--------------------------------------------------------------------
+ // Options for the GenericFilter
void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Options for the Filter
template<class FilterType>
- void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
+ void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
//--------------------------------------------------------------------
// Main function called each time the filter is updated
clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::
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);
}
//--------------------------------------------------------------------
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"
/** ImageDimension constants */
itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
- // Set all options at a time
- template<class ArgsInfoType>
- 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();
double m_FuzzyThreshold1;
double m_FuzzyThreshold2;
double m_FuzzyThreshold3;
- double m_DistanceMaxToAnteriorPartOfTheSpine;
- bool m_UseBones;
+ bool m_UseBones;
double m_UpperThreshold;
double m_LowerThreshold;
SetFuzzyThreshold2(0.6);
SetFuzzyThreshold3(0.05);
- SetDistanceMaxToAnteriorPartOfTheSpine(10);
SetOutputMediastinumFilename("mediastinum.mhd");
UseBonesOff();
//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-template <class ImageType>
-template<class ArgsInfoType>
-void
-clitk::ExtractMediastinumFilter<ImageType>::
-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 <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
GenerateInputRequestedRegion()
{
- //DD("GenerateInputRequestedRegion");
+ // DD("GenerateInputRequestedRegion");
// Do not call default
- // Superclass::GenerateInputRequestedRegion();
- // DD("End GenerateInputRequestedRegion");
+ // Superclass::GenerateInputRequestedRegion();
+ // DD("End GenerateInputRequestedRegion");
}
//--------------------------------------------------------------------
void
clitk::ExtractMediastinumFilter<ImageType>::
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<const ImageType*>(itk::ProcessObject::GetInput(0));
- MaskImagePointer patient = GetAFDB()->template GetImage <MaskImageType>("patient");
- MaskImagePointer lung = GetAFDB()->template GetImage <MaskImageType>("lungs");
- MaskImagePointer bones = GetAFDB()->template GetImage <MaskImageType>("bones");
- MaskImagePointer trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");
+ MaskImagePointer patient = GetAFDB()->template GetImage <MaskImageType>("Patient");
+ MaskImagePointer lung = GetAFDB()->template GetImage <MaskImageType>("Lungs");
+ MaskImagePointer bones;
+ if (GetUseBones()) {
+ bones = GetAFDB()->template GetImage <MaskImageType>("Bones");
+ }
+ MaskImagePointer trachea = GetAFDB()->template GetImage <MaskImageType>("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");
cropFilter->Update();
output = cropFilter->GetOutput();
this->template StopCurrentStep<MaskImageType>(output);
-
+
//--------------------------------------------------------------------
// Step 2: Crop support (previous) to bones extend in AP
if (GetUseBones()) {
//--------------------------------------------------------------------
// 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<MaskImageType> BoolFilterType;
typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
boolFilter->InPlaceOn();
// (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<MaskImageType, MaskImageType>(lung, lung, 2, 0);
- ImagePointer left_lung = clitk::SetBackground<MaskImageType, MaskImageType>(lung, lung, 1, 0);
- writeImage<MaskImageType>(right_lung, "right.mhd");
- writeImage<MaskImageType>(left_lung, "left.mhd");
- */
+
+ // The following cannot be "inplace" because mask is the same than input ...
+ MaskImagePointer right_lung =
+ clitk::SetBackground<MaskImageType, MaskImageType>(lung, lung, 2, 0, false);
+ MaskImagePointer left_lung =
+ clitk::SetBackground<MaskImageType, MaskImageType>(lung, lung, 1, 0, false);
+ right_lung = clitk::ResizeImageLike<MaskImageType>(right_lung, output, GetBackgroundValue());
+ left_lung = clitk::ResizeImageLike<MaskImageType>(left_lung, output, GetBackgroundValue());
+ // writeImage<MaskImageType>(right_lung, "right.mhd");
+ // writeImage<MaskImageType>(left_lung, "left.mhd");
+
typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> 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<MaskImageType>(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();
roiFilter->ReleaseDataFlagOff();
roiFilter->Update();
bones_ant = roiFilter->GetOutput();
- writeImage<MaskImageType>(bones_ant, "b_ant.mhd");
+ // writeImage<MaskImageType>(bones_ant, "b_ant.mhd");
// POST part
roiFilter = ROIFilterType::New();
index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1;
roiFilter->ReleaseDataFlagOff();
roiFilter->Update();
bones_post = roiFilter->GetOutput();
- writeImage<MaskImageType>(bones_post, "b_post.mhd");
+ // writeImage<MaskImageType>(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<MaskImageType>(output, "post.mhd");
+ // writeImage<MaskImageType>(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();
GetForegroundValue(), 1, 1, 0);
this->template StopCurrentStep<MaskImageType>(output);
- //--------------------------------------------------------------------
- // Step 7 : Slice by Slice to optimize posterior part
- // Warning slice does not necesseraly correspond between 'output' and 'bones'
- typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
- typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
- typedef typename ExtractSliceFilterType::SliceType SliceType;
- std::vector<typename SliceType::Pointer> mSlices;
- if (GetUseBones()) {
- StartNewStep("Rafine posterior part according to vertebral body");
- extractSliceFilter->SetInput(bones_post);
- extractSliceFilter->SetDirection(2);
- extractSliceFilter->Update();
- std::vector<double> mVertebralAntPositionBySlice;
- extractSliceFilter->GetOutputSlices(mSlices);
- for(unsigned int i=0; i<mSlices.size(); i++) {
- mSlices[i] = Labelize<SliceType>(mSlices[i], 0, true, 10);
- mSlices[i] = KeepLabels<SliceType>(mSlices[i],
- GetBackgroundValue(),
- GetForegroundValue(), 1, 2, true); // keep two first
- // Find most anterior point (start of the vertebral)
- typename itk::ImageRegionIteratorWithIndex<SliceType>
- 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; i<mSlices.size(); i++) {
- // Compute index
- MaskImagePointType point;
- point[0] = 0;
-
- //TODO 10 mm OPTION
-
- point[1] = mVertebralAntPositionBySlice[i]+GetDistanceMaxToAnteriorPartOfTheSpine();// ADD ONE CM
- point[2] = bones_post->GetOrigin()[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<MaskImageType> it(output, region);
- it.GoToBegin();
- while (!it.IsAtEnd()) {
- it.Set(GetBackgroundValue());
- ++it;
- }
- }
- }
- }
- this->template StopCurrentStep<MaskImageType>(output);
- }
//--------------------------------------------------------------------
// Step 8: Trial segmentation KMeans
ImagePointer working_input = cropLikeFilter->GetOutput();
writeImage<ImageType>(working_input, "crop-input.mhd");
// Set bG at -1000
- working_input = clitk::SetBackground<ImageType, MaskImageType>(working_input, output, GetBackgroundValue(), -1000);
+ working_input = clitk::SetBackground<ImageType, MaskImageType>(working_input, output, GetBackgroundValue(), -1000, true);
writeImage<ImageType>(working_input, "crop-input2.mhd");
// Kmeans
typedef itk::ScalarImageKmeansImageFilter<ImageType> KMeansFilterType;
}
MaskImageType::Pointer kmeans = kmeansFilter->GetOutput();
kmeans = clitk::SetBackground<MaskImageType, MaskImageType>(kmeans, kmeans,
- 1, GetBackgroundValue());
+ 1, GetBackgroundValue(), true);
writeImage<MaskImageType>(kmeans, "kmeans.mhd");
// Get final results, and remove from current mask
boolFilter = BoolFilterType::New();
// 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);
// 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();
StartNewStep("Slice by Slice keep only one component");
typedef clitk::ExtractSliceFilter<MaskImageType> 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<typename SliceType::Pointer>
- mSlices.clear();
+ std::vector<typename SliceType::Pointer> mSlices;
extractSliceFilter->GetOutputSlices(mSlices);
for(unsigned int i=0; i<mSlices.size(); i++) {
mSlices[i] = Labelize<SliceType>(mSlices[i], 0, true, 100);
//--------------------------------------------------------------------
// 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<ImageType> CropLikeFilterType;
- typename CropLikeFilterType::Pointer cropLikeFilter = CropLikeFilterType::New();
- cropLikeFilter->SetInput(input);
- cropLikeFilter->SetCropLikeImage(output);
- cropLikeFilter->Update();
- ImagePointer working_input = cropLikeFilter->GetOutput();
- writeImage<ImageType>(working_input, "crop-ct.mhd");
- // Binarize
- typedef itk::BinaryThresholdImageFilter<ImageType, MaskImageType> 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<MaskImageType>(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<MaskImageType>(output);
+ if (0) {
+ StartNewStep("Remove hypersignal (bones and injected part");
+ // Crop initial ct like current support
+ typedef CropLikeImageFilter<ImageType> CropLikeFilterType;
+ typename CropLikeFilterType::Pointer cropLikeFilter = CropLikeFilterType::New();
+ cropLikeFilter->SetInput(input);
+ cropLikeFilter->SetCropLikeImage(output);
+ cropLikeFilter->Update();
+ ImagePointer working_input = cropLikeFilter->GetOutput();
+ // writeImage<ImageType>(working_input, "crop-ct.mhd");
+ // Binarize
+ typedef itk::BinaryThresholdImageFilter<ImageType, MaskImageType> 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<MaskImageType>(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<MaskImageType>(output);
+ }
//--------------------------------------------------------------------
// Step 10 : AutoCrop
clitk::ExtractMediastinumFilter<ImageType>::
GenerateData()
{
- DD("GenerateData");
this->GraftOutput(output);
// Store image filenames into AFDB
- GetAFDB()->SetImageFilename("mediastinum", this->GetOutputMediastinumFilename());
+ GetAFDB()->SetImageFilename("Mediastinum", this->GetOutputMediastinumFilename());
WriteAFDB();
}
//--------------------------------------------------------------------
itkTypeMacro(ExtractMediastinumGenericFilter, LightObject);
//--------------------------------------------------------------------
+ // Options for the GenericFilter
void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Options for the Filter
+ template<class FilterType>
+ void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
//--------------------------------------------------------------------
// Main function called each time the filter is updated
//--------------------------------------------------------------------
template<class ArgsInfoType>
-clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::ExtractMediastinumGenericFilter():
+clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::
+ExtractMediastinumGenericFilter():
ImageToImageGenericFilter<Self>("ExtractMediastinum")
{
// Default values
//--------------------------------------------------------------------
template<class ArgsInfoType>
template<unsigned int Dim>
-void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::InitializeImageType()
+void
+clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::
+InitializeImageType()
{
ADD_IMAGE_TYPE(Dim, short);
- // ADD_IMAGE_TYPE(Dim, short);
- // ADD_IMAGE_TYPE(Dim, int);
- // ADD_IMAGE_TYPE(Dim, float);
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
template<class ArgsInfoType>
-void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a)
+void
+clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::
+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<class ArgsInfoType>
+template<class FilterType>
+void
+clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::
+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
//--------------------------------------------------------------------
{
// Reading input
typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
- // typename ImageType::Pointer patient = this->template GetInput<ImageType>(0);
- // typename ImageType::Pointer lung = this->template GetInput<ImageType>(1);
- // typename ImageType::Pointer bones = this->template GetInput<ImageType>(2);
- // typename ImageType::Pointer trachea = this->template GetInput<ImageType>(3);
// Create filter
typedef clitk::ExtractMediastinumFilter<ImageType> FilterType;
// 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<FilterType>(filter);
// Go !
filter->Update();
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<class ArgsInfoType>
- 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();
#include "clitkSetBackgroundImageFilter.h"
#include "clitkDecomposeAndReconstructImageFilter.h"
#include "clitkAutoCropFilter.h"
+#include "clitkMemoryUsage.h"
// itk
#include "itkBinaryThresholdImageFilter.h"
//--------------------------------------------------------------------
-//--------------------------------------------------------------------
-template <class TInputImageType>
-template<class ArgsInfoType>
-void
-clitk::ExtractPatientFilter<TInputImageType>::
-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 <class TInputImageType>
void
clitk::ExtractPatientFilter<TInputImageType>::
GenerateOutputInformation() {
+ clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK
+
Superclass::GenerateOutputInformation();
input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
// Final Graft
this->GraftOutput(output);
// Store image filename into AFDB
- GetAFDB()->SetImageFilename("patient", this->GetOutputPatientFilename());
+ GetAFDB()->SetImageFilename("Patient", this->GetOutputPatientFilename());
WriteAFDB();
}
//--------------------------------------------------------------------