--- /dev/null
+#=========================================================
+
+INCLUDE(${PROJECT_SOURCE_DIR}/cmake/common.cmake)
+
+#=========================================================
+
+SET( CMAKE_VERBOSE_MAKEFILE off)
+
+#=========================================================
+
+WRAP_GGO(clitkSegmentationFilters_GGO_C
+ clitkFillMask.ggo
+ clitkConnectedComponentLabeling.ggo
+ clitkExtractLung.ggo
+ clitkExtractPatient.ggo
+ clitkExtractBones.ggo
+ clitkExtractMediastinum.ggo
+ clitkExtractLymphStations.ggo
+)
+
+SET(clitkSegmentationFilters_SRC
+ ${clitkSegmentationFilters_GGO_C}
+)
+
+ADD_LIBRARY(clitkSegmentationFilters STATIC ${clitkSegmentationFilters_SRC})
+
+ADD_EXECUTABLE(clitkTestFilter clitkTestFilter.cxx clitkTestFilter_ggo.c)
+TARGET_LINK_LIBRARIES(clitkTestFilter clitkCommon ITKIO clitkSegmentationFilters ITKStatistics)
+
+## Segmentation part
+
+ADD_EXECUTABLE(clitkConnectedComponentLabeling clitkConnectedComponentLabeling.cxx)
+TARGET_LINK_LIBRARIES(clitkConnectedComponentLabeling clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkFillMask clitkFillMask.cxx clitkFillMaskGenericFilter.cxx)
+TARGET_LINK_LIBRARIES(clitkFillMask clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractPatient clitkExtractPatient.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractPatient clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractLung clitkExtractLung.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractLung clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractBones clitkExtractBones.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractBones clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractMediastinum clitkExtractMediastinum.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractMediastinum clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
+
+ADD_EXECUTABLE(clitkExtractLymphStations clitkExtractLymphStations.cxx)
+TARGET_LINK_LIBRARIES(clitkExtractLymphStations clitkCommon ITKIO ITKStatistics clitkSegmentationFilters)
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkConnectedComponentLabeling_ggo.h"
+#include "clitkConnectedComponentLabelingGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+ // Init command line
+ GGO(clitkConnectedComponentLabeling, args_info);
+ CLITK_INIT;
+
+ // Filter
+ typedef clitk::ConnectedComponentLabelingGenericFilter<args_info_clitkConnectedComponentLabeling> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+
+ filter->SetArgsInfo(args_info);
+ filter->Update();
+
+ if (filter->HasError()) {
+ std::cout << filter->GetLastError() << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkConnectedComponentLabeling.ggo
+package "clitkConnectedComponentLabeling"
+version "1.0"
+purpose "Basic segmentation : connected component labeling "
+
+option "config" - "Config file" string no
+option "verbose" v "Verbose" flag off
+option "imagetypes" - "Display allowed image types" flag off
+option "verboseOption" - "Display options values" flag off
+
+section "I/O"
+
+option "input" i "Input image filename" string yes
+option "inputBG" - "Input Background" int default="0" no
+option "output" o "Output filename" string yes
+
+section "Labelize"
+
+option "minSize" - "Minimum component size in voxels" int no default="100"
+option "full" - "Full connecticity" flag off
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_H
+#define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "itkMacro.h"
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+ template<class ArgsInfoType>
+ class ITK_EXPORT ConnectedComponentLabelingGenericFilter:
+ public ImageToImageGenericFilter<ConnectedComponentLabelingGenericFilter<ArgsInfoType> >
+ {
+
+ public:
+ //--------------------------------------------------------------------
+ ConnectedComponentLabelingGenericFilter();
+
+ //--------------------------------------------------------------------
+ typedef ConnectedComponentLabelingGenericFilter Self;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ //--------------------------------------------------------------------
+ itkNewMacro(Self);
+ itkTypeMacro(ConnectedComponentLabelingGenericFilter, LightObject);
+
+ //--------------------------------------------------------------------
+ void SetArgsInfo(const ArgsInfoType & a);
+ std::vector<float> GetSizeOfObjectsInPixels() const { return m_SizeOfObjectsInPixels; }
+ std::vector<float> GetSizeOfObjectsInPhysicalUnits() const { return m_SizeOfObjectsInPhysicalUnits; }
+ itkGetConstMacro(OriginalNumberOfObjects, unsigned long int);
+
+ //--------------------------------------------------------------------
+ // Main function called each time the filter is updated
+ template<class ImageType>
+ void UpdateWithInputImageType();
+
+ protected:
+ void Modified() {} // Need for using itkMacros
+ template<unsigned int Dim> void InitializeImageType();
+ ArgsInfoType mArgsInfo;
+ std::vector<float> m_SizeOfObjectsInPixels;
+ std::vector<float> m_SizeOfObjectsInPhysicalUnits;
+ unsigned long int m_OriginalNumberOfObjects;
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkConnectedComponentLabelingGenericFilter.txx"
+#endif
+
+#endif // #define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_H
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_TXX
+#define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+
+// itk
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::ConnectedComponentLabelingGenericFilter():
+ ImageToImageGenericFilter<Self>("ConnectedComponentLabeling")
+{
+ // InitializeImageType<2>();
+ InitializeImageType<3>();
+ //InitializeImageType<4>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::InitializeImageType()
+{
+ ADD_IMAGE_TYPE(Dim, uchar);
+ ADD_IMAGE_TYPE(Dim, short);
+ // ADD_IMAGE_TYPE(Dim, int);
+ // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ConnectedComponentLabelingGenericFilter<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.output_given) SetOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
+{
+ DD("UpdateWithInputImageType");
+
+ // Reading input
+ typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+ // Output image type
+ typedef itk::Image<int, ImageType::ImageDimension> OutputImageType;
+
+ // Create CCL filter
+ DD("CCL");
+ typedef itk::ConnectedComponentImageFilter<ImageType, OutputImageType> ConnectFilterType;
+ typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
+ connectFilter->SetInput(input);
+ connectFilter->SetBackgroundValue(mArgsInfo.inputBG_arg);
+ connectFilter->SetFullyConnected(mArgsInfo.full_flag);
+
+ // TODO SetBackgroud to zero forr relabel ?
+
+
+ // Sort by size and remove too small area.
+ typedef itk::RelabelComponentImageFilter<OutputImageType, OutputImageType> RelabelFilterType;
+ typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
+ // relabelFilter->InPlaceOn();
+ relabelFilter->SetInput(connectFilter->GetOutput());
+ relabelFilter->SetMinimumObjectSize(mArgsInfo.minSize_arg);
+ relabelFilter->Update();
+
+ DD(mArgsInfo.inputBG_arg);
+ DD(mArgsInfo.full_flag);
+ DD(mArgsInfo.minSize_arg);
+
+ // Set information
+ const std::vector<typename RelabelFilterType::ObjectSizeType> & a = relabelFilter->GetSizeOfObjectsInPixels();
+ m_SizeOfObjectsInPixels.resize(a.size());
+ for(unsigned int i=0; i<a.size(); i++) m_SizeOfObjectsInPixels[i] = a[i];
+ m_SizeOfObjectsInPhysicalUnits = relabelFilter->GetSizeOfObjectsInPhysicalUnits();
+ m_OriginalNumberOfObjects = relabelFilter->GetOriginalNumberOfObjects();
+ DD(m_OriginalNumberOfObjects);
+ DD(m_SizeOfObjectsInPhysicalUnits.size());
+
+ // Write/Save results
+ typename OutputImageType::Pointer output = relabelFilter->GetOutput();
+ this->template SetNextOutput<OutputImageType>(output);
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKCONNECTEDCOMPONENTLABELINGSGENERICFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractBones_ggo.h"
+#include "clitkExtractBonesGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+ // Init command line
+ GGO(clitkExtractBones, args_info);
+ CLITK_INIT;
+
+ // Filter
+ typedef clitk::ExtractBonesGenericFilter<args_info_clitkExtractBones> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+
+ filter->SetArgsInfo(args_info);
+ filter->Update();
+
+ return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkExtractBones.ggo
+package "clitkExtractBones"
+version "1.0"
+purpose "Extract bony anatomy through thresholding and connected component labelling. Resample mask afterwards (interp= NN) to match another one (like)"
+
+option "config" - "Config file" string no
+option "imagetypes" - "Display allowed image types" flag off
+option "verbose" v "Verbose" flag off
+option "verboseStep" - "Verbose each step" flag off
+option "writeStep" w "Write image at each step" flag off
+option "verboseOption" - "Display options values" flag off
+option "verboseWarningOff" - "Do not display warning" flag off
+
+section "I/O"
+
+option "input" i "Input image filename" string yes
+option "output" o "Output image filename" string yes
+option "like" l "Resample like this image" string no
+
+section "Initial connected component labelling (CCL)"
+
+option "lower1" - "Lower threshold for CCL" double no default="100"
+option "upper1" - "Upper threshold for CCL" double no default="1500"
+option "minSize" - "Minimal Component Size for CCL" int no default="100"
+option "full" - "Use full connectivity (one side is enough)" flag off
+
+section "Neighborhood Connected Region Growing (RG)"
+
+option "lower2" - "Lower threshold for RG" double no default="10"
+option "upper2" - "Upper threshold for RG" double no default="1500"
+option "radius2" - "Neighborhood radius" int no multiple default="1"
+option "sampleRate2" - "Sample rate of label image for RG: number of voxels to skip between seeds" int no default="0"
+
+option "autoCrop" - "Crop final mask to BoundingBox" flag off
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSFILTER_H
+#define CLITKEXTRACTBONESSFILTER_H
+
+// clitk
+#include "clitkFilterBase.h"
+#include "clitkDecomposeAndReconstructImageFilter.h"
+#include "clitkExplosionControlledThresholdConnectedImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include "itkStatisticsImageFilter.h"
+
+namespace clitk {
+
+ //--------------------------------------------------------------------
+ /*
+ Extract bony anatomy through thresholding and connected component labelling.
+ */
+ //--------------------------------------------------------------------
+
+ template <class TInputImageType, class TOutputImageType>
+ class ITK_EXPORT ExtractBonesFilter:
+ public clitk::FilterBase,
+ public itk::ImageToImageFilter<TInputImageType, TOutputImageType>
+ {
+
+ public:
+ /** Standard class typedefs. */
+ typedef ExtractBonesFilter Self;
+ typedef itk::ImageToImageFilter<TInputImageType, TOutputImageType> Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(ExtractBonesFilter, ImageToImageFilter);
+ FILTERBASE_INIT;
+
+ /** Some convenient typedefs */
+ typedef TInputImageType InputImageType;
+ typedef typename InputImageType::ConstPointer InputImageConstPointer;
+ typedef typename InputImageType::Pointer InputImagePointer;
+ typedef typename InputImageType::RegionType InputImageRegionType;
+ typedef typename InputImageType::PixelType InputImagePixelType;
+ typedef typename InputImageType::SizeType InputImageSizeType;
+ typedef typename InputImageType::IndexType InputImageIndexType;
+
+ typedef TOutputImageType OutputImageType;
+ typedef typename OutputImageType::ConstPointer OutputImageConstPointer;
+ typedef typename OutputImageType::Pointer OutputImagePointer;
+ typedef typename OutputImageType::RegionType OutputImageRegionType;
+ typedef typename OutputImageType::PixelType OutputImagePixelType;
+ typedef typename OutputImageType::SizeType OutputImageSizeType;
+ typedef typename OutputImageType::IndexType OutputImageIndexType;
+
+ itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
+ typedef int InternalPixelType;
+ typedef itk::Image<InternalPixelType, InputImageType::ImageDimension> InternalImageType;
+ typedef typename InternalImageType::Pointer InternalImagePointer;
+ typedef typename InternalImageType::IndexType InternalIndexType;
+ typedef LabelizeParameters<InternalPixelType> LabelParamType;
+
+ /** Connect inputs */
+ void SetInput(const InputImageType * image);
+
+ // Set all options at a time
+ template<class ArgsInfoType>
+ void SetArgsInfo(ArgsInfoType arg);
+
+ // Background / Foreground
+ itkGetConstMacro(BackgroundValue, OutputImagePixelType);
+ itkGetConstMacro(ForegroundValue, OutputImagePixelType);
+
+ itkSetMacro(MinimalComponentSize, int);
+ itkGetConstMacro(MinimalComponentSize, int);
+ GGO_DefineOption(minSize, SetMinimalComponentSize, int);
+
+ // 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);
+
+ // Final Step
+ itkSetMacro(AutoCrop, bool);
+ itkGetConstMacro(AutoCrop, bool);
+ itkBooleanMacro(AutoCrop);
+ GGO_DefineOption_Flag(autoCrop, SetAutoCrop);
+
+ protected:
+ ExtractBonesFilter();
+ virtual ~ExtractBonesFilter() {}
+
+ // Global options
+ itkSetMacro(BackgroundValue, OutputImagePixelType);
+ itkSetMacro(ForegroundValue, OutputImagePixelType);
+ OutputImagePixelType m_BackgroundValue;
+ OutputImagePixelType m_ForegroundValue;
+
+ // Step 1
+ InputImagePixelType m_UpperThreshold1;
+ InputImagePixelType m_LowerThreshold1;
+ int m_MinimalComponentSize;
+ bool m_FullConnectivity;
+
+ // Step 2
+ InputImagePixelType m_UpperThreshold2;
+ InputImagePixelType m_LowerThreshold2;
+ InputImageSizeType m_Radius2;
+ int m_SampleRate2;
+
+ bool m_AutoCrop;
+
+ virtual void GenerateOutputInformation();
+ virtual void GenerateData();
+
+ // Steps
+ void RemoveAir();
+ void FindTrachea();
+ void ExtractBones();
+ void RemoveTrachea();
+ void BonesSeparation();
+ InputImageConstPointer input;
+ OutputImageConstPointer patient;
+ InputImagePointer working_input;
+ typename InternalImageType::Pointer working_image;
+ typename InternalImageType::Pointer trachea;
+ typename InternalImageType::Pointer output;
+
+ private:
+ ExtractBonesFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractBonesFilter.txx"
+#endif
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSFILTER_TXX
+#define CLITKEXTRACTBONESSFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+#include "clitkSetBackgroundImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+#include "clitkAutoCropFilter.h"
+
+// itk
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkNeighborhoodConnectedImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+ExtractBonesFilter():
+ clitk::FilterBase(),
+ itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
+{
+ // Default global options
+ this->SetNumberOfRequiredInputs(1);
+ SetBackgroundValue(0); // Must be zero
+ SetForegroundValue(1);
+
+ SetMinimalComponentSize(100);
+ SetUpperThreshold1(1500);
+ SetLowerThreshold1(100);
+ SetFullConnectivity(false);
+
+ SetUpperThreshold2(1500);
+ SetLowerThreshold2(10);
+ InputImageSizeType s;
+ s.Fill(1);
+ SetRadius2(s);
+ SetSampleRate2(0);
+ AutoCropOff();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+SetInput(const TInputImageType * image)
+{
+ this->SetNthInput(0, const_cast<TInputImageType *>(image));
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+template<class ArgsInfoType>
+void
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+ SetVerboseOption_GGO(mArgsInfo);
+ SetVerboseStep_GGO(mArgsInfo);
+ SetWriteStep_GGO(mArgsInfo);
+ SetVerboseWarningOff_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);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+GenerateOutputInformation() {
+ // Get input pointers
+ InputImagePointer input = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
+ // InputImagePointer input = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
+ Superclass::GenerateOutputInformation();
+ OutputImagePointer outputImage = this->GetOutput(0);
+ outputImage->SetRegions(input->GetLargestPossibleRegion());
+
+ // typedefs
+ typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinarizeFilterType;
+ typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> BinarizeFilterType;
+ typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
+ typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
+ typedef clitk::SetBackgroundImageFilter<InternalImageType,InternalImageType, InternalImageType> SetBackgroundFilterType;
+ typedef itk::CastImageFilter<InternalImageType,OutputImageType> CastImageFilterType;
+ typedef itk::ImageFileWriter<OutputImageType> WriterType;
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Initial Labeling");
+
+ typename InternalImageType::Pointer firstLabelImage;
+
+ //---------------------------------
+ // Binarize the image
+ //---------------------------------
+ typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+ binarizeFilter->SetInput(input);
+ binarizeFilter->SetLowerThreshold(GetLowerThreshold1());
+ binarizeFilter->SetUpperThreshold(GetUpperThreshold1());
+ binarizeFilter->SetInsideValue(this->GetForegroundValue());
+ binarizeFilter->SetOutsideValue(this->GetBackgroundValue());
+
+ //---------------------------------
+ // Label the connected components
+ //---------------------------------
+ typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
+ connectFilter->SetInput(binarizeFilter->GetOutput());
+ connectFilter->SetBackgroundValue(this->GetBackgroundValue());
+ connectFilter->SetFullyConnected(GetFullConnectivity());
+
+ //---------------------------------
+ // Sort the labels according to size
+ //---------------------------------
+ typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
+ relabelFilter->SetInput(connectFilter->GetOutput());
+ relabelFilter->SetMinimumObjectSize(GetMinimalComponentSize());
+
+ //---------------------------------
+ // Keep the label
+ //---------------------------------
+ typename BinarizeFilterType::Pointer binarizeFilter2=BinarizeFilterType::New();
+ binarizeFilter2->SetInput(relabelFilter->GetOutput());
+ binarizeFilter2->SetLowerThreshold(1);
+ binarizeFilter2->SetUpperThreshold(1);
+ binarizeFilter2->SetInsideValue(this->GetForegroundValue());
+ binarizeFilter2->SetOutsideValue(this->GetBackgroundValue());
+ binarizeFilter2->Update();
+
+ firstLabelImage = binarizeFilter2->GetOutput();
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Neighborhood connected filter");
+ typename InternalImageType::Pointer secondLabelImage;
+
+ //---------------------------------
+ //Neighborhood connected RG
+ //---------------------------------
+ typedef itk::NeighborhoodConnectedImageFilter<InputImageType, InternalImageType>
+ NeighborhoodConnectedImageFilterType;
+ typename NeighborhoodConnectedImageFilterType::Pointer neighborhoodConnectedImageFilter=
+ NeighborhoodConnectedImageFilterType::New();
+
+ // thresholds
+ neighborhoodConnectedImageFilter->SetLower(GetLowerThreshold2());
+ neighborhoodConnectedImageFilter->SetUpper(GetUpperThreshold2());
+ neighborhoodConnectedImageFilter->SetReplaceValue(this->GetForegroundValue());
+ neighborhoodConnectedImageFilter->SetRadius(GetRadius2());
+ neighborhoodConnectedImageFilter->SetInput(input);
+
+ // Seeds from label image
+ typedef itk::ImageRegionIteratorWithIndex<InternalImageType> IteratorType;
+ IteratorType it(firstLabelImage, firstLabelImage->GetLargestPossibleRegion());
+ typename InputImageType::IndexType index;
+ unsigned int counter=0;
+ while (!it.IsAtEnd())
+ {
+ if (it.Get()==this->GetForegroundValue())
+ {
+ counter++;
+ index=it.GetIndex();
+ neighborhoodConnectedImageFilter->AddSeed(index);
+ ++it;
+ unsigned int i=0;
+ while (!it.IsAtEnd() && i< (unsigned int) GetSampleRate2())
+ {
+ ++it;
+ i++;
+ }
+ }
+ else ++it;
+ }
+
+ neighborhoodConnectedImageFilter->Update();
+ secondLabelImage = neighborhoodConnectedImageFilter->GetOutput();
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Combine de images");
+ typedef clitk::SetBackgroundImageFilter<InternalImageType, InternalImageType, InternalImageType>
+ SetBackgroundImageFilterType;
+ typename SetBackgroundImageFilterType::Pointer setBackgroundFilter=SetBackgroundImageFilterType::New();
+ setBackgroundFilter->SetInput(firstLabelImage);
+ setBackgroundFilter->SetInput2(secondLabelImage);
+ setBackgroundFilter->SetMaskValue(this->GetForegroundValue());
+ setBackgroundFilter->SetOutsideValue(this->GetForegroundValue());
+ setBackgroundFilter->Update();
+
+ output = setBackgroundFilter->GetOutput();
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // [Optional]
+ if (GetAutoCrop()) {
+ StartNewStep("AutoCrop");
+ typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
+ typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+ cropFilter->SetInput(output);
+ cropFilter->SetBackgroundValue(GetBackgroundValue());
+ cropFilter->Update();
+ output = cropFilter->GetOutput();
+ StopCurrentStep<InternalImageType>(output);
+ outputImage->SetRegions(output->GetLargestPossibleRegion());
+ }
+
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void
+clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
+GenerateData() {
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // Final Cast
+ typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
+ typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+ caster->SetInput(output);
+ caster->Update();
+ //this->SetNthOutput(0, caster->GetOutput());
+ this->GraftOutput(caster->GetOutput());
+ return;
+}
+//--------------------------------------------------------------------
+
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSGENERICFILTER_H
+#define CLITKEXTRACTBONESSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractBonesFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+ template<class ArgsInfoType>
+ class ITK_EXPORT ExtractBonesGenericFilter:
+ public ImageToImageGenericFilter<ExtractBonesGenericFilter<ArgsInfoType> >
+ {
+
+ public:
+ //--------------------------------------------------------------------
+ ExtractBonesGenericFilter();
+
+ //--------------------------------------------------------------------
+ typedef ExtractBonesGenericFilter Self;
+ typedef ImageToImageGenericFilter<ExtractBonesGenericFilter<ArgsInfoType> > Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ //--------------------------------------------------------------------
+ itkNewMacro(Self);
+ itkTypeMacro(ExtractBonesGenericFilter, LightObject);
+
+ //--------------------------------------------------------------------
+ void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Main function called each time the filter is updated
+ template<class ImageType>
+ void UpdateWithInputImageType();
+
+ protected:
+ template<unsigned int Dim> void InitializeImageType();
+ ArgsInfoType mArgsInfo;
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractBonesGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTBONESSGENERICFILTER_H
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTBONESSGENERICFILTER_TXX
+#define CLITKEXTRACTBONESSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractBonesGenericFilter<ArgsInfoType>::ExtractBonesGenericFilter():
+ ImageToImageGenericFilter<Self>("ExtractBones")
+{
+ // Default values
+ cmdline_parser_clitkExtractBones_init(&mArgsInfo);
+ InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractBonesGenericFilter<ArgsInfoType>::InitializeImageType()
+{
+ ADD_IMAGE_TYPE(Dim, short);
+ // ADD_IMAGE_TYPE(Dim, int);
+ // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractBonesGenericFilter<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.output_given) AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractBonesGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
+{
+ // Mask & output image type
+ typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
+
+ // Reading input
+ typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+ // Create filter
+ typedef clitk::ExtractBonesFilter<ImageType, OutputImageType> FilterType;
+ typename FilterType::Pointer filter = FilterType::New();
+
+ // Set global Options
+ filter->SetArgsInfo(mArgsInfo);
+ filter->SetInput(input);
+
+ // Go !
+ filter->Update();
+
+ // Check if error
+ if (filter->HasError()) {
+ SetLastError(filter->GetLastError());
+ // No output
+ return;
+ }
+
+ // Write/Save results
+ typename OutputImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<OutputImageType>(output);
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTBONESSGENERICFILTER_TXX
--- /dev/null
+
+#ifndef __clitkExtractImageFilter_h
+#define __clitkExtractImageFilter_h
+
+#include "itkImageToImageFilter.h"
+#include "itkSmartPointer.h"
+#include "itkExtractImageFilterRegionCopier.h"
+
+namespace clitk
+{
+
+template <class TInputImage, class TOutputImage>
+class ITK_EXPORT ExtractImageFilter:
+ public itk::ImageToImageFilter<TInputImage,TOutputImage>
+{
+public:
+ /** Standard class typedefs. */
+ typedef ExtractImageFilter Self;
+ typedef itk::ImageToImageFilter<TInputImage,TOutputImage> Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(ExtractImageFilter, ImageToImageFilter);
+
+ /** Image type information. */
+ typedef TInputImage InputImageType;
+ typedef TOutputImage OutputImageType;
+
+ /** Typedef to describe the output and input image region types. */
+ typedef typename TOutputImage::RegionType OutputImageRegionType;
+ typedef typename TInputImage::RegionType InputImageRegionType;
+
+ /** Typedef to describe the type of pixel. */
+ typedef typename TOutputImage::PixelType OutputImagePixelType;
+ typedef typename TInputImage::PixelType InputImagePixelType;
+
+ /** Typedef to describe the output and input image index and size types. */
+ typedef typename TOutputImage::IndexType OutputImageIndexType;
+ typedef typename TInputImage::IndexType InputImageIndexType;
+ typedef typename TOutputImage::SizeType OutputImageSizeType;
+ typedef typename TInputImage::SizeType InputImageSizeType;
+
+ /** ImageDimension enumeration */
+ itkStaticConstMacro(InputImageDimension, unsigned int,
+ TInputImage::ImageDimension);
+ itkStaticConstMacro(OutputImageDimension, unsigned int,
+ TOutputImage::ImageDimension);
+
+ typedef itk::ImageToImageFilterDetail::ExtractImageFilterRegionCopier<
+ itkGetStaticConstMacro(InputImageDimension),
+ itkGetStaticConstMacro(OutputImageDimension)> ExtractImageFilterRegionCopierType;
+
+ void SetExtractionRegion(InputImageRegionType extractRegion);
+ itkGetMacro(ExtractionRegion, InputImageRegionType);
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+ /** Begin concept checking */
+ itkConceptMacro(InputCovertibleToOutputCheck,
+ (itk::Concept::Convertible<InputImagePixelType, OutputImagePixelType>));
+ /** End concept checking */
+#endif
+
+protected:
+ ExtractImageFilter();
+ ~ExtractImageFilter() {};
+ void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+
+ virtual void GenerateOutputInformation();
+
+
+ virtual void CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
+ const OutputImageRegionType &srcRegion);
+
+
+ void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+ int threadId );
+ InputImageRegionType m_ExtractionRegion;
+ OutputImageRegionType m_OutputImageRegion;
+
+private:
+ ExtractImageFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractImageFilter.txx"
+#endif
+
+#endif
--- /dev/null
+
+#ifndef _clitkExtractImageFilter_txx
+#define _clitkExtractImageFilter_txx
+
+#include "clitkExtractImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkObjectFactory.h"
+#include "itkExtractImageFilterRegionCopier.h"
+#include "itkProgressReporter.h"
+
+
+namespace clitk
+{
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage>
+ExtractImageFilter<TInputImage,TOutputImage>
+::ExtractImageFilter()
+{
+}
+
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage>
+void
+ExtractImageFilter<TInputImage,TOutputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+ Superclass::PrintSelf(os,indent);
+
+ os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
+ os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
+}
+
+
+template<class TInputImage, class TOutputImage>
+void
+ExtractImageFilter<TInputImage,TOutputImage>
+::CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
+ const OutputImageRegionType &srcRegion)
+{
+ ExtractImageFilterRegionCopierType extractImageRegionCopier;
+ extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
+}
+
+
+template <class TInputImage, class TOutputImage>
+void
+ExtractImageFilter<TInputImage,TOutputImage>
+::SetExtractionRegion(InputImageRegionType extractRegion)
+{
+ m_ExtractionRegion = extractRegion;
+
+ unsigned int nonzeroSizeCount = 0;
+ InputImageSizeType inputSize = extractRegion.GetSize();
+ OutputImageSizeType outputSize;
+ OutputImageIndexType outputIndex;
+
+ /**
+ * check to see if the number of non-zero entries in the extraction region
+ * matches the number of dimensions in the output image.
+ **/
+ for (unsigned int i = 0; i < InputImageDimension; ++i)
+ {
+ if (inputSize[i])
+ {
+ outputSize[nonzeroSizeCount] = inputSize[i];
+ outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
+ nonzeroSizeCount++;
+ }
+ }
+
+ if (nonzeroSizeCount != OutputImageDimension)
+ {
+ itkExceptionMacro("Extraction Region not consistent with output image");
+ }
+
+ m_OutputImageRegion.SetSize(outputSize);
+ m_OutputImageRegion.SetIndex(outputIndex);
+ this->Modified();
+}
+
+
+
+/**
+ * ExtractImageFilter can produce an image which is a different resolution
+ * than its input image. As such, ExtractImageFilter needs to provide an
+ * implementation for GenerateOutputInformation() in order to inform
+ * the pipeline execution model. The original documentation of this
+ * method is below.
+ *
+ * \sa ProcessObject::GenerateOutputInformaton()
+ */
+template <class TInputImage, class TOutputImage>
+void
+ExtractImageFilter<TInputImage,TOutputImage>
+::GenerateOutputInformation()
+{
+ // do not call the superclass' implementation of this method since
+ // this filter allows the input and the output to be of different dimensions
+
+ // get pointers to the input and output
+ typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
+ typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
+
+ if ( !outputPtr || !inputPtr)
+ {
+ return;
+ }
+
+ // Set the output image size to the same value as the extraction region.
+ outputPtr->SetLargestPossibleRegion( m_OutputImageRegion );
+
+ // Set the output spacing and origin
+ const itk::ImageBase<InputImageDimension> *phyData;
+
+ phyData
+ = dynamic_cast<const itk::ImageBase<InputImageDimension>*>(this->GetInput());
+
+ if (phyData)
+ {
+ // Copy what we can from the image from spacing and origin of the input
+ // This logic needs to be augmented with logic that select which
+ // dimensions to copy
+
+ unsigned int i;
+ const typename InputImageType::SpacingType&
+ inputSpacing = inputPtr->GetSpacing();
+ const typename InputImageType::DirectionType&
+ inputDirection = inputPtr->GetDirection();
+ const typename InputImageType::PointType&
+ inputOrigin = inputPtr->GetOrigin();
+
+ typename OutputImageType::SpacingType outputSpacing;
+ typename OutputImageType::DirectionType outputDirection;
+ typename OutputImageType::PointType outputOrigin;
+
+ if ( static_cast<unsigned int>(OutputImageDimension) >
+ static_cast<unsigned int>(InputImageDimension ) )
+ {
+ // copy the input to the output and fill the rest of the
+ // output with zeros.
+ for (i=0; i < InputImageDimension; ++i)
+ {
+ outputSpacing[i] = inputSpacing[i];
+ outputOrigin[i] = inputOrigin[i];
+ for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+ {
+ outputDirection[i][dim] = inputDirection[i][dim];
+ }
+ }
+ for (; i < OutputImageDimension; ++i)
+ {
+ outputSpacing[i] = 1.0;
+ outputOrigin[i] = 0.0;
+ for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+ {
+ outputDirection[i][dim] = 0.0;
+ }
+ outputDirection[i][i] = 1.0;
+ }
+ }
+ else
+ {
+ // copy the non-collapsed part of the input spacing and origing to the output
+ int nonZeroCount = 0;
+ for (i=0; i < InputImageDimension; ++i)
+ {
+ if (m_ExtractionRegion.GetSize()[i])
+ {
+ outputSpacing[nonZeroCount] = inputSpacing[i];
+ outputOrigin[nonZeroCount] = inputOrigin[i];
+ int nonZeroCount2 = 0;
+ for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+ {
+ if (m_ExtractionRegion.GetSize()[dim])
+ {
+ outputDirection[nonZeroCount][nonZeroCount2] =
+ inputDirection[i][dim];
+ ++nonZeroCount2;
+ }
+ }
+ nonZeroCount++;
+ }
+ }
+ }
+
+ // set the spacing and origin
+ outputPtr->SetSpacing( outputSpacing );
+ outputPtr->SetDirection( outputDirection );
+ outputPtr->SetOrigin( outputOrigin );
+ outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel() );
+ }
+ else
+ {
+ // pointer could not be cast back down
+ itkExceptionMacro(<< "itk::ExtractImageFilter::GenerateOutputInformation "
+ << "cannot cast input to "
+ << typeid(itk::ImageBase<InputImageDimension>*).name() );
+ }
+}
+
+/**
+ * ExtractImageFilter can be implemented as a multithreaded filter.
+ * Therefore, this implementation provides a ThreadedGenerateData()
+ * routine which is called for each processing thread. The output
+ * image data is allocated automatically by the superclass prior to
+ * calling ThreadedGenerateData(). ThreadedGenerateData can only
+ * write to the portion of the output image specified by the
+ * parameter "outputRegionForThread"
+ *
+ * \sa ImageToImageFilter::ThreadedGenerateData(),
+ * ImageToImageFilter::GenerateData()
+ */
+template <class TInputImage, class TOutputImage>
+void
+ExtractImageFilter<TInputImage,TOutputImage>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+ int threadId)
+{
+ itkDebugMacro(<<"Actually executing");
+
+ // Get the input and output pointers
+ typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
+ typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
+
+ // support progress methods/callbacks
+ itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+
+ // Define the portion of the input to walk for this thread
+ InputImageRegionType inputRegionForThread;
+ this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
+
+ // Define the iterators.
+ typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
+ typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
+
+ OutputIterator outIt(outputPtr, outputRegionForThread);
+ InputIterator inIt(inputPtr, inputRegionForThread);
+
+ // walk the output region, and sample the input image
+ while( !outIt.IsAtEnd() )
+ {
+ // copy the input pixel to the output
+ outIt.Set( static_cast<OutputImagePixelType>(inIt.Get()));
+ ++outIt;
+ ++inIt;
+ progress.CompletedPixel();
+ }
+}
+
+} // end namespace clitk
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractLung_ggo.h"
+#include "clitkExtractLungGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+ // Init command line
+ GGO(clitkExtractLung, args_info);
+ CLITK_INIT;
+
+ // Filter
+ typedef clitk::ExtractLungGenericFilter<args_info_clitkExtractLung> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+
+ filter->SetArgsInfo(args_info);
+ filter->Update();
+
+ if (filter->HasError()) {
+ std::cout << filter->GetLastError() << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkExtractLungs.ggo
+package "clitkExtractLungs"
+version "1.0"
+purpose "Segment lungs in CT image. Need 'patient' mask."
+
+option "config" - "Config file" string no
+option "imagetypes" - "Display allowed image types" flag off
+option "verbose" v "Verbose" flag off
+option "verboseStep" - "Verbose each step" flag off
+option "writeStep" w "Write image at each step" flag off
+option "verboseOption" - "Display options values" flag off
+option "verboseWarningOff" - "Do not display warning" flag off
+
+section "I/O"
+
+option "input" i "Input CT image filename" string yes
+option "patient" p "Input patient mask filename" string yes
+option "patientBG" - "Patient Background" int default="0" no
+option "output" o "Output lungs mask filename" string yes
+option "outputTrachea" t "Output trachea mask filename" string no
+
+section "Step 1 : Air remove"
+
+option "lower" - "Initial lower threshold" double no
+option "upper" - "Initial upper threshold" double no default="-300"
+option "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
+
+section "Step 2 : find trachea"
+
+option "upperThresholdForTrachea" - "Initial upper threshold for trachea" double no default="-900"
+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
+
+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
+
+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"
+
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSFILTER_H
+#define CLITKEXTRACTLUNGSFILTER_H
+
+// clitk
+#include "clitkFilterBase.h"
+#include "clitkDecomposeAndReconstructImageFilter.h"
+#include "clitkExplosionControlledThresholdConnectedImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include "itkStatisticsImageFilter.h"
+
+namespace clitk {
+
+ //--------------------------------------------------------------------
+ /*
+ Try to extract the Lung part of a thorax CT. Inspired by
+ Rikxoort2009, Section IIA, MedPhys.
+
+ - First, all air besides lungs and thrachea is removed, by
+ removing the second largest label of the firstLabelImage and
+ setting the remainder to 0HU . This modified input is optimally
+ thresholded (Otsu1979).
+
+ - Trachea and bronchi are grown from seeds in the top of the image
+ by explosion controlled region growing, slightly dilated and
+ removed from the second label image.
+
+ - Left and right lung are separated (if necessary) by erosion and
+ reconstructed by conditional dilation.
+
+ - TRACHEA is available at the end
+
+ TODO ********** Remaining holes can be filled afterwards (clitkFillMask).
+
+ */
+ //--------------------------------------------------------------------
+
+ template <class TInputImageType, class TMaskImageType>
+ class ITK_EXPORT ExtractLungFilter:
+ public clitk::FilterBase,
+ public itk::ImageToImageFilter<TInputImageType, TMaskImageType>
+ {
+
+ public:
+ /** Standard class typedefs. */
+ typedef itk::ImageToImageFilter<TInputImageType, TMaskImageType> Superclass;
+ typedef ExtractLungFilter Self;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
+ FILTERBASE_INIT;
+
+ /** Some convenient typedefs */
+ typedef TInputImageType InputImageType;
+ typedef typename InputImageType::ConstPointer InputImageConstPointer;
+ typedef typename InputImageType::Pointer InputImagePointer;
+ typedef typename InputImageType::RegionType InputImageRegionType;
+ typedef typename InputImageType::PixelType InputImagePixelType;
+ typedef typename InputImageType::SizeType InputImageSizeType;
+ typedef typename InputImageType::IndexType InputImageIndexType;
+
+ typedef TMaskImageType MaskImageType;
+ typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
+ typedef typename MaskImageType::Pointer MaskImagePointer;
+ typedef typename MaskImageType::RegionType MaskImageRegionType;
+ typedef typename MaskImageType::PixelType MaskImagePixelType;
+ typedef typename MaskImageType::SizeType MaskImageSizeType;
+ typedef typename MaskImageType::IndexType MaskImageIndexType;
+
+ itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
+ typedef int InternalPixelType;
+ typedef itk::Image<InternalPixelType, InputImageType::ImageDimension> InternalImageType;
+ typedef typename InternalImageType::Pointer InternalImagePointer;
+ typedef typename InternalImageType::IndexType InternalIndexType;
+ typedef LabelizeParameters<InternalPixelType> LabelParamType;
+
+ /** Connect inputs */
+ void SetInput(const InputImageType * image);
+ void SetInputPatientMask(MaskImageType * mask, MaskImagePixelType BG);
+ itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
+ itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
+ GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType);
+
+ // 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; }
+
+ // Background / Foreground
+ itkGetConstMacro(BackgroundValue, MaskImagePixelType);
+ itkGetConstMacro(ForegroundValue, MaskImagePixelType);
+
+ // 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(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, InputImageType::ImageDimension, true);
+
+ // 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 options LungSeparation
+ // itkSetMacro(FinalOpenClose, bool);
+ // itkGetConstMacro(FinalOpenClose, bool);
+ // itkBooleanMacro(FinalOpenClose);
+
+ // virtual void Update();
+
+ protected:
+ ExtractLungFilter();
+ virtual ~ExtractLungFilter() {}
+
+ // Global options
+ itkSetMacro(BackgroundValue, MaskImagePixelType);
+ itkSetMacro(ForegroundValue, MaskImagePixelType);
+ MaskImagePixelType m_PatientMaskBackgroundValue;
+ MaskImagePixelType m_BackgroundValue;
+ MaskImagePixelType m_ForegroundValue;
+ int m_MinimalComponentSize;
+
+ // Step 1
+ InputImagePixelType m_UpperThreshold;
+ InputImagePixelType m_LowerThreshold;
+ bool m_UseLowerThreshold;
+ LabelParamType* m_LabelizeParameters1;
+
+ // Step 2
+ InputImagePixelType m_UpperThresholdForTrachea;
+ InputImagePixelType m_ThresholdStepSizeForTrachea;
+ double m_MultiplierForTrachea;
+ std::vector<InternalIndexType> m_Seeds;
+
+ // Step 3
+ int m_NumberOfHistogramBins;
+ LabelParamType* m_LabelizeParameters2;
+
+ // Step 4
+ int m_RadiusForTrachea;
+ LabelParamType* m_LabelizeParameters3;
+
+ // Step 5
+ // bool m_FinalOpenClose;
+
+ virtual void GenerateOutputInformation();
+ virtual void GenerateData();
+
+ // Steps
+ void RemoveAir();
+ void FindTrachea();
+ void ExtractLung();
+ void RemoveTrachea();
+ void LungSeparation();
+ InputImageConstPointer input;
+ MaskImageConstPointer patient;
+ InputImagePointer working_input;
+ typename InternalImageType::Pointer working_image;
+ typename InternalImageType::Pointer trachea_tmp;
+ MaskImagePointer trachea;
+
+ private:
+ ExtractLungFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLungFilter.txx"
+#endif
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSFILTER_TXX
+#define CLITKEXTRACTLUNGSFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+#include "clitkSetBackgroundImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+#include "clitkAutoCropFilter.h"
+
+// itk
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkOtsuThresholdImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+ExtractLungFilter():
+ clitk::FilterBase(),
+ itk::ImageToImageFilter<TInputImageType, TMaskImageType>()
+{
+ // Default global options
+ this->SetNumberOfRequiredInputs(2);
+ SetPatientMaskBackgroundValue(0);
+ SetBackgroundValue(0); // Must be zero
+ SetForegroundValue(1);
+
+ // Step 1 default values
+ SetUpperThreshold(-300);
+ SetLowerThreshold(-1000);
+ UseLowerThresholdOff();
+ LabelParamType * p1 = new LabelParamType;
+ p1->SetFirstKeep(1);
+ p1->UseLastKeepOff();
+ p1->AddLabelToRemove(2);
+ SetLabelizeParameters1(p1);
+
+ // Step 2 default values
+ SetUpperThresholdForTrachea(-900);
+ SetMultiplierForTrachea(5);
+ SetThresholdStepSizeForTrachea(64);
+
+ // Step 3 default values
+ SetNumberOfHistogramBins(500);
+ LabelParamType * p2 = new LabelParamType;
+ p2->SetFirstKeep(1);
+ p2->UseLastKeepOff();
+ // p->AddLabelToRemove(2); // No label to remove by default
+ SetLabelizeParameters2(p2);
+
+ // Step 4 default values
+ SetRadiusForTrachea(1);
+ LabelParamType * p3 = new LabelParamType;
+ p3->SetFirstKeep(1);
+ p3->SetLastKeep(2);
+ p3->UseLastKeepOff();
+ SetLabelizeParameters3(p3);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+SetInput(const TInputImageType * image)
+{
+ this->SetNthInput(0, const_cast<TInputImageType *>(image));
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+SetInputPatientMask(TMaskImageType * image, MaskImagePixelType bg )
+{
+ this->SetNthInput(1, const_cast<TMaskImageType *>(image));
+ SetPatientMaskBackgroundValue(bg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+AddSeed(InternalIndexType s)
+{
+ m_Seeds.push_back(s);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+template<class ArgsInfoType>
+void
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+ SetVerboseOption_GGO(mArgsInfo);
+ SetVerboseStep_GGO(mArgsInfo);
+ SetWriteStep_GGO(mArgsInfo);
+ SetVerboseWarningOff_GGO(mArgsInfo);
+
+ SetUpperThreshold_GGO(mArgsInfo);
+ SetLowerThreshold_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);
+
+ SetNumberOfHistogramBins_GGO(mArgsInfo);
+ SetLabelizeParameters2_GGO(mArgsInfo);
+
+ SetRadiusForTrachea_GGO(mArgsInfo);
+ SetLabelizeParameters3_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+GenerateOutputInformation()
+{
+ input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+ Superclass::GenerateOutputInformation();
+// MaskImagePointer output = this->GetOutput(0);
+
+ // Get input pointers
+ input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+ patient = dynamic_cast<const TMaskImageType*>(itk::ProcessObject::GetInput(1));
+
+ // Check image
+ if (!HasSameSizeAndSpacing<TInputImageType, TMaskImageType>(input, patient)) {
+ this->SetLastError("* ERROR * the images (input and patient mask) must have the same size & spacing");
+ return;
+ }
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Set background to initial image");
+ working_input = SetBackground<TInputImageType, TMaskImageType>
+ (input, patient, GetPatientMaskBackgroundValue(), -1000);
+ StopCurrentStep<InputImageType>(working_input);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Remove Air");
+ // Threshold to get air
+ typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinarizeFilterType;
+ typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+ binarizeFilter->SetInput(working_input);
+ if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(m_LowerThreshold);
+ binarizeFilter->SetUpperThreshold(m_UpperThreshold);
+ 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_image = RemoveLabels<InternalImageType>
+ (working_image, GetBackgroundValue(), GetLabelizeParameters1()->GetLabelsToRemove());
+ typename InternalImageType::Pointer air = KeepLabels<InternalImageType>
+ (working_image,
+ GetBackgroundValue(),
+ GetForegroundValue(),
+ GetLabelizeParameters1()->GetFirstKeep(),
+ GetLabelizeParameters1()->GetLastKeep(),
+ GetLabelizeParameters1()->GetUseLastKeep());
+
+ // Set Air to BG
+ working_input = SetBackground<TInputImageType, InternalImageType>
+ (working_input, air, this->GetForegroundValue(), this->GetBackgroundValue());
+
+ // End
+ StopCurrentStep<InputImageType>(working_input);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Find the trachea");
+ if (m_Seeds.size() == 0) { // try to find seed
+ // Search seed (parameters = UpperThresholdForTrachea)
+ static const unsigned int Dim = InputImageType::ImageDimension;
+ typename InternalImageType::RegionType sliceRegion = working_input->GetLargestPossibleRegion();
+ typename InternalImageType::SizeType sliceRegionSize = sliceRegion.GetSize();
+ typename InternalImageType::IndexType sliceRegionIndex = sliceRegion.GetIndex();
+ sliceRegionIndex[Dim-1]=sliceRegionSize[Dim-1]-5;
+ sliceRegionSize[Dim-1]=5;
+ sliceRegion.SetSize(sliceRegionSize);
+ sliceRegion.SetIndex(sliceRegionIndex);
+
+ typedef itk::ImageRegionConstIterator<InputImageType> IteratorType;
+ IteratorType it(working_input, sliceRegion);
+ it.GoToBegin();
+ while (!it.IsAtEnd()) {
+ if(it.Get() < GetUpperThresholdForTrachea() ) {
+ AddSeed(it.GetIndex());
+ }
+ ++it;
+ }
+ }
+
+ if (m_Seeds.size() != 0) {
+ // Explosion controlled region growing
+ typedef clitk::ExplosionControlledThresholdConnectedImageFilter<InputImageType, InternalImageType> ImageFilterType;
+ typename ImageFilterType::Pointer f= ImageFilterType::New();
+ f->SetInput(working_input);
+ f->SetVerbose(false);
+ f->SetLower(-2000);
+ f->SetUpper(GetUpperThresholdForTrachea());
+ f->SetMinimumLowerThreshold(-2000);
+ f->SetMaximumUpperThreshold(0);
+ f->SetAdaptLowerBorder(false);
+ f->SetAdaptUpperBorder(true);
+ f->SetMinimumSize(5000);
+ f->SetReplaceValue(1);
+ f->SetMultiplier(GetMultiplierForTrachea());
+ f->SetThresholdStepSize(GetThresholdStepSizeForTrachea());
+ f->SetMinimumThresholdStepSize(1);
+ for(unsigned int i=0; i<m_Seeds.size();i++) {
+ // std::cout<<"Adding seed " <<m_Seeds[i]<<"..."<<std::endl;
+ f->AddSeed(m_Seeds[i]);
+ }
+ f->Update();
+ trachea_tmp = f->GetOutput();
+ // Set output
+ StopCurrentStep<InternalImageType>(trachea_tmp);
+
+ }
+ else { // Trachea not found
+ this->SetWarning("* WARNING * No seed found for trachea.");
+ // Set output
+ StopCurrentStep();
+ }
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Extract the lung with Otsu filter");
+ // Automated Otsu thresholding and relabeling
+ typedef itk::OtsuThresholdImageFilter<InputImageType,InternalImageType> 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();
+
+ // Set output
+ StopCurrentStep<InternalImageType>(working_image);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Select labels");
+ // Keep right labels
+ working_image = LabelizeAndSelectLabels<InternalImageType>
+ (working_image,
+ GetBackgroundValue(),
+ GetForegroundValue(),
+ false,
+ GetMinimalComponentSize(),
+ GetLabelizeParameters2());
+
+ // Set output
+ StopCurrentStep<InternalImageType>(working_image);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ 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);
+
+ // Dilate the trachea
+ static const unsigned int Dim = InputImageType::ImageDimension;
+ typedef itk::BinaryBallStructuringElement<InternalPixelType, Dim> KernelType;
+ KernelType structuringElement;
+ structuringElement.SetRadius(GetRadiusForTrachea());
+ structuringElement.CreateStructuringElement();
+ typedef clitk::ConditionalBinaryDilateImageFilter<InternalImageType, InternalImageType, 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->Update();
+ working_image = dilateFilter->GetOutput();
+
+ // Set trachea with dilatation
+ trachea_tmp = SetBackground<InternalImageType, InternalImageType>
+ (trachea_tmp, working_image, -1, this->GetForegroundValue());
+
+ // Remove the trachea
+ working_image = SetBackground<InternalImageType, InternalImageType>
+ (working_image, working_image, -1, this->GetBackgroundValue());
+
+ // Label
+ working_image = LabelizeAndSelectLabels<InternalImageType>
+ (working_image,
+ GetBackgroundValue(),
+ GetForegroundValue(),
+ false,
+ GetMinimalComponentSize(),
+ GetLabelizeParameters3());
+
+ // Set output
+ StopCurrentStep<InternalImageType>(working_image);
+ }
+
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
+ typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+ if (m_Seeds.size() != 0) { // if ==0 ->no trachea found
+ StartNewStep("Croping trachea");
+ cropFilter->SetInput(trachea_tmp);
+ cropFilter->Update(); // Needed
+ typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
+ typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+ caster->SetInput(cropFilter->GetOutput());
+ caster->Update();
+ trachea = caster->GetOutput();
+ StopCurrentStep<MaskImageType>(trachea);
+ }
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Croping lung");
+ cropFilter = CropFilterType::New(); // Needed to reset pipeline
+ cropFilter->SetInput(working_image);
+ cropFilter->Update();
+ working_image = cropFilter->GetOutput();
+ StopCurrentStep<InternalImageType>(working_image);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Separate Left/Right lungs");
+ // Initial label
+ working_image = Labelize<InternalImageType>(working_image,
+ GetBackgroundValue(),
+ false,
+ GetMinimalComponentSize());
+
+ // Count the labels
+ typedef itk::StatisticsImageFilter<InternalImageType> StatisticsImageFilterType;
+ typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
+ statisticsImageFilter->SetInput(working_image);
+ statisticsImageFilter->Update();
+ unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
+ working_image = statisticsImageFilter->GetOutput();
+
+ // Decompose the first label
+ static const unsigned int Dim = InputImageType::ImageDimension;
+ if (initialNumberOfLabels<2) {
+ // Structuring element radius
+ typename InputImageType::SizeType radius;
+ for (unsigned int i=0;i<Dim;i++) radius[i]=1;
+ typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> DecomposeAndReconstructFilterType;
+ typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
+ decomposeAndReconstructFilter->SetInput(working_image);
+ decomposeAndReconstructFilter->SetVerbose(false);
+ decomposeAndReconstructFilter->SetRadius(radius);
+ decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
+ decomposeAndReconstructFilter->SetMinimumObjectSize(this->GetMinimalComponentSize());
+ decomposeAndReconstructFilter->SetMinimumNumberOfIterations(1);
+ decomposeAndReconstructFilter->SetBackgroundValue(this->GetBackgroundValue());
+ decomposeAndReconstructFilter->SetForegroundValue(this->GetForegroundValue());
+ decomposeAndReconstructFilter->SetFullyConnected(true);
+ decomposeAndReconstructFilter->SetNumberOfNewLabels(1);
+ decomposeAndReconstructFilter->Update();
+ working_image = decomposeAndReconstructFilter->GetOutput();
+ }
+
+ // Retain labels (lungs)
+ typedef itk::ThresholdImageFilter<InternalImageType> ThresholdImageFilterType;
+ typename ThresholdImageFilterType::Pointer thresholdFilter = ThresholdImageFilterType::New();
+ thresholdFilter->SetInput(working_image);
+ thresholdFilter->ThresholdAbove(2);
+ thresholdFilter->SetOutsideValue(this->GetBackgroundValue());
+ thresholdFilter->Update();
+ working_image = thresholdFilter->GetOutput();
+ StopCurrentStep<InternalImageType> (working_image);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TMaskImageType>
+void
+clitk::ExtractLungFilter<TInputImageType, TMaskImageType>::
+GenerateData() {
+ // Final Cast
+ typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
+ typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+ caster->SetInput(working_image);
+ caster->Update();
+ // Set output
+ //this->SetNthOutput(0, caster->GetOutput()); // -> no because redo filter otherwise
+ this->GraftOutput(caster->GetOutput());
+ return;
+}
+//--------------------------------------------------------------------
+
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSGENERICFILTER_H
+#define CLITKEXTRACTLUNGSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractLungFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+ template<class ArgsInfoType>
+ class ITK_EXPORT ExtractLungGenericFilter:
+ public ImageToImageGenericFilter<ExtractLungGenericFilter<ArgsInfoType> >
+ {
+
+ public:
+ //--------------------------------------------------------------------
+ ExtractLungGenericFilter();
+
+ //--------------------------------------------------------------------
+ typedef ExtractLungGenericFilter Self;
+ typedef ImageToImageGenericFilter<ExtractLungGenericFilter<ArgsInfoType> > Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ //--------------------------------------------------------------------
+ itkNewMacro(Self);
+ itkTypeMacro(ExtractLungGenericFilter, LightObject);
+
+ //--------------------------------------------------------------------
+ void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Main function called each time the filter is updated
+ template<class ImageType>
+ void UpdateWithInputImageType();
+
+ protected:
+ template<unsigned int Dim> void InitializeImageType();
+ ArgsInfoType mArgsInfo;
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLungGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTLUNGSGENERICFILTER_H
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLUNGSGENERICFILTER_TXX
+#define CLITKEXTRACTLUNGSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractLungGenericFilter<ArgsInfoType>::ExtractLungGenericFilter():
+ ImageToImageGenericFilter<Self>("ExtractLung")
+{
+ // Default values
+ cmdline_parser_clitkExtractLung_init(&mArgsInfo);
+ InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractLungGenericFilter<ArgsInfoType>::InitializeImageType()
+{
+ ADD_IMAGE_TYPE(Dim, short);
+ // ADD_IMAGE_TYPE(Dim, int);
+ // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractLungGenericFilter<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.output_given) AddOutputFilename(mArgsInfo.output_arg);
+ if (mArgsInfo.outputTrachea_given) AddOutputFilename(mArgsInfo.outputTrachea_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractLungGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
+{
+ // Mask & output image type
+ typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
+ typedef itk::Image<uchar, ImageType::ImageDimension> MaskImageType;
+
+ // Reading input
+ typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+ typename MaskImageType::Pointer patient = this->template GetInput<MaskImageType>(1);
+
+ // Create filter
+ typedef clitk::ExtractLungFilter<ImageType, MaskImageType> FilterType;
+ typename FilterType::Pointer filter = FilterType::New();
+
+ // Set global Options
+ filter->SetArgsInfo(mArgsInfo);
+ filter->SetInput(input);
+ filter->SetInputPatientMask(patient, mArgsInfo.patientBG_arg);
+
+ // Go !
+ filter->Update();
+
+ // Check if error
+ if (filter->HasError()) {
+ SetLastError(filter->GetLastError());
+ // No output
+ return;
+ }
+
+ // Write/Save results
+ typename OutputImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<OutputImageType>(output);
+ if (mArgsInfo.outputTrachea_given)
+ this->template SetNextOutput<typename FilterType::MaskImageType>(filter->GetTracheaImage());
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTLUNGSGENERICFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractLymphStations_ggo.h"
+#include "clitkExtractLymphStationsGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+ // Init command line
+ GGO(clitkExtractLymphStations, args_info);
+ CLITK_INIT;
+
+ // Filter
+ typedef clitk::ExtractLymphStationsGenericFilter<args_info_clitkExtractLymphStations> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+
+ filter->SetArgsInfo(args_info);
+ filter->Update();
+
+ if (filter->HasError()) {
+ std::cout << filter->GetLastError() << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkExtractLymphStations.ggo
+package "clitkExtractLymphStations"
+version "1.0"
+purpose "Extract LymphStations with help of TODO"
+
+option "config" - "Config file" string no
+option "imagetypes" - "Display allowed image types" flag off
+option "verbose" v "Verbose" flag off
+option "verboseStep" - "Verbose each step" flag off
+option "writeStep" w "Write image at each step" flag off
+option "verboseOption" - "Display options values" flag off
+option "verboseWarningOff" - "Do not display warning" flag off
+
+section "I/O"
+
+option "mediastinum" m "Input mediastinum mask filename" string yes
+option "trachea" t "Input trachea mask filename" string yes
+option "output" o "Output lungs mask filename" string yes
+
+option "carenaZposition" c "Sup-Inf position of the carena (in mm)" double no
+option "middleLobeBronchusZposition" b "Sup-Inf position of the middle lobe bronchus (in mm)" double no
+option "spacing" - "Intermediate resampling spacing" double no default="6"
+option "fuzzy1" - "Fuzzy relative position threshold" double no default="0.6"
+
+
+
+
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_H
+#define CLITKEXTRACTLYMPHSTATIONSFILTER_H
+
+#include "clitkFilterBase.h"
+
+namespace clitk {
+
+ //--------------------------------------------------------------------
+ /*
+ Try to extract the LymphStations part of a thorax CT.
+ Inputs :
+ - Patient label image
+ - Lungs label image
+ - Bones label image
+ */
+ //--------------------------------------------------------------------
+
+ template <class TImageType>
+ class ITK_EXPORT ExtractLymphStationsFilter:
+ public clitk::FilterBase,
+ public itk::ImageToImageFilter<TImageType, TImageType>
+ {
+
+ public:
+ /** Standard class typedefs. */
+ typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+ typedef ExtractLymphStationsFilter Self;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(ExtractLymphStationsFilter, InPlaceImageFilter);
+ FILTERBASE_INIT;
+
+ /** Some convenient typedefs. */
+ typedef TImageType ImageType;
+ typedef typename ImageType::ConstPointer ImageConstPointer;
+ typedef typename ImageType::Pointer ImagePointer;
+ typedef typename ImageType::RegionType ImageRegionType;
+ typedef typename ImageType::PixelType ImagePixelType;
+ typedef typename ImageType::SizeType ImageSizeType;
+ typedef typename ImageType::IndexType ImageIndexType;
+
+ /** Connect inputs */
+ void SetInputMediastinumLabelImage(const TImageType * image, ImagePixelType bg=0);
+ void SetInputTracheaLabelImage(const TImageType * image, ImagePixelType bg=0);
+
+ /** ImageDimension constants */
+ itkStaticConstMacro(ImageDimension, unsigned int, TImageType::ImageDimension);
+
+ // Set all options at a time
+ template<class ArgsInfoType>
+ void SetArgsInfo(ArgsInfoType arg);
+
+ // Background / Foreground
+ itkSetMacro(BackgroundValueMediastinum, ImagePixelType);
+ itkGetConstMacro(BackgroundValueMediastinum, ImagePixelType);
+ //GGO_DefineOption(MediastinumBG, SetBackgroundValueMediastinum, ImagePixelType);
+
+ itkSetMacro(BackgroundValueTrachea, ImagePixelType);
+ itkGetConstMacro(BackgroundValueTrachea, ImagePixelType);
+ //GGO_DefineOption(TracheaBG, SetBackgroundValueTrachea, ImagePixelType);
+
+ itkGetConstMacro(BackgroundValue, ImagePixelType);
+ itkGetConstMacro(ForegroundValue, ImagePixelType);
+
+ itkSetMacro(CarenaZPositionInMM, double);
+ itkGetConstMacro(CarenaZPositionInMM, double);
+ GGO_DefineOption(carenaZposition, SetCarenaZPositionInMM, double);
+
+ itkSetMacro(MiddleLobeBronchusZPositionInMM, double);
+ itkGetConstMacro(MiddleLobeBronchusZPositionInMM, double);
+ GGO_DefineOption(middleLobeBronchusZposition, SetMiddleLobeBronchusZPositionInMM, double);
+
+ itkSetMacro(IntermediateSpacing, double);
+ itkGetConstMacro(IntermediateSpacing, double);
+ GGO_DefineOption(spacing, SetIntermediateSpacing, double);
+
+ itkSetMacro(FuzzyThreshold1, double);
+ itkGetConstMacro(FuzzyThreshold1, double);
+ GGO_DefineOption(fuzzy1, SetFuzzyThreshold1, double);
+
+
+
+ protected:
+ ExtractLymphStationsFilter();
+ virtual ~ExtractLymphStationsFilter() {}
+
+ virtual void GenerateOutputInformation();
+ virtual void GenerateInputRequestedRegion();
+ virtual void GenerateData();
+
+ itkSetMacro(BackgroundValue, ImagePixelType);
+ itkSetMacro(ForegroundValue, ImagePixelType);
+
+ ImageConstPointer m_mediastinum;
+ ImageConstPointer m_trachea;
+ ImagePointer m_working_image;
+ ImagePointer m_working_trachea;
+ ImagePointer m_output;
+
+ ImagePixelType m_BackgroundValueMediastinum;
+ ImagePixelType m_BackgroundValueTrachea;
+ ImagePixelType m_BackgroundValue;
+ ImagePixelType m_ForegroundValue;
+
+ double m_CarenaZPositionInMM;
+ double m_MiddleLobeBronchusZPositionInMM;
+ double m_IntermediateSpacing;
+ double m_FuzzyThreshold1;
+
+ private:
+ ExtractLymphStationsFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLymphStationsFilter.txx"
+#endif
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
+#define CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
+
+// clitk
+#include "clitkCommon.h"
+#include "clitkExtractLymphStationsFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+#include "clitkAutoCropFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include <deque>
+#include <itkStatisticsLabelMapFilter.h>
+#include <itkLabelImageToStatisticsLabelMapFilter.h>
+#include <itkRegionOfInterestImageFilter.h>
+#include <itkBinaryThresholdImageFilter.h>
+#include <itkImageSliceConstIteratorWithIndex.h>
+
+// itk ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TImageType>
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractLymphStationsFilter():
+ clitk::FilterBase(),
+ itk::ImageToImageFilter<TImageType, TImageType>()
+{
+ this->SetNumberOfRequiredInputs(1);
+ SetBackgroundValueMediastinum(0);
+ SetBackgroundValueTrachea(0);
+ SetBackgroundValue(0);
+ SetForegroundValue(1);
+
+ SetIntermediateSpacing(6);
+ SetFuzzyThreshold1(0.6);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+SetInputMediastinumLabelImage(const TImageType * image, ImagePixelType bg) {
+ this->SetNthInput(0, const_cast<TImageType *>(image));
+ m_BackgroundValueMediastinum = bg;
+ SetCarenaZPositionInMM(image->GetOrigin()[2]+image->GetLargestPossibleRegion().GetSize()[2]*image->GetSpacing()[2]);
+ SetMiddleLobeBronchusZPositionInMM(image->GetOrigin()[2]);
+ // DD(m_CarenaZPositionInMM);
+// DD(m_MiddleLobeBronchusZPositionInMM);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+SetInputTracheaLabelImage(const TImageType * image, ImagePixelType bg) {
+ this->SetNthInput(1, const_cast<TImageType *>(image));
+ m_BackgroundValueTrachea = bg;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+template<class ArgsInfoType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+ SetVerboseOption_GGO(mArgsInfo);
+ SetVerboseStep_GGO(mArgsInfo);
+ SetWriteStep_GGO(mArgsInfo);
+ SetVerboseWarningOff_GGO(mArgsInfo);
+ SetCarenaZPositionInMM_GGO(mArgsInfo);
+ SetMiddleLobeBronchusZPositionInMM_GGO(mArgsInfo);
+ SetIntermediateSpacing_GGO(mArgsInfo);
+ SetFuzzyThreshold1_GGO(mArgsInfo);
+ //SetBackgroundValueMediastinum_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateOutputInformation() {
+ // Superclass::GenerateOutputInformation();
+
+ // Get input
+ m_mediastinum = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(0));
+ m_trachea = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(1));
+
+ // ----------------------------------------------------------------
+ // ----------------------------------------------------------------
+ // Superior limit = carena
+ // Inferior limit = origine middle lobe bronchus
+ StartNewStep("Inf/Sup limits with carena/bronchus");
+ ImageRegionType region = m_mediastinum->GetLargestPossibleRegion(); DD(region);
+ ImageSizeType size = region.GetSize();
+ ImageIndexType index = region.GetIndex();
+ DD(m_CarenaZPositionInMM);
+ DD(m_MiddleLobeBronchusZPositionInMM);
+ index[2] = floor((m_MiddleLobeBronchusZPositionInMM - m_mediastinum->GetOrigin()[2]) / m_mediastinum->GetSpacing()[2]);
+ size[2] = ceil((m_CarenaZPositionInMM-m_MiddleLobeBronchusZPositionInMM) / m_mediastinum->GetSpacing()[2]);
+ region.SetSize(size);
+ region.SetIndex(index);
+ DD(region);
+ typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
+ typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+ cropFilter->SetInput(m_mediastinum);
+ cropFilter->SetRegionOfInterest(region);
+ cropFilter->Update();
+ m_working_image = cropFilter->GetOutput();
+ // Auto Crop (because following rel pos is faster)
+ m_working_image = clitk::AutoCrop<ImageType>(m_working_image, 0);
+ StopCurrentStep<ImageType>(m_working_image);
+ m_output = m_working_image;
+
+ // ----------------------------------------------------------------
+ // ----------------------------------------------------------------
+ // Separate trachea in two CCL
+ StartNewStep("Separate trachea");
+ // DD(region);
+ ImageRegionType trachea_region = m_trachea->GetLargestPossibleRegion();
+ for(int i=0; i<3; i++) {
+ index[i] = floor(((index[i]*m_mediastinum->GetSpacing()[i])+m_mediastinum->GetOrigin()[i]
+ -m_trachea->GetOrigin()[i])/m_trachea->GetSpacing()[i]);
+ // DD(index[i]);
+ size[i] = ceil((size[i]*m_mediastinum->GetSpacing()[i])/m_trachea->GetSpacing()[i]);
+ // DD(size[i]);
+ if (index[i] < 0) {
+ size[i] += index[i];
+ index[i] = 0;
+ }
+ if (size[i]+index[i] > (trachea_region.GetSize()[i] + trachea_region.GetIndex()[i])) {
+ size[i] = trachea_region.GetSize()[i] + trachea_region.GetIndex()[i] - index[i];
+ }
+ }
+ // DD(index);
+ // DD(size);
+ region.SetIndex(index);
+ region.SetSize(size);
+ // typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
+ // typename CropFilterType::Pointer
+ cropFilter = CropFilterType::New();
+ // m_trachea.Print(std::cout);
+ cropFilter->SetInput(m_trachea);
+ cropFilter->SetRegionOfInterest(region);
+ cropFilter->Update();
+ m_working_trachea = cropFilter->GetOutput();
+
+ // Labelize and consider two main labels
+ m_working_trachea = Labelize<ImageType>(m_working_trachea, 0, true, 1);
+ StopCurrentStep<ImageType>(m_working_trachea);
+
+ // Detect wich label is at Left
+ typedef itk::ImageSliceConstIteratorWithIndex<ImageType> SliceIteratorType;
+ SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
+ iter.SetFirstDirection(0);
+ iter.SetSecondDirection(1);
+ iter.GoToBegin();
+ bool stop = false;
+ ImagePixelType leftLabel;
+ while (!stop) {
+ if (iter.Get() != m_BackgroundValueTrachea) {
+ // DD(iter.GetIndex());
+ // DD((int)iter.Get());
+ leftLabel = iter.Get();
+ stop = true;
+ }
+ ++iter;
+ }
+ DD((int)leftLabel);
+
+ // Relative position
+ StartNewStep("Left/Right limits with trachea");
+
+ // Select LeftLabel (set label 1 to 0)
+ ImagePointer temp = SetBackground<ImageType, ImageType>(m_working_trachea, m_working_trachea, 1, 0);
+ writeImage<ImageType>(temp, "temp1.mhd");
+
+ // Left relative position
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<TImageType> RelPosFilterType;
+ typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInput(m_working_image);
+ relPosFilter->SetInputObject(temp);
+ relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+ relPosFilter->Update();
+ m_working_image = relPosFilter->GetOutput();
+
+ // Select RightLabel (set label 2 to 0)
+ temp = SetBackground<ImageType, ImageType>(m_working_trachea, m_working_trachea, 2, 0);
+ writeImage<ImageType>(temp, "temp2.mhd");
+
+ // Left relative position
+ relPosFilter = RelPosFilterType::New();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOn();
+ relPosFilter->WriteStepOn();
+ relPosFilter->SetInput(m_working_image);
+ relPosFilter->SetInputObject(temp);
+ relPosFilter->SetOrientationType(RelPosFilterType::LeftTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+ relPosFilter->Update();
+ m_working_image = relPosFilter->GetOutput();
+
+
+ //-----------------------------------------------------
+ // StartNewStep("Left/Right limits with trachea (slice by slice");
+ // typedef SliceBySliceImageFilter<ImageType, ImageType,
+
+
+ DD("end");
+ m_output = m_working_image;
+ StopCurrentStep<ImageType>(m_output);
+
+ // Set output image information (required)
+ ImagePointer outputImage = this->GetOutput(0);
+ outputImage->SetRegions(m_working_image->GetLargestPossibleRegion());
+ outputImage->SetOrigin(m_working_image->GetOrigin());
+ outputImage->SetRequestedRegion(m_working_image->GetLargestPossibleRegion());
+ DD("end2");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateInputRequestedRegion() {
+ DD("GenerateInputRequestedRegion");
+ // Call default
+ Superclass::GenerateInputRequestedRegion();
+ // Following needed because output region can be greater than input (trachea)
+ ImagePointer mediastinum = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+ ImagePointer trachea = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
+ mediastinum->SetRequestedRegion(mediastinum->GetLargestPossibleRegion());
+ trachea->SetRequestedRegion(trachea->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateData() {
+ DD("GenerateData");
+ // Final Step -> graft output (if SetNthOutput => redo)
+ this->GraftOutput(m_output);
+}
+//--------------------------------------------------------------------
+
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H
+#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractLymphStationsFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+ template<class ArgsInfoType>
+ class ITK_EXPORT ExtractLymphStationsGenericFilter:
+ public ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> >
+ {
+
+ public:
+ //--------------------------------------------------------------------
+ ExtractLymphStationsGenericFilter();
+
+ //--------------------------------------------------------------------
+ typedef ExtractLymphStationsGenericFilter Self;
+ typedef ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> > Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ //--------------------------------------------------------------------
+ itkNewMacro(Self);
+ itkTypeMacro(ExtractLymphStationsGenericFilter, LightObject);
+
+ //--------------------------------------------------------------------
+ void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Main function called each time the filter is updated
+ template<class ImageType>
+ void UpdateWithInputImageType();
+
+ protected:
+ template<unsigned int Dim> void InitializeImageType();
+ ArgsInfoType mArgsInfo;
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractLymphStationsGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_H
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX
+#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::ExtractLymphStationsGenericFilter():
+ ImageToImageGenericFilter<Self>("ExtractLymphStations")
+{
+ // Default values
+ cmdline_parser_clitkExtractLymphStations_init(&mArgsInfo);
+ InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::InitializeImageType()
+{
+ ADD_IMAGE_TYPE(Dim, uchar);
+ // ADD_IMAGE_TYPE(Dim, short);
+ // ADD_IMAGE_TYPE(Dim, int);
+ // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a)
+{
+ mArgsInfo=a;
+ SetIOVerbose(mArgsInfo.verbose_flag);
+ if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+ if (mArgsInfo.mediastinum_given) AddInputFilename(mArgsInfo.mediastinum_arg);
+ if (mArgsInfo.trachea_given) AddInputFilename(mArgsInfo.trachea_arg);
+ if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
+{
+ // Reading input
+ typename ImageType::Pointer mediastinum = this->template GetInput<ImageType>(0);
+ typename ImageType::Pointer trachea = this->template GetInput<ImageType>(1);
+
+ // Create filter
+ typedef clitk::ExtractLymphStationsFilter<ImageType> FilterType;
+ typename FilterType::Pointer filter = FilterType::New();
+
+ // Set global Options
+ filter->SetInputMediastinumLabelImage(mediastinum, 0); // change 0 with BG
+ filter->SetInputTracheaLabelImage(trachea, 0); // change 0 with BG
+ filter->SetArgsInfo(mArgsInfo);
+
+ // Go !
+ filter->Update();
+
+ // Check if error
+ if (filter->HasError()) {
+ SetLastError(filter->GetLastError());
+ // No output
+ return;
+ }
+
+ // Write/Save results
+ typename ImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<ImageType>(output);
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTLYMPHSTATIONSSGENERICFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractMediastinum_ggo.h"
+#include "clitkExtractMediastinumGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+ // Init command line
+ GGO(clitkExtractMediastinum, args_info);
+ CLITK_INIT;
+
+ // Filter
+ typedef clitk::ExtractMediastinumGenericFilter<args_info_clitkExtractMediastinum> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+
+ filter->SetArgsInfo(args_info);
+ filter->Update();
+
+ if (filter->HasError()) {
+ std::cout << filter->GetLastError() << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkExtractMediastinum.ggo
+package "clitkExtractMediastinum"
+version "1.0"
+purpose "Extract mediastinum with help of patient/lungs/bones mask"
+
+option "config" - "Config file" string no
+option "imagetypes" - "Display allowed image types" flag off
+option "verbose" v "Verbose" flag off
+option "verboseStep" - "Verbose each step" flag off
+option "writeStep" w "Write image at each step" flag off
+option "verboseOption" - "Display options values" flag off
+option "verboseWarningOff" - "Do not display warning" flag off
+
+section "I/O"
+
+option "patient" p "Input patient mask filename" string yes
+option "patientBG" - "Patient Background" int default="0" no
+option "bones" b "Input bones mask filename" string yes
+option "bonesBG" - "Bones Background" int default="0" no
+option "lung" l "Input lung mask filename" string yes
+option "lungBG" - "Lung Background" int default="0" no
+option "lungLeft" - "Lung Left value" int default="1" no
+option "lungRight" - "Lung Right value" int default="2" no
+
+option "output" o "Output lungs mask filename" string yes
+
+section "Step 1 : Left/Right limits with lungs"
+
+option "spacing" - "Intermediate resampling spacing" double no default="6"
+option "fuzzy1" - "Fuzzy relative position threshold" double no default="0.6"
+
+section "Step 2 : Ant/Post limits with bones"
+
+option "fuzzy2" - "Fuzzy relative position threshold" double no default="0.6"
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMFILTER_H
+#define CLITKEXTRACTMEDIASTINUMFILTER_H
+
+#include "clitkFilterBase.h"
+
+namespace clitk {
+
+ //--------------------------------------------------------------------
+ /*
+ Try to extract the mediastinum part of a thorax CT.
+ Inputs :
+ - Patient label image
+ - Lungs label image
+ - Bones label image
+ */
+ //--------------------------------------------------------------------
+
+ template <class TImageType>
+ class ITK_EXPORT ExtractMediastinumFilter:
+ public clitk::FilterBase,
+ public itk::ImageToImageFilter<TImageType, TImageType>
+ {
+
+ public:
+ /** Standard class typedefs. */
+ typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+ typedef ExtractMediastinumFilter Self;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(ExtractMediastinumFilter, InPlaceImageFilter);
+ FILTERBASE_INIT;
+
+ /** Some convenient typedefs. */
+ typedef TImageType ImageType;
+ typedef typename ImageType::ConstPointer ImageConstPointer;
+ typedef typename ImageType::Pointer ImagePointer;
+ typedef typename ImageType::RegionType ImageRegionType;
+ typedef typename ImageType::PixelType ImagePixelType;
+ typedef typename ImageType::SizeType ImageSizeType;
+ typedef typename ImageType::IndexType ImageIndexType;
+
+ /** Connect inputs */
+ void SetInputPatientLabelImage(const TImageType * image, ImagePixelType bg=0);
+ void SetInputLungLabelImage(const TImageType * image, ImagePixelType bg=0,
+ ImagePixelType fgLeftLung=1, ImagePixelType fgRightLung=2);
+ void SetInputBonesLabelImage(const TImageType * image, ImagePixelType bg=0);
+
+ /** ImageDimension constants */
+ itkStaticConstMacro(ImageDimension, unsigned int, TImageType::ImageDimension);
+
+ // Set all options at a time
+ template<class ArgsInfoType>
+ void SetArgsInfo(ArgsInfoType arg);
+
+ // Background / Foreground
+ itkSetMacro(BackgroundValuePatient, ImagePixelType);
+ itkGetConstMacro(BackgroundValuePatient, ImagePixelType);
+ GGO_DefineOption(patientBG, SetBackgroundValuePatient, ImagePixelType);
+
+ itkSetMacro(BackgroundValueLung, ImagePixelType);
+ itkGetConstMacro(BackgroundValueLung, ImagePixelType);
+ GGO_DefineOption(lungBG, SetBackgroundValueLung, ImagePixelType);
+
+ itkSetMacro(BackgroundValueBones, ImagePixelType);
+ itkGetConstMacro(BackgroundValueBones, ImagePixelType);
+ GGO_DefineOption(bonesBG, SetBackgroundValueBones, ImagePixelType);
+
+ itkGetConstMacro(BackgroundValue, ImagePixelType);
+ itkGetConstMacro(ForegroundValue, ImagePixelType);
+
+ itkSetMacro(ForegroundValueLeftLung, ImagePixelType);
+ itkGetConstMacro(ForegroundValueLeftLung, ImagePixelType);
+ GGO_DefineOption(lungLeft, SetForegroundValueLeftLung, ImagePixelType);
+
+ itkSetMacro(ForegroundValueRightLung, ImagePixelType);
+ itkGetConstMacro(ForegroundValueRightLung, ImagePixelType);
+ GGO_DefineOption(lungRight, SetForegroundValueRightLung, ImagePixelType);
+
+ 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);
+
+ protected:
+ ExtractMediastinumFilter();
+ virtual ~ExtractMediastinumFilter() {}
+
+ virtual void GenerateOutputInformation();
+ virtual void GenerateInputRequestedRegion();
+ virtual void GenerateData();
+
+ itkSetMacro(BackgroundValue, ImagePixelType);
+ itkSetMacro(ForegroundValue, ImagePixelType);
+
+ ImagePixelType m_BackgroundValuePatient;
+ ImagePixelType m_BackgroundValueLung;
+ ImagePixelType m_BackgroundValueBones;
+ ImagePixelType m_ForegroundValueLeftLung;
+ ImagePixelType m_ForegroundValueRightLung;
+
+ ImagePixelType m_BackgroundValue;
+ ImagePixelType m_ForegroundValue;
+
+ double m_IntermediateSpacing;
+ double m_FuzzyThreshold1;
+ double m_FuzzyThreshold2;
+
+ private:
+ ExtractMediastinumFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractMediastinumFilter.txx"
+#endif
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMFILTER_TXX
+#define CLITKEXTRACTMEDIASTINUMFILTER_TXX
+
+// clitk
+#include "clitkCommon.h"
+#include "clitkExtractMediastinumFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+#include "clitkSegmentationFunctions.h"
+
+// itk
+#include <deque>
+#include "itkStatisticsLabelMapFilter.h"
+#include "itkLabelImageToStatisticsLabelMapFilter.h"
+#include "itkRegionOfInterestImageFilter.h"
+#include "itkBinaryThresholdImageFilter.h"
+
+// itk ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TImageType>
+clitk::ExtractMediastinumFilter<TImageType>::
+ExtractMediastinumFilter():
+ clitk::FilterBase(),
+ itk::ImageToImageFilter<TImageType, TImageType>()
+{
+ this->SetNumberOfRequiredInputs(3);
+
+ SetBackgroundValuePatient(0);
+ SetBackgroundValueLung(0);
+ SetBackgroundValueBones(0);
+ SetForegroundValueLeftLung(1);
+ SetForegroundValueRightLung(2);
+ SetBackgroundValue(0);
+ SetForegroundValue(1);
+
+ SetIntermediateSpacing(6);
+ SetFuzzyThreshold1(0.6);
+ SetFuzzyThreshold2(0.7);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+SetInputPatientLabelImage(const TImageType * image, ImagePixelType bg) {
+ this->SetNthInput(0, const_cast<TImageType *>(image));
+ m_BackgroundValuePatient = bg;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+SetInputLungLabelImage(const TImageType * image, ImagePixelType bg,
+ ImagePixelType fgLeft, ImagePixelType fgRight) {
+ this->SetNthInput(1, const_cast<TImageType *>(image));
+ m_BackgroundValueLung = bg;
+ m_ForegroundValueLeftLung = fgLeft;
+ m_ForegroundValueRightLung = fgRight;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+SetInputBonesLabelImage(const TImageType * image, ImagePixelType bg) {
+ this->SetNthInput(2, const_cast<TImageType *>(image));
+ m_BackgroundValueBones = bg;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+template<class ArgsInfoType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+SetArgsInfo(ArgsInfoType mArgsInfo)
+{
+ SetVerboseOption_GGO(mArgsInfo);
+ SetVerboseStep_GGO(mArgsInfo);
+ SetWriteStep_GGO(mArgsInfo);
+ SetVerboseWarningOff_GGO(mArgsInfo);
+
+ SetBackgroundValuePatient_GGO(mArgsInfo);
+ SetBackgroundValueLung_GGO(mArgsInfo);
+ SetBackgroundValueBones_GGO(mArgsInfo);
+
+ SetForegroundValueLeftLung_GGO(mArgsInfo);
+ SetForegroundValueRightLung_GGO(mArgsInfo);
+
+ SetIntermediateSpacing_GGO(mArgsInfo);
+ SetFuzzyThreshold1_GGO(mArgsInfo);
+ SetFuzzyThreshold2_GGO(mArgsInfo);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+GenerateOutputInformation() {
+ ImagePointer input = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+ ImagePointer outputImage = this->GetOutput(0);
+ outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+GenerateInputRequestedRegion() {
+ // Call default
+ Superclass::GenerateInputRequestedRegion();
+ // Get input pointers
+ ImagePointer patient = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+ ImagePointer lung = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
+ ImagePointer bones = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(2));
+
+ patient->SetRequestedRegion(patient->GetLargestPossibleRegion());
+ lung->SetRequestedRegion(lung->GetLargestPossibleRegion());
+ bones->SetRequestedRegion(bones->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractMediastinumFilter<TImageType>::
+GenerateData() {
+ // Get input pointers
+ ImageConstPointer patient = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(0));
+ ImageConstPointer lung = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(1));
+ ImageConstPointer bones = dynamic_cast<const TImageType*>(itk::ProcessObject::GetInput(2));
+
+ // Get output pointer
+ ImagePointer output;
+
+ // Step 1: patient minus lungs, minus bones
+ StartNewStep("Patient contours minus lungs and minus bones");
+ typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
+ typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
+ boolFilter->InPlaceOn();
+ boolFilter->SetInput1(patient);
+ boolFilter->SetInput2(lung);
+ boolFilter->SetOperationType(BoolFilterType::AndNot);
+ boolFilter->Update();
+ boolFilter->SetInput1(boolFilter->GetOutput());
+ boolFilter->SetInput2(bones);
+ boolFilter->SetOperationType(BoolFilterType::AndNot);
+ boolFilter->Update();
+ output = boolFilter->GetOutput();
+
+ output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
+ ////autoCropFilter->GetOutput(); typedef clitk::AutoCropFilter<ImageType> CropFilterType;
+ //typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+ //cropFilter->SetInput(output);
+ //cropFilter->Update();
+ //output = cropFilter->GetOutput();
+
+ this->template StopCurrentStep<TImageType>(output);
+
+ // Step 2: LR limits from lung (need separate lung ?)
+ StartNewStep("Left/Right limits with lungs");
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<TImageType> RelPosFilterType;
+ typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInput(output);
+ relPosFilter->SetInputObject(lung);
+ relPosFilter->SetOrientationType(RelPosFilterType::LeftTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+ relPosFilter->Update();
+ output = relPosFilter->GetOutput();
+
+ relPosFilter->SetInput(output);
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInputObject(lung);
+ relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
+ relPosFilter->Update();
+ output = relPosFilter->GetOutput();
+ this->template StopCurrentStep<TImageType>(output);
+
+ // Step 3: AP limits from bones
+ StartNewStep("Ant/Post limits with bones");
+ relPosFilter->SetCurrentStepNumber(0);
+ relPosFilter->ResetPipeline();// = RelPosFilterType::New();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInput(output);
+ relPosFilter->SetInputObject(bones);
+ relPosFilter->SetOrientationType(RelPosFilterType::AntTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
+ relPosFilter->Update();
+
+ relPosFilter->SetInput(relPosFilter->GetOutput());
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInputObject(bones);
+ relPosFilter->SetOrientationType(RelPosFilterType::PostTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
+ relPosFilter->Update();
+ output = relPosFilter->GetOutput();
+ this->template StopCurrentStep<TImageType>(output);
+
+ // Get CCL
+ output = clitk::Labelize<TImageType>(output, GetBackgroundValue(), true, 100);
+ // output = RemoveLabels<TImageType>(output, BG, param->GetLabelsToRemove());
+ output = clitk::KeepLabels<TImageType>(output, GetBackgroundValue(),
+ GetForegroundValue(), 1, 1, 0);
+
+ output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
+ // cropFilter = CropFilterType::New();
+ //cropFilter->SetInput(output);
+ //cropFilter->Update();
+ //output = cropFilter->GetOutput();
+
+ // Final Step -> set output
+ this->SetNthOutput(0, output);
+}
+//--------------------------------------------------------------------
+
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMSGENERICFILTER_H
+#define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_H
+
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractMediastinumFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+ template<class ArgsInfoType>
+ class ITK_EXPORT ExtractMediastinumGenericFilter:
+ public ImageToImageGenericFilter<ExtractMediastinumGenericFilter<ArgsInfoType> >
+ {
+
+ public:
+ //--------------------------------------------------------------------
+ ExtractMediastinumGenericFilter();
+
+ //--------------------------------------------------------------------
+ typedef ExtractMediastinumGenericFilter Self;
+ typedef ImageToImageGenericFilter<ExtractMediastinumGenericFilter<ArgsInfoType> > Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ //--------------------------------------------------------------------
+ itkNewMacro(Self);
+ itkTypeMacro(ExtractMediastinumGenericFilter, LightObject);
+
+ //--------------------------------------------------------------------
+ void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Main function called each time the filter is updated
+ template<class ImageType>
+ void UpdateWithInputImageType();
+
+ protected:
+ template<unsigned int Dim> void InitializeImageType();
+ ArgsInfoType mArgsInfo;
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractMediastinumGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_H
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTMEDIASTINUMSGENERICFILTER_TXX
+#define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_TXX
+
+#include "clitkImageCommon.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::ExtractMediastinumGenericFilter():
+ ImageToImageGenericFilter<Self>("ExtractMediastinum")
+{
+ // Default values
+ cmdline_parser_clitkExtractMediastinum_init(&mArgsInfo);
+ InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::InitializeImageType()
+{
+ ADD_IMAGE_TYPE(Dim, uchar);
+ // 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)
+{
+ mArgsInfo=a;
+ SetIOVerbose(mArgsInfo.verbose_flag);
+ if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+ 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.output_given) AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
+{
+ // Reading input
+ 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);
+
+ // Create filter
+ typedef clitk::ExtractMediastinumFilter<ImageType> FilterType;
+ typename FilterType::Pointer filter = FilterType::New();
+
+ // Set global Options
+ 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->SetArgsInfo(mArgsInfo);
+
+ // Go !
+ filter->Update();
+
+ // Check if error
+ if (filter->HasError()) {
+ SetLastError(filter->GetLastError());
+ // No output
+ return;
+ }
+
+ // Write/Save results
+ typename ImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<ImageType>(output);
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKEXTRACTMEDIASTINUMSGENERICFILTER_TXX
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+// clitk
+#include "clitkExtractPatient_ggo.h"
+#include "clitkExtractPatientGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+ // Init command line
+ GGO(clitkExtractPatient, args_info);
+ CLITK_INIT;
+
+ // Filter
+ typedef clitk::ExtractPatientGenericFilter<args_info_clitkExtractPatient> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+
+ filter->SetArgsInfo(args_info);
+ filter->Update();
+
+ if (filter->HasError()) {
+ std::cout << filter->GetLastError() << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkExtractPatient.ggo
+package "clitkExtractPatient"
+version "1.0"
+purpose "Prefer high resolution input and resample (NN) output at the end (like). Input is binarized using initial thresholds, connected components are labeled (firstLabel). The air label (1) is removed. The remaining is binarized and relabeled, patient should now be the principal label (secondLabel). Two mechanismes are provided to influence the label images. Crop to reduce connectivity (image is restored to original size), eg for SBF. Decomposition through ersion and reconstruction through dilation (slow), eg for Pulmo bellows. Choose which labels to keep from second Label image. Final mask is cleaned by opening and closing."
+
+option "config" - "Config file" string no
+option "imagetypes" - "Display allowed image types" flag off
+option "verbose" v "Verbose" flag off
+option "verboseStep" - "Verbose each step" flag off
+option "writeStep" w "Write image at each step" flag off
+option "verboseOption" - "Display options values" flag off
+option "verboseWarningOff" - "Do not display warning" flag off
+
+section "I/O"
+
+option "input" i "Input image filename" string yes
+option "output" o "Output image filename" string yes
+
+section "Binarize"
+
+option "lower" - "Initial lower threshold" double no
+option "upper" - "Initial upper threshold" double no default="-300"
+
+section "First Label Image (air=1)"
+
+option "erode1" - "Decompose through erosion" flag off
+option "radius1" - "Radius for erosion and dilation" int multiple no default="1"
+option "new1" - "Number of new labels" int no default="1"
+option "max1" - "Max number of labels to consider" int no default="2"
+
+section "Second Label Image (air=1)"
+
+option "erode2" - "Decompose through erosion" flag off
+option "radius2" - "Radius for erosion and dilation" int multiple no default="1"
+option "new2" - "Number of new labels" int no default="1"
+option "max2" - "Max number of labels to consider" int no default="2"
+# option "crop" - "Crop the first label image" flag off
+# option "boundingBox" b "Bounding box of the crop region (minX,maxX,...)" int no multiple
+# option "lowerS" - "Size of the lower crop region" int no multiple
+# option "upperS" - "Size of the upper crop region" int no multiple
+
+section "Labels to keep (air=1)"
+
+option "firstKeep" - "First label to keep" int no default="1"
+option "lastKeep" - "Last label to keep" int no default="1"
+option "remove" - "Labels to remove" int no multiple
+
+section "Clean-up"
+
+option "openClose" - "Perform morphological opening and closing with unit radius" flag on
+option "autoCrop" - "Crop final mask to BoundingBox" flag off
+
+
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTPATIENTFILTER_H
+#define CLITKEXTRACTPATIENTFILTER_H
+
+#include "clitkFilterBase.h"
+
+namespace clitk {
+
+ //--------------------------------------------------------------------
+ /*
+ Try to extract the Patient part of a thorax CT.
+
+ Prefer high resolution input and resample (NN) output at the end
+ (like). Input is binarized using initial thresholds, connected
+ components are labeled (firstLabel). The air label (1) is
+ removed. The remaining is binarized and relabeled, patient should
+ now be the principal label (secondLabel). Two mechanismes are
+ provided to influence the label images. Crop to reduce
+ connectivity (image is restored to original size), eg for
+ SBF. Decomposition through ersion and reconstruction through
+ dilation (slow), eg for Pulmo bellows. Choose which labels to keep
+ from second Label image. Final mask is cleaned by opening and
+ closing.
+
+ */
+ //--------------------------------------------------------------------
+
+ template <class TInputImageType, class TOutputImageType>
+ class ITK_EXPORT ExtractPatientFilter:
+ public clitk::FilterBase,
+ public itk::ImageToImageFilter<TInputImageType, TOutputImageType>
+ {
+ public:
+ /** Standard class typedefs. */
+ typedef ExtractPatientFilter Self;
+ typedef itk::ImageToImageFilter<TInputImageType, TOutputImageType> Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ /** Method for creation through the object factory. */
+ itkNewMacro(Self);
+
+ /** Run-time type information (and related methods). */
+ itkTypeMacro(ExtractPatientFilter, ImageToImageFilter);
+ FILTERBASE_INIT;
+
+ /** Some convenient typedefs. */
+ typedef TInputImageType InputImageType;
+ typedef typename InputImageType::ConstPointer InputImageConstPointer;
+ typedef typename InputImageType::Pointer InputImagePointer;
+ typedef typename InputImageType::RegionType InputImageRegionType;
+ typedef typename InputImageType::PixelType InputImagePixelType;
+ typedef typename InputImageType::SizeType InputImageSizeType;
+ typedef typename InputImageType::IndexType InputImageIndexType;
+
+ typedef TOutputImageType OutputImageType;
+ typedef typename OutputImageType::ConstPointer OutputImageConstPointer;
+ typedef typename OutputImageType::Pointer OutputImagePointer;
+ typedef typename OutputImageType::RegionType OutputImageRegionType;
+ typedef typename OutputImageType::PixelType OutputImagePixelType;
+ typedef typename OutputImageType::SizeType OutputImageSizeType;
+ typedef typename OutputImageType::IndexType OutputImageIndexType;
+
+ itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
+ typedef int InternalPixelType;
+ typedef itk::Image<InternalPixelType, ImageDimension> InternalImageType;
+ typedef typename InternalImageType::SizeType InternalImageSizeType;
+
+ /** Connect inputs */
+ void SetInput(const TInputImageType * image);
+
+ // 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(autoCrop, SetAutoCrop);
+
+ protected:
+ ExtractPatientFilter();
+ virtual ~ExtractPatientFilter() {}
+
+ itkSetMacro(BackgroundValue, OutputImagePixelType);
+ itkSetMacro(ForegroundValue, OutputImagePixelType);
+ itkGetConstMacro(BackgroundValue, OutputImagePixelType);
+ itkGetConstMacro(ForegroundValue, OutputImagePixelType);
+ OutputImagePixelType m_BackgroundValue;
+ OutputImagePixelType m_ForegroundValue;
+
+ InputImagePixelType m_UpperThreshold;
+ InputImagePixelType m_LowerThreshold;
+ bool m_UseLowerThreshold;
+ bool m_DecomposeAndReconstructDuringFirstStep;
+ bool m_DecomposeAndReconstructDuringSecondStep;
+ bool m_FinalOpenClose;
+ InternalImageSizeType m_Radius1;
+ InternalImageSizeType m_Radius2;
+ int m_MaximumNumberOfLabels1;
+ int m_MaximumNumberOfLabels2;
+ int m_NumberOfNewLabels1;
+ int m_NumberOfNewLabels2;
+ int m_FirstKeep;
+ int m_LastKeep;
+ bool m_AutoCrop;
+
+ virtual void GenerateOutputInformation();
+ virtual void GenerateData();
+
+ InputImageConstPointer input;
+ OutputImagePointer output;
+ typename InternalImageType::Pointer working_image;
+
+ private:
+ ExtractPatientFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
+ }; // end class
+ //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractPatientFilter.txx"
+#endif
+
+#endif
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#ifndef CLITKEXTRACTPATIENTFILTER_TXX
+#define CLITKEXTRACTPATIENTFILTER_TXX
+
+// clitk
+#include "clitkImageCommon.h"
+#include "clitkSetBackgroundImageFilter.h"
+#include "clitkDecomposeAndReconstructImageFilter.h"
+#include "clitkAutoCropFilter.h"
+
+// itk
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkBinaryMorphologicalClosingImageFilter.h"
+#include "itkBinaryMorphologicalOpeningImageFilter.h"
+#include "itkBinaryBallStructuringElement.h"
+#include "itkCastImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+ExtractPatientFilter():
+ clitk::FilterBase(),
+ itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
+{
+ this->SetNumberOfRequiredInputs(1);
+ SetBackgroundValue(0); // Must be zero
+ SetForegroundValue(1);
+
+ // Step 1: Threshold + CC + sort (Find low density areas)
+ SetUpperThreshold(-300);
+ SetLowerThreshold(-1000);
+ UseLowerThresholdOff();
+
+ // Step 2: DecomposeAndReconstructImageFilter (optional)
+ DecomposeAndReconstructDuringFirstStepOff();
+ InternalImageSizeType r;
+ r.Fill(1);
+ SetRadius1(r);
+ SetMaximumNumberOfLabels1(2);
+ SetNumberOfNewLabels1(1);
+
+ // Step 3: Remove the air (largest area).
+
+ // Step 4: 2nd DecomposeAndReconstructImageFilter
+ DecomposeAndReconstructDuringSecondStepOff();
+ SetRadius2(r);
+ SetMaximumNumberOfLabels2(2);
+ SetNumberOfNewLabels2(1);
+
+ // Step 5: Only keep label corresponding (Keep patient's labels)
+ SetFirstKeep(1);
+ SetLastKeep(1);
+
+ // Step 4: OpenClose (option)
+ FinalOpenCloseOn();
+ AutoCropOff();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+SetInput(const TInputImageType * image)
+{
+ this->SetNthInput(0, const_cast<TInputImageType *>(image));
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+template<class ArgsInfoType>
+void
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+SetArgsInfo(ArgsInfoType arg)
+{
+ SetVerboseOption_GGO(arg);
+ SetVerboseStep_GGO(arg);
+ SetWriteStep_GGO(arg);
+ SetVerboseWarningOff_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);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+GenerateOutputInformation() {
+
+ Superclass::GenerateOutputInformation();
+ input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+
+ // OutputImagePointer outputImage = this->GetOutput(0);
+// outputImage->SetRegions(input->GetLargestPossibleRegion());
+
+ // Get input pointers
+ static const unsigned int Dim = InputImageType::ImageDimension;
+ //input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // Step 1:
+ StartNewStep("Find low densities areas");
+ typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> BinarizeFilterType;
+ typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New();
+ binarizeFilter->SetInput(input);
+ if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(GetLowerThreshold());
+ binarizeFilter->SetUpperThreshold(GetUpperThreshold());
+ binarizeFilter ->SetInsideValue(this->GetForegroundValue());
+ binarizeFilter ->SetOutsideValue(this->GetBackgroundValue());
+
+ // Connected component labeling
+ typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
+ typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
+ connectFilter->SetInput(binarizeFilter->GetOutput());
+ connectFilter->SetBackgroundValue(this->GetBackgroundValue());
+ connectFilter->SetFullyConnected(false);
+
+ // Sort labels according to size
+ typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
+ typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
+ relabelFilter->InPlaceOn();
+ relabelFilter->SetInput(connectFilter->GetOutput());
+ relabelFilter->Update();
+ working_image = relabelFilter->GetOutput();
+
+ // End
+ StopCurrentStep<InternalImageType>(working_image);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // [Optional]
+ if (GetDecomposeAndReconstructDuringFirstStep()) {
+ StartNewStep("First Decompose & Reconstruct step");
+ typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> FilterType;
+ typename FilterType::Pointer f = FilterType::New();
+ f->SetInput(working_image);
+ // f->SetVerbose(m_Verbose);
+ f->SetRadius(GetRadius1());
+ f->SetMaximumNumberOfLabels(GetMaximumNumberOfLabels1());
+ f->SetBackgroundValue(this->GetBackgroundValue());
+ f->SetForegroundValue(this->GetForegroundValue());
+ f->SetFullyConnected(true);
+ f->SetNumberOfNewLabels(GetNumberOfNewLabels1());
+ f->Update();
+ working_image = f->GetOutput();
+ StopCurrentStep<InternalImageType>(working_image);
+ }
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Remove the air (largest area)");
+ typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> iBinarizeFilterType;
+ typename iBinarizeFilterType::Pointer binarizeFilter2 = iBinarizeFilterType::New();
+ binarizeFilter2->SetInput(working_image);
+ binarizeFilter2->SetLowerThreshold(this->GetForegroundValue());
+ binarizeFilter2->SetUpperThreshold(this->GetForegroundValue());
+ binarizeFilter2 ->SetInsideValue(this->GetBackgroundValue());
+ binarizeFilter2 ->SetOutsideValue(this->GetForegroundValue());
+ // binarizeFilter2 ->Update(); // NEEDED ?
+
+ typename ConnectFilterType::Pointer connectFilter2 = ConnectFilterType::New();
+ connectFilter2->SetInput(binarizeFilter2->GetOutput());
+ connectFilter2->SetBackgroundValue(this->GetBackgroundValue());
+ connectFilter2->SetFullyConnected(false);
+
+ typename RelabelFilterType::Pointer relabelFilter2 = RelabelFilterType::New();
+ relabelFilter2->SetInput(connectFilter2->GetOutput());
+ relabelFilter2->Update();
+ working_image = relabelFilter2->GetOutput();
+ StopCurrentStep<InternalImageType>(working_image);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // [Optional]
+ if (GetDecomposeAndReconstructDuringSecondStep()) {
+ StartNewStep("Second Decompose & Reconstruct step");
+ typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> FilterType;
+ typename FilterType::Pointer f = FilterType::New();
+ f->SetInput(working_image);
+ // f->SetVerbose(m_Verbose);
+ f->SetRadius(GetRadius2());
+ f->SetMaximumNumberOfLabels(GetMaximumNumberOfLabels2());
+ f->SetBackgroundValue(this->GetBackgroundValue());
+ f->SetForegroundValue(this->GetForegroundValue());
+ f->SetFullyConnected(true);
+ f->SetNumberOfNewLabels(GetNumberOfNewLabels2());
+ f->Update();
+ working_image = f->GetOutput();
+ StopCurrentStep<InternalImageType>(working_image);
+ }
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ StartNewStep("Keep patient's labels");
+ typename iBinarizeFilterType::Pointer binarizeFilter3 = iBinarizeFilterType::New();
+ binarizeFilter3->SetInput(working_image);
+ binarizeFilter3->SetLowerThreshold(GetFirstKeep());
+ binarizeFilter3->SetUpperThreshold(GetLastKeep());
+ binarizeFilter3 ->SetInsideValue(this->GetForegroundValue());
+ binarizeFilter3 ->SetOutsideValue(this->GetBackgroundValue());
+ binarizeFilter3->Update();
+ working_image = binarizeFilter3->GetOutput();
+ StopCurrentStep<InternalImageType>(working_image);
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // [Optional]
+ if (GetFinalOpenClose()) {
+ StartNewStep("Final OpenClose");
+ // Open
+ typedef itk::BinaryBallStructuringElement<InternalPixelType,Dim> KernelType;
+ KernelType structuringElement;
+ structuringElement.SetRadius(1);
+ structuringElement.CreateStructuringElement();
+ typedef itk::BinaryMorphologicalOpeningImageFilter<InternalImageType, InternalImageType , KernelType> OpenFilterType;
+ typename OpenFilterType::Pointer openFilter = OpenFilterType::New();
+ openFilter->SetInput(working_image);
+ openFilter->SetBackgroundValue(this->GetBackgroundValue());
+ openFilter->SetForegroundValue(this->GetForegroundValue());
+ openFilter->SetKernel(structuringElement);
+ // Close
+ typedef itk::BinaryMorphologicalClosingImageFilter<InternalImageType, InternalImageType , KernelType> CloseFilterType;
+ typename CloseFilterType::Pointer closeFilter = CloseFilterType::New();
+ closeFilter->SetInput(openFilter->GetOutput());
+ closeFilter->SetSafeBorder(true);
+ closeFilter->SetForegroundValue(this->GetForegroundValue());
+ // closeFilter->SetBackgroundValue(SetBackgroundValue());
+ closeFilter->SetKernel(structuringElement);
+ closeFilter->Update();
+ working_image = closeFilter->GetOutput();
+ StopCurrentStep<InternalImageType>(working_image);
+ }
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // Final Cast
+ typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
+ typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
+ caster->SetInput(working_image);
+ caster->Update();
+ output = caster->GetOutput();
+
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // [Optional]
+ if (GetAutoCrop()) {
+ StartNewStep("AutoCrop");
+ typedef clitk::AutoCropFilter<OutputImageType> CropFilterType;
+ typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+ cropFilter->SetInput(output);
+ cropFilter->SetBackgroundValue(GetBackgroundValue());
+ cropFilter->Update();
+ output = cropFilter->GetOutput();
+ StopCurrentStep<OutputImageType>(output);
+ }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TInputImageType, class TOutputImageType>
+void
+clitk::ExtractPatientFilter<TInputImageType, TOutputImageType>::
+GenerateData() {
+ //this->SetNthOutput(0, output); // -> no because redo filter otherwise
+ this->GraftOutput(output);
+}
+//--------------------------------------------------------------------
+
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
--- /dev/null
+#ifndef clitkExtractPatientGenericFilter_cxx
+#define clitkExtractPatientGenericFilter_cxx
+
+/* =================================================
+ * @file clitkExtractPatientGenericFilter.cxx
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+#include "clitkExtractPatientGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+ //-----------------------------------------------------------
+ // Constructor
+ //-----------------------------------------------------------
+ ExtractPatientGenericFilter::ExtractPatientGenericFilter()
+ {
+ m_Verbose=false;
+ m_InputFileName="";
+ }
+
+
+ //-----------------------------------------------------------
+ // Update
+ //-----------------------------------------------------------
+ void ExtractPatientGenericFilter::Update()
+ {
+ // Read the Dimension and PixelType
+ int Dimension;
+ std::string PixelType;
+ ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+
+ // Call UpdateWithDim
+ if(Dimension==2) UpdateWithDim<2>(PixelType);
+ else if(Dimension==3) UpdateWithDim<3>(PixelType);
+ // else if (Dimension==4)UpdateWithDim<4>(PixelType);
+ else
+ {
+ std::cout<<"Error, Only for 2 or 3 Dimensions!!!"<<std::endl ;
+ return;
+ }
+ }
+
+
+} //end clitk
+
+#endif //#define clitkExtractPatientGenericFilter_cxx
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+#ifndef CLITKEXTRACTPATIENTGENERICFILTER_H
+#define CLITKEXTRACTPATIENTGENERICFILTER_H
+
+// clitk
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkExtractPatientFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk
+{
+
+ template<class ArgsInfoType>
+ class ITK_EXPORT ExtractPatientGenericFilter:
+ public ImageToImageGenericFilter<ExtractPatientGenericFilter<ArgsInfoType> >
+ {
+ public:
+ //--------------------------------------------------------------------
+ ExtractPatientGenericFilter();
+
+ //--------------------------------------------------------------------
+ typedef ExtractPatientGenericFilter Self;
+ typedef ImageToImageGenericFilter<ExtractPatientGenericFilter<ArgsInfoType> > Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ //--------------------------------------------------------------------
+ itkNewMacro(Self);
+ itkTypeMacro( ExtractPatientGenericFilter, LightObject );
+
+ //--------------------------------------------------------------------
+ void SetArgsInfo(const ArgsInfoType & a);
+
+ //--------------------------------------------------------------------
+ // Main function called each time the filter is updated
+ template<class ImageType>
+ void UpdateWithInputImageType();
+
+ protected:
+ template<unsigned int Dim> void InitializeImageType();
+ ArgsInfoType mArgsInfo;
+
+ };// end class
+ //--------------------------------------------------------------------
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractPatientGenericFilter.txx"
+#endif
+
+#endif // #define CLITKEXTRACTPATIENTGENERICFILTER_H
--- /dev/null
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+#include "clitkImageCommon.h"
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::ExtractPatientGenericFilter<ArgsInfoType>::ExtractPatientGenericFilter():
+ ImageToImageGenericFilter<Self>("ExtractPatient")
+{
+ // Default values
+ cmdline_parser_clitkExtractPatient_init(&mArgsInfo);
+ InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::ExtractPatientGenericFilter<ArgsInfoType>::InitializeImageType()
+{
+ ADD_IMAGE_TYPE(Dim, short);
+ // ADD_IMAGE_TYPE(Dim, int);
+ // ADD_IMAGE_TYPE(Dim, float);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::ExtractPatientGenericFilter<ArgsInfoType>::SetArgsInfo(const ArgsInfoType & a)
+{
+ mArgsInfo=a;
+ SetIOVerbose(mArgsInfo.verbose_flag);
+ if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+ if (mArgsInfo.input_given) SetInputFilename(mArgsInfo.input_arg);
+ if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::ExtractPatientGenericFilter<ArgsInfoType>::UpdateWithInputImageType()
+{
+ // Output image type
+ typedef itk::Image<uchar, ImageType::ImageDimension> OutputImageType;
+
+ // Reading input
+ typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+
+ // Create filter
+ typedef clitk::ExtractPatientFilter<ImageType, OutputImageType> FilterType;
+ typename FilterType::Pointer filter = FilterType::New();
+
+ // Set global Options
+ filter->SetArgsInfo(mArgsInfo);
+ filter->SetInput(input);
+
+ // Go !
+ filter->Update();
+
+ // Check if error
+ if (filter->HasError()) {
+ SetLastError(filter->GetLastError());
+ // No output
+ return;
+ }
+
+ // Write/Save results
+ typename OutputImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<OutputImageType>(output);
+}
+//--------------------------------------------------------------------
+
+
--- /dev/null
+/*------------------------------------------------------------------------
+
+ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+ l'Image). All rights reserved. See Doc/License.txt or
+ http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+ ------------------------------------------------------------------------*/
+
+/* =================================================
+ * @file clitkFillMask.cxx
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+
+// clitk
+#include "clitkFillMask_ggo.h"
+#include "clitkIO.h"
+#include "clitkFillMaskGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+ // Init command line
+ GGO(clitkFillMask,args_info);
+ CLITK_INIT;
+
+ // Filter
+ clitk::FillMaskGenericFilter::Pointer genericFilter=clitk::FillMaskGenericFilter::New();
+
+ genericFilter->SetArgsInfo(args_info);
+ genericFilter->Update();
+
+ return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkFillMask.ggo
+package "clitkFillMask"
+version "1.0"
+purpose "Fill in holes (bg=0) in an object (fg=1) of a binary image, by running over the slices and retaining only one connected component bg."
+
+option "config" - "Config file" string no
+option "verbose" v "Verbose" flag off
+
+option "input" i "Input image filename" string yes
+option "output" o "Output image filename" string yes
+option "dir" d "Directions (axes) to perform filling (defaults to 2,1,0)" int multiple no
+
+
--- /dev/null
+#ifndef clitkFillMaskGenericFilter_cxx
+#define clitkFillMaskGenericFilter_cxx
+
+/* =================================================
+ * @file clitkFillMaskGenericFilter.cxx
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+#include "clitkFillMaskGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+ //-----------------------------------------------------------
+ // Constructor
+ //-----------------------------------------------------------
+ FillMaskGenericFilter::FillMaskGenericFilter()
+ {
+ m_Verbose=false;
+ m_InputFileName="";
+ }
+
+
+ //-----------------------------------------------------------
+ // Update
+ //-----------------------------------------------------------
+ void FillMaskGenericFilter::Update()
+ {
+ // Read the Dimension and PixelType
+ int Dimension;
+ std::string PixelType;
+ ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+
+ // Call UpdateWithPixelType
+ if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+ if (Dimension != 3)
+ {
+ std::cerr<<"Error: Only for 3D!!"<<std::endl;
+ return;
+ }
+
+ if(PixelType == "short"){
+ if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+ UpdateWithPixelType<signed short>();
+ }
+
+ // else if(PixelType == "unsigned_short"){
+ // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+ // UpdateWithPixelType<unsigned short>();
+ // }
+
+ else if (PixelType == "unsigned_char"){
+ if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+ UpdateWithPixelType<unsigned char>();
+ }
+
+ // else if (PixelType == "char"){
+ // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+ // UpdateWithPixelType<signed char>();
+ // }
+
+ else {
+ if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+ UpdateWithPixelType<float>();
+ }
+ }
+
+
+} //end clitk
+
+#endif //#define clitkFillMaskGenericFilter_cxx
--- /dev/null
+#ifndef clitkFillMaskGenericFilter_h
+#define clitkFillMaskGenericFilter_h
+
+/* =================================================
+ * @file clitkFillMaskGenericFilter.h
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+
+// clitk include
+#include "clitkFillMask_ggo.h"
+#include "clitkImageCommon.h"
+#include "clitkExtractImageFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkJoinSeriesImageFilter.h"
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkConnectedComponentImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
+#include "itkThresholdImageFilter.h"
+#include "itkPermuteAxesImageFilter.h"
+#include "itkExtractImageFilter.h"
+#include "itkCastImageFilter.h"
+
+namespace clitk
+{
+
+
+ class ITK_EXPORT FillMaskGenericFilter : public itk::LightObject
+ {
+ public:
+ //----------------------------------------
+ // ITK
+ //----------------------------------------
+ typedef FillMaskGenericFilter Self;
+ typedef itk::LightObject Superclass;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
+
+ // Method for creation through the object factory
+ itkNewMacro(Self);
+
+ // Run-time type information (and related methods)
+ itkTypeMacro( FillMaskGenericFilter, LightObject );
+
+
+ //----------------------------------------
+ // Typedefs
+ //----------------------------------------
+
+
+ //----------------------------------------
+ // Set & Get
+ //----------------------------------------
+ void SetArgsInfo(const args_info_clitkFillMask & a)
+ {
+ m_ArgsInfo=a;
+ m_Verbose=m_ArgsInfo.verbose_flag;
+ m_InputFileName=m_ArgsInfo.input_arg;
+ }
+
+
+ //----------------------------------------
+ // Update
+ //----------------------------------------
+ void Update();
+
+ protected:
+
+ //----------------------------------------
+ // Constructor & Destructor
+ //----------------------------------------
+ FillMaskGenericFilter();
+ ~FillMaskGenericFilter() {};
+
+
+ //----------------------------------------
+ // Templated members
+ //----------------------------------------
+ template <class PixelType> void UpdateWithPixelType();
+
+
+ //----------------------------------------
+ // Data members
+ //----------------------------------------
+ args_info_clitkFillMask m_ArgsInfo;
+ bool m_Verbose;
+ std::string m_InputFileName;
+
+ };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkFillMaskGenericFilter.txx"
+#endif
+
+#endif // #define clitkFillMaskGenericFilter_h
--- /dev/null
+#ifndef clitkFillMaskGenericFilter_txx
+#define clitkFillMaskGenericFilter_txx
+
+/* =================================================
+ * @file clitkFillMaskGenericFilter.txx
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+
+namespace clitk
+{
+
+ //-------------------------------------------------------------------
+ // Update with the pixeltype
+ //-------------------------------------------------------------------
+ template <class PixelType>
+ void
+ FillMaskGenericFilter::UpdateWithPixelType()
+ {
+ // Dim & Pix
+ const unsigned int Dimension=3;
+ typedef int InternalPixelType;
+
+ // ImageTypes
+ typedef itk::Image<PixelType, Dimension> InputImageType;
+ typedef itk::Image<InternalPixelType, Dimension> InternalImageType;
+ typedef itk::Image<PixelType, Dimension> OutputImageType;
+
+ // Read the input
+ typedef itk::ImageFileReader<InputImageType> InputReaderType;
+ typename InputReaderType::Pointer reader = InputReaderType::New();
+ reader->SetFileName( m_InputFileName);
+ reader->Update();
+ typename InputImageType::Pointer input= reader->GetOutput();
+
+ // Read the directions over which to fill holes
+ std::vector<unsigned int> direction;
+ if (m_ArgsInfo.dir_given)
+ for ( unsigned int i=0;i<m_ArgsInfo.dir_given;i++)
+ direction.push_back(m_ArgsInfo.dir_arg[i]);
+ else
+ for ( unsigned int i=0;i<Dimension;i++)
+ direction.push_back(Dimension-i-1);
+
+ //----------------------------------------
+ // Cast to internal type
+ //----------------------------------------
+ typedef itk::CastImageFilter<InputImageType,InternalImageType> InputCastImageFilterType;
+ typename InputCastImageFilterType::Pointer inputCaster= InputCastImageFilterType::New();
+ inputCaster->SetInput(input);
+ inputCaster->Update();
+
+ //----------------------------------------
+ // Loop over directions
+ //----------------------------------------
+ typename InternalImageType::Pointer output=inputCaster->GetOutput();
+ for (unsigned int i=0; i<direction.size();i++)
+ {
+
+ //----------------------------------------
+ // Fill the holes of a mask in 2D
+ //----------------------------------------
+ if(m_Verbose) std::cout<<"Fill holes in the mask slice by slice in direction "<<direction[i]<<"..."<<std::endl;
+
+ // We define the region to be extracted.
+ typedef itk::Image<InternalPixelType, Dimension-1> ImageSliceType;
+ typedef itk::Image<InternalPixelType, Dimension-1> MaskSliceType;
+ typename InternalImageType::RegionType region3D= input->GetLargestPossibleRegion();
+ typename InternalImageType::RegionType::SizeType size3D= region3D.GetSize();
+ typename InternalImageType::RegionType::SizeType size2D=size3D;
+ size2D[direction[i]]=0;
+ typename InternalImageType::IndexType start2D;
+ start2D.Fill(0);
+ typename InternalImageType::RegionType desiredRegion;
+ desiredRegion.SetSize( size2D );
+ desiredRegion.SetIndex( start2D );
+
+ // Extract and Join
+ typedef itk::ExtractImageFilter<InternalImageType, ImageSliceType> ExtractImageFilterType;
+ typedef itk::JoinSeriesImageFilter<ImageSliceType, InternalImageType> JoinSeriesFilterType;
+ typename JoinSeriesFilterType::Pointer joinFilter=JoinSeriesFilterType::New();
+ joinFilter->SetSpacing(input->GetSpacing()[direction[i]]);
+
+ //----------------------------------------
+ // Run over the sliceIndexs
+ // ----------------------------------------
+ for(unsigned int sliceIndex=0; sliceIndex <size3D[direction[i]]; sliceIndex++)
+ {
+ //----------------------------------------
+ // Extract mask sliceIndex
+ //----------------------------------------
+ typename ExtractImageFilterType::Pointer extractFilter=ExtractImageFilterType::New();
+ extractFilter->SetInput(output);
+ start2D[direction[i]]=sliceIndex;
+ desiredRegion.SetIndex( start2D );
+ extractFilter->SetExtractionRegion( desiredRegion );
+ extractFilter->Update( );
+ typename ImageSliceType::Pointer slice= extractFilter->GetOutput();
+
+ // Binarize the image (Before: OBJECT!=0, rest=0, After: object=1, rest=0 )
+ typedef itk::BinaryThresholdImageFilter<ImageSliceType,ImageSliceType> BinarizeFilterType;
+ typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New();
+ binarizeFilter->SetInput(slice);
+ binarizeFilter->SetUpperThreshold(0);
+ binarizeFilter->SetOutsideValue(0);
+ binarizeFilter->SetInsideValue(1);
+ // writeImage<ImageSliceType>(binarizeFilter->GetOutput(),"/home/jef/tmp/input.mhd");
+
+ // Perform connected labelling on the slice (body+air=0 )
+ typedef itk::ConnectedComponentImageFilter<ImageSliceType, ImageSliceType> ConnectFilterType;
+ typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
+ connectFilter->SetInput(binarizeFilter->GetOutput());
+ connectFilter->SetBackgroundValue(0);
+ connectFilter->SetFullyConnected(false);
+ //connectFilter->Update();
+ //writeImage<ImageSliceType>(connectFilter->GetOutput(),"/home/jef/tmp/connect.mhd");
+
+ // Sort the labels
+ typedef itk::RelabelComponentImageFilter<ImageSliceType, ImageSliceType> RelabelFilterType;
+ typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
+ relabelFilter->SetInput(connectFilter->GetOutput());
+ //relabelFilter->Update();
+ //writeImage<ImageSliceType>(relabelFilter->GetOutput(),"/home/jef/tmp/label.mhd");
+
+ // Keep the first
+ typedef itk::ThresholdImageFilter<ImageSliceType> ThresholdFilterType;
+ typename ThresholdFilterType::Pointer thresholdFilter=ThresholdFilterType::New();
+ thresholdFilter->SetInput(relabelFilter->GetOutput());
+ thresholdFilter->SetUpper(1);
+ thresholdFilter->SetOutsideValue(0);
+ // thresholdFilter->Update();
+ // writeImage<ImageSliceType>(thresholdFilter->GetOutput(),"/home/jef/tmp/bin.mhd");
+
+ // Invert the labels (lung 1, rest 0)
+ typename BinarizeFilterType::Pointer switchFilter=BinarizeFilterType::New();
+ switchFilter->SetInput(thresholdFilter->GetOutput());
+ switchFilter->SetUpperThreshold(0);
+ switchFilter->SetOutsideValue(0);
+ switchFilter->SetInsideValue(1);
+ switchFilter->Update();
+ //writeImage<ImageSliceType>(switchFilter->GetOutput(),"/home/jef/tmp/inv_bin.mhd");
+
+ //Join
+ joinFilter->SetInput( sliceIndex, switchFilter->GetOutput());
+ }
+
+ // Join to a 3D image
+ if (m_Verbose) std::cout<<"Joining the slices..."<<std::endl;
+ joinFilter->Update();
+
+ // Permute the axes to reset to orientation
+ typedef itk::PermuteAxesImageFilter<InternalImageType> PermuteFilterType;
+ typename PermuteFilterType::Pointer permuteFilter=PermuteFilterType::New();
+ permuteFilter->SetInput(joinFilter->GetOutput());
+ typename PermuteFilterType::PermuteOrderArrayType order;
+ order[direction[i]]=2;
+ if( direction[i]==2)
+ {
+ order[0]=0;
+ order[1]=1;
+ }
+ else if ( direction[i]==1)
+ {
+ order[0]=0;
+ order[2]=1;
+ }
+ else if (direction[i]==0)
+ {
+ order[1]=0;
+ order[2]=1;
+ }
+ permuteFilter->SetOrder(order);
+ permuteFilter->Update();
+ output =permuteFilter->GetOutput();
+
+ // Set the image direction to the input one
+ output->SetDirection(input->GetDirection());
+ output->SetOrigin(input->GetOrigin());
+ }
+
+
+ // Cast
+ typedef itk::CastImageFilter<InternalImageType,OutputImageType> OutputCastImageFilterType;
+ typename OutputCastImageFilterType::Pointer outputCaster =OutputCastImageFilterType::New();
+ outputCaster->SetInput(output);
+
+ // Output
+ typedef itk::ImageFileWriter<OutputImageType> WriterType;
+ typename WriterType::Pointer writer = WriterType::New();
+ writer->SetFileName(m_ArgsInfo.output_arg);
+ writer->SetInput(outputCaster->GetOutput());
+ writer->Update();
+ }
+
+}//end clitk
+
+#endif //#define clitkFillMaskGenericFilter_txx
--- /dev/null
+
+/*=========================================================================
+ Program: vv http://www.creatis.insa-lyon.fr/rio/vv
+
+ Authors belong to:
+ - University of LYON http://www.universite-lyon.fr/
+ - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the copyright notices for more information.
+
+ It is distributed under dual licence
+
+ - BSD See included LICENSE.txt file
+ - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ ======================================================================-====*/
+
+// clitk
+#include "clitkTestFilter_ggo.h"
+#include "clitkImageCommon.h"
+#include "clitkBooleanOperatorLabelImageFilter.h"
+#include "clitkAutoCropFilter.h"
+//#include "clitkRelativePositionConstraintLabelImageFilter.h"
+#include "clitkResampleImageWithOptionsFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+
+#include "clitkExtractLungFilter.h"
+#include "clitkExtractPatientFilter.h"
+#include "clitkExtractMediastinumFilter.h"
+
+// ITK ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+ // Init command line
+ GGO(clitkTestFilter, args_info);
+
+ // Image types
+ //typedef unsigned char PixelType;
+ typedef short PixelType;
+ static const int Dim=3;
+ typedef itk::Image<PixelType, Dim> InputImageType;
+
+ // Read inputs
+ InputImageType::Pointer input1;
+ InputImageType::Pointer input2;
+ InputImageType::Pointer input3;
+ input1 = clitk::readImage<InputImageType>(args_info.input1_arg, true);
+ if (args_info.input2_given) input2 = clitk::readImage<InputImageType>(args_info.input2_arg, true);
+ if (args_info.input3_given) input3 = clitk::readImage<InputImageType>(args_info.input3_arg, true);
+
+ // Declare output
+ InputImageType::Pointer output;
+
+ //--------------------------------------------------------------------
+ // Filter test BooleanOperatorLabelImageFilter
+ if (0) {
+ typedef clitk::BooleanOperatorLabelImageFilter<InputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput1(input1);
+ filter->SetInput2(input2);
+ output = clitk::NewImageLike<InputImageType>(input1);
+ filter->GraftOutput(output); /// TO VERIFY !!!
+ filter->Update();
+ filter->SetInput2(input3);
+ filter->Update();
+ output = filter->GetOutput();
+ clitk::writeImage<InputImageType>(output, args_info.output_arg);
+ }
+
+ //--------------------------------------------------------------------
+ // Filter test AutoCropLabelImageFilter
+ if (1) {
+ typedef clitk::AutoCropFilter<InputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput(input1);
+ filter->Update();
+ output = filter->GetOutput();
+ clitk::writeImage<InputImageType>(output, args_info.output_arg);
+ }
+
+ //--------------------------------------------------------------------
+ // Filter test RelativePositionPropImageFilter
+ if (0) {
+ typedef itk::Image<float, Dim> OutputImageType;
+ OutputImageType::Pointer outputf;
+ typedef itk::RelativePositionPropImageFilter<InputImageType, OutputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput(input1);
+
+ filter->SetAlpha1(clitk::deg2rad(args_info.angle1_arg)); // xy plane
+ filter->SetAlpha2(clitk::deg2rad(args_info.angle2_arg));
+ filter->SetK1(M_PI/2.0); // Opening parameter, default = pi/2
+ filter->SetFast(true);
+ filter->SetRadius(2);
+ filter->SetVerboseProgress(true);
+
+ /* A1 A2
+ Left 0 0
+ Right 180 0
+ Ant 90 0
+ Post -90 0
+ Inf 0 90
+ Sup 0 -90
+ */
+
+ filter->Update();
+ clitk::writeImage<OutputImageType>(filter->GetOutput(), args_info.output_arg);
+ }
+
+ //--------------------------------------------------------------------
+ // Filter test
+ if (0) {
+ typedef itk::Image<short, Dim> OutputImageType;
+ typedef clitk::ResampleImageWithOptionsFilter<InputImageType, OutputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput(input1);
+ filter->SetOutputIsoSpacing(1);
+ //filter->SetNumberOfThreads(4); // auto
+ filter->SetGaussianFilteringEnabled(false);
+ filter->Update();
+ clitk::writeImage<OutputImageType>(filter->GetOutput(), args_info.output_arg);
+ }
+
+ //--------------------------------------------------------------------
+ // Filter AddRelativePositionConstraintToLabelImageFilter test
+ if (0) {
+ /*
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<InputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput(input1);
+ filter->SetInputObject(input2);
+ filter->SetOrientationType(FilterType::LeftTo);
+ filter->SetIntermediateSpacing(5);
+ filter->SetFuzzyThreshold(0.5);
+ filter->VerboseStepOn();
+ filter->WriteStepOff();
+ filter->Update();
+
+ filter->SetInput(filter->GetOutput());
+ filter->SetInputObject(input2);
+ filter->SetOrientationType(FilterType::RightTo);
+ filter->SetIntermediateSpacing(5);
+ filter->SetFuzzyThreshold(0.5);
+ filter->Update();
+
+ clitk::writeImage<InputImageType>(filter->GetOutput(), args_info.output_arg);
+ */
+ }
+
+ //--------------------------------------------------------------------
+ // Filter test ExtractPatientFilter
+ if (0) {
+ typedef itk::Image<char, Dim> OutputImageType;
+ typedef clitk::ExtractPatientFilter<InputImageType, OutputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInput(input1);
+ filter->VerboseStepOn();
+ filter->WriteStepOn();
+ // options (default)
+ filter->SetUpperThreshold(-300);
+ filter->FinalOpenCloseOff(); // default=on (not rezally needed ?)
+ filter->Update();
+ OutputImageType::Pointer output = filter->GetOutput();
+ clitk::writeImage<OutputImageType>(output, args_info.output_arg);
+ }
+
+ //--------------------------------------------------------------------
+ // Filter test ExtractLungsFilter
+ if (0) {
+ typedef itk::Image<PixelType, Dim> OutputImageType; // to change into char
+ typedef clitk::ExtractLungFilter<InputImageType, OutputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ // DD(filter->GetNumberOfSteps());
+ filter->SetInput(input1); // CT
+ filter->SetInputPatientMask(input2, 0); // Patient mask and BG value
+ filter->VerboseStepOn();
+ filter->WriteStepOn();
+ // options (default)
+ //filter->SetBackgroundValue(0);
+ filter->SetUpperThreshold(-300);
+ // filter->SetMinimumComponentSize(100);
+
+ filter->Update();
+ OutputImageType::Pointer output = filter->GetOutput();
+ clitk::writeImage<OutputImageType>(output, args_info.output_arg);
+ }
+
+ //--------------------------------------------------------------------
+ // Filter test ExtractMediastinumFilter
+ if (0) {
+ typedef clitk::ExtractMediastinumFilter<InputImageType> FilterType;
+ FilterType::Pointer filter = FilterType::New();
+ filter->SetInputPatientLabelImage(input1);
+ filter->SetInputLungLabelImage(input2, 0, 1, 2); // BG, FG Left Lung, FG Right Lung
+ filter->SetInputBonesLabelImage(input3);
+ filter->VerboseStepOn();
+ filter->WriteStepOn();
+ filter->Update();
+ output = filter->GetOutput();
+ clitk::writeImage<InputImageType>(output, args_info.output_arg);
+ }
+
+ // This is the end my friend
+ return EXIT_SUCCESS;
+}// end main
+//--------------------------------------------------------------------
--- /dev/null
+#File clitkTestFilter.ggo
+package "clitkTestFilter"
+version "1.0"
+purpose "Test a filter"
+
+option "config" - "Config file" string no
+option "verbose" v "Verbose" flag off
+
+option "input1" i "Input 1 image filename" string yes
+option "input2" j "Input 2 image filename" string no
+option "input3" k "Input 3 image filename" string no
+option "output" o "Output image filename" string yes
+
+option "angle1" a "First angle (degree)" float default = "0" no
+option "angle2" b "Second angle (degree)" float default = "0" no
+