// std
#include <iterator>
#include <sstream>
-#include <cctype>\r
-#include <functional>\r
+#include <cctype>
+#include <functional>
//--------------------------------------------------------------------
clitk::AnatomicalFeatureDatabase::AnatomicalFeatureDatabase()
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+double clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, int dim)
+{
+ PointType3D p;
+ GetPoint3D(tag, p);
+ return p[dim];
+}
+//--------------------------------------------------------------------
+
//--------------------------------------------------------------------
void clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, PointType3D & p)
{
typedef itk::Point<double,3> PointType3D;
void SetPoint3D(TagType tag, PointType3D & p);
void GetPoint3D(TagType tag, PointType3D & p);
+ double GetPoint3D(std::string tag, int dim);
// Set Get image
void SetImageFilename(TagType tag, std::string f);
_l1 = l1;
_l2 = l2;
}
+
IndexType index;
PointType point;
+ double weight;
PixelType l;
PixelType l1;
PixelType l2;
typedef typename InternalImageType::Pointer InternalImagePointer;
typedef typename InternalImageType::IndexType InternalIndexType;
typedef LabelizeParameters<InternalPixelType> LabelParamType;
-
+
+ // Data Structures for trees
+ struct FullTreeNodeType {
+ ImageIndexType index;
+ ImagePointType point;
+ double weight;
+ };
+ struct StructuralTreeNodeType {
+ ImageIndexType index;
+ ImagePointType point;
+ double weight;
+ };
+ typedef tree<FullTreeNodeType> FullTreeType;
+ typedef tree<StructuralTreeNodeType> StructuralTreeType;
+ FullTreeType mFullSkeletonTree;
+ StructuralTreeType mStructuralSkeletonTree;
+
/** Connect inputs */
void SetInput(const ImageType * image);
virtual void GenerateData();
TreeType m_SkeletonTree;
+ void TrackFromThisIndex2(ImageIndexType index, ImagePointer skeleton,
+ ImagePixelType label,
+ typename FullTreeType::iterator currentNode,
+ typename StructuralTreeType::iterator currentSNode);
void TrackFromThisIndex(std::vector<BifurcationType> & listOfBifurcations,
ImagePointer skeleton,
ImageIndexType index,
clitk::ExtractAirwaysTreeInfoFilter<ImageType>::
GenerateData()
{
- StartNewStep("Thinning filter (skeleton)");
+
+ // Crop just abov lungs ?
+
+ // read skeleton if already exist
+ bool foundSkeleton = true;
+ try {
+ skeleton = GetAFDB()->template GetImage <ImageType>("skeleton");
+ }
+ catch (clitk::ExceptionObject e) {
+ DD("did not found skeleton");
+ foundSkeleton = false;
+ }
+
// Extract skeleton
- typedef itk::BinaryThinningImageFilter3D<ImageType, ImageType> ThinningFilterType;
- typename ThinningFilterType::Pointer thinningFilter = ThinningFilterType::New();
- thinningFilter->SetInput(input); // input = trachea
- thinningFilter->Update();
- skeleton = thinningFilter->GetOutput();
- StopCurrentStep<ImageType>(skeleton);
+ if (!foundSkeleton) {
+ StartNewStep("Thinning filter (skeleton)");
+ typedef itk::BinaryThinningImageFilter3D<ImageType, ImageType> ThinningFilterType;
+ typename ThinningFilterType::Pointer thinningFilter = ThinningFilterType::New();
+ thinningFilter->SetInput(input); // input = trachea
+ thinningFilter->Update();
+ skeleton = thinningFilter->GetOutput();
+ StopCurrentStep<ImageType>(skeleton);
+ writeImage<ImageType>(skeleton, "skeleton.mhd");
+ }
// Find first point for tracking
StartNewStep("Find first point for tracking");
typename ImageType::IndexType index = it.GetIndex();
DD(index);
- // Initialize neighborhooditerator
- typedef itk::NeighborhoodIterator<ImageType> NeighborhoodIteratorType;
- typename NeighborhoodIteratorType::SizeType radius;
- radius.Fill(1);
- NeighborhoodIteratorType nit(radius, skeleton, skeleton->GetLargestPossibleRegion());
+ if (0) {
+ // Initialize neighborhooditerator
+ typedef itk::NeighborhoodIterator<ImageType> NeighborhoodIteratorType;
+ typename NeighborhoodIteratorType::SizeType radius;
+ radius.Fill(1);
+ NeighborhoodIteratorType nit(radius, skeleton, skeleton->GetLargestPossibleRegion());
+ }
- // Find first label number (must be different from BG and FG)
+ // Find a label number different from BG and FG
typename ImageType::PixelType label = GetForegroundValue()+1;
while ((label == GetBackgroundValue()) || (label == GetForegroundValue())) { label++; }
- DD(label);
+ DD((int)label);
/*
Tracking ?
-> follow at Left
*/
-
- // Track from the first point
+ // NEW Track from the first point
StartNewStep("Start tracking");
- std::vector<BifurcationType> listOfBifurcations;
- m_SkeletonTree.set_head(index);
- TrackFromThisIndex(listOfBifurcations, skeleton, index, label, m_SkeletonTree.begin());
- DD("end track");
-
- // Convert index into physical point coordinates
- for(unsigned int i=0; i<listOfBifurcations.size(); i++) {
- skeleton->TransformIndexToPhysicalPoint(listOfBifurcations[i].index,
- listOfBifurcations[i].point);
+ FullTreeNodeType n;
+ n.index = index;
+ skeleton->TransformIndexToPhysicalPoint(n.index, n.point); // à mettre dans TrackFromThisIndex2
+ mFullSkeletonTree.set_head(n);
+ StructuralTreeNodeType sn;
+ sn.index = index;
+ skeleton->TransformIndexToPhysicalPoint(sn.index, sn.point);
+ mStructuralSkeletonTree.set_head(sn);
+ TrackFromThisIndex2(index, skeleton, label, mFullSkeletonTree.begin(), mStructuralSkeletonTree.begin());
+ StopCurrentStep();
+
+ // Reput FG instead of label in the skeleton image
+ skeleton = clitk::SetBackground<ImageType, ImageType>(skeleton, skeleton, label, GetForegroundValue());
+
+ // Debug
+ typename StructuralTreeType::iterator sit = mStructuralSkeletonTree.begin();
+ while (sit != mStructuralSkeletonTree.end()) {
+ DD(sit->point);
+ ++sit;
+ }
+
+ // compute weight : n longueurs à chaque bifurfaction.
+ // parcours de FullTreeNodeType, à partir de leaf, remonter de proche en proche la distance eucl.
+ // par post order
+
+ // Init
+ typename FullTreeType::iterator fit = mFullSkeletonTree.begin();
+ while (fit != mFullSkeletonTree.end()) {
+ fit->weight = 0.0;
+ ++fit;
+ }
+
+ DD("compute weight");
+ typename FullTreeType::post_order_iterator pit = mFullSkeletonTree.begin_post();
+ while (pit != mFullSkeletonTree.end_post()) {
+ //DD(pit->point);
+ /*
+ if (pit != mFullSkeletonTree.begin()) {
+ typename FullTreeType::iterator parent = mFullSkeletonTree.parent(pit);
+ double d = pit->point.EuclideanDistanceTo(parent->point);
+ // DD(parent->weight);
+ //DD(d);
+ parent->weight += d;
+ if (pit.number_of_children() > 1) {
+ DD(pit.number_of_children());
+ DD(pit->point);
+ DD(pit->weight);
+ DD(parent->weight);
+ DD(mFullSkeletonTree.child(pit, 0)->weight);
+ DD(mFullSkeletonTree.child(pit, 1)->weight);
+ }
+ }
+ */
+ double previous = pit->weight;
+ for(uint i=0; i<pit.number_of_children(); i++) {
+ double d = pit->point.EuclideanDistanceTo(mFullSkeletonTree.child(pit, i)->point);
+ // pit->weight = pit->weight + mFullSkeletonTree.child(pit, i)->weight + d;
+ if (i==0)
+ pit->weight = pit->weight + mFullSkeletonTree.child(pit, i)->weight + d;
+ if (i>0) {
+ DD(pit.number_of_children());
+ DD(pit->point);
+ DD(pit->weight);
+ DD(mFullSkeletonTree.child(pit, 0)->weight);
+ DD(mFullSkeletonTree.child(pit, 1)->weight);
+ pit->weight = std::max(pit->weight, previous+mFullSkeletonTree.child(pit, i)->weight + d);
+ }
+ }
+ ++pit;
+ }
+
+ DD("end");
+ fit = mFullSkeletonTree.begin();
+ while (fit != mFullSkeletonTree.end()) {
+ std::cout << "p = " << fit->point
+ << " " << fit->weight
+ << " child= " << fit.number_of_children()
+ << " -> ";
+ for(uint i=0; i<fit.number_of_children(); i++) {
+ std::cout << " " << mFullSkeletonTree.child(fit, i)->weight;
+ }
+ std::cout << std::endl;
+ ++fit;
+ }
+
+ /* Selection criteria ?
+ - at least 2 child
+ - from top to bottom
+ - equilibr ?
+ */
+ DD("=========================================");
+ fit = mFullSkeletonTree.begin();
+ while (fit != mFullSkeletonTree.end()) {
+ if (fit.number_of_children() > 1) {
+ std::cout << "ppp = " << fit->point
+ << " " << fit->weight << std::endl;
+ for(uint i=1; i<fit.number_of_children(); i++) {
+ double w1 = mFullSkeletonTree.child(fit, i-1)->weight;
+ double w2 = mFullSkeletonTree.child(fit, i)->weight;
+ // if (w1 <= 0.1) break;
+ // if (w2 <= 0.1) break;
+ DD(w1);DD(w2);
+ if (w1>w2) {
+ double sw=w1;
+ w1=w2; w2=sw;
+ }
+ DD(w1/w2);
+ if (w1/w2 > 0.7) {
+ DD("KEEP IT");
+ }
+ }
+ }
+ ++fit;
}
+
+ if (0) {
+ // Track from the first point
+ StartNewStep("Start tracking OLD");
+ std::vector<BifurcationType> listOfBifurcations;
+ m_SkeletonTree.set_head(index);
+ TrackFromThisIndex(listOfBifurcations, skeleton, index, label, m_SkeletonTree.begin());
+ DD("end track");
+
+ // Convert index into physical point coordinates
+ for(unsigned int i=0; i<listOfBifurcations.size(); i++) {
+ skeleton->TransformIndexToPhysicalPoint(listOfBifurcations[i].index,
+ listOfBifurcations[i].point);
+ }
+
// Search for the first slice that separate the bronchus
// (carina). Labelize slice by slice, stop when the two points of
// the skeleton ar not in the same connected component
DD("REDO !!!!!!!!!!!!");
/**
=> chercher la bif qui a les plus important sous-arbres
+ - iterate sur m_SkeletonTree depth first, remonter au parent, add value = distance
+
+ NONNNNN m_SkeletonTree n'est pas la structure mais l'ensemble avec ts le skeleton
+
+ TreeIterator itt = m_SkeletonTree.begin();
+ while (itt != m_SkeletonTree.end()) {
+ itt->weight = 0.0;
+ ++itt;
+ }
+
+ typename tree<NodeType>::post_order_iterator pit = m_SkeletonTree.begin_post();
+ while (pit != m_SkeletonTree.end_post()) {
+ typename tree<NodeType>::iterator parent = m_SkeletonTree.parent(pit);
+ double d = pit->point.EuclideanDistanceTo(parent);
+ DD(parent.weight);
+ DD(d);
+ parent.weight += d;
+ ++it;
+ }
+
+ itt = m_SkeletonTree.begin();
+ while (itt != m_SkeletonTree.end()) {
+ DD(itt->weight);
+ ++itt;
+ }
**/
+
+ // search for carina
bool stop = false;
int slice_index = listOfBifurcations[0].index[2]; // first slice from carina in skeleton
int i=0;
if (GetVerboseStep()) {
std::cout << "\t Found carina at " << carina_position << " mm" << std::endl;
}
- GetAFDB()->SetPoint3D("Carina", carina_position);
+ GetAFDB()->SetPoint3D("carina", carina_position);
// Write bifurcation (debug)
for(uint i=0; i<listOfBifurcations.size(); i++) {
GetAFDB()->SetPoint3D("Bif"+toString(i), listOfBifurcations[i].point);
}
+ }
// Set the output (skeleton);
this->GraftOutput(skeleton); // not SetNthOutput
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+/**
+ Start from the pixel "index" in the image "skeleton" and track the
+ path from neighbor pixels. Put the tracked path in the tree at the
+ currentNode position. Label is used to mark the FG pixel as already
+ visited. Progress recursively when several neighbors are found.
+ **/
+template <class ImageType>
+void
+clitk::ExtractAirwaysTreeInfoFilter<ImageType>::
+TrackFromThisIndex2(ImageIndexType index, ImagePointer skeleton,
+ ImagePixelType label,
+ typename FullTreeType::iterator currentNode,
+ typename StructuralTreeType::iterator currentSNode)
+{
+ // Create NeighborhoodIterator
+ typedef itk::NeighborhoodIterator<ImageType> NeighborhoodIteratorType;
+ typename NeighborhoodIteratorType::SizeType radius;
+ radius.Fill(1);
+ NeighborhoodIteratorType nit(radius, skeleton, skeleton->GetLargestPossibleRegion());
+
+ // Track
+ std::vector<typename NeighborhoodIteratorType::IndexType> listOfTrackedPoint;
+ bool stop = false;
+ while (!stop) {
+ nit.SetLocation(index);
+ nit.SetCenterPixel(label);
+ listOfTrackedPoint.clear();
+ for(unsigned int i=0; i<nit.Size(); i++) {
+ if (i != nit.GetCenterNeighborhoodIndex ()) { // Do not observe the current point
+ if (nit.GetPixel(i) == GetForegroundValue()) {
+ // if pixel value is FG, we keep this point
+ listOfTrackedPoint.push_back(nit.GetIndex(i));
+ }
+ }
+ }
+ // If only neighbor is found, we keep the point and continue
+ if (listOfTrackedPoint.size() == 1) {
+ FullTreeNodeType n;
+ index = n.index = listOfTrackedPoint[0];
+ skeleton->TransformIndexToPhysicalPoint(n.index, n.point);
+ currentNode = mFullSkeletonTree.append_child(currentNode, n);
+ skeleton->SetPixel(n.index, label); // change label in skeleton image
+ }
+ else {
+ if (listOfTrackedPoint.size() >= 2) {
+ for(uint i=0; i<listOfTrackedPoint.size(); i++) {
+ FullTreeNodeType n;
+ n.index = listOfTrackedPoint[i];
+ skeleton->TransformIndexToPhysicalPoint(n.index, n.point);
+ typename FullTreeType::iterator node = mFullSkeletonTree.append_child(currentNode, n);
+ StructuralTreeNodeType sn;
+ sn.index = listOfTrackedPoint[i];
+ skeleton->TransformIndexToPhysicalPoint(sn.index, sn.point);
+ typename StructuralTreeType::iterator snode = mStructuralSkeletonTree.append_child(currentSNode, sn);
+ TrackFromThisIndex2(listOfTrackedPoint[i], skeleton, label, node, snode);
+ }
+ }
+ stop = true; // this it the end of the tracking
+ } // end else
+ } // end while stop
+}
+//--------------------------------------------------------------------
+
//--------------------------------------------------------------------
template <class ImageType>
void
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"
+section "Fill holes"
+option "doNotFillHoles" - "Do not fill holes if set" flag on
+option "dir" d "Directions (axes) to perform filling (defaults to 2,1,0)" int multiple no
+
option "noAutoCrop" - "If set : do no crop final mask to BoundingBox" flag on
itkGetConstMacro(SampleRate2, int);
GGO_DefineOption(sampleRate2, SetSampleRate2, int);
- // Final Step
+ // Step fill holes
+ itkSetMacro(FillHoles, bool);
+ itkGetConstMacro(FillHoles, bool);
+ itkBooleanMacro(FillHoles);
+ GGO_DefineOption_Flag(doNotFillHoles, SetFillHoles);
+
+ // Step Auto Crop
itkSetMacro(AutoCrop, bool);
itkGetConstMacro(AutoCrop, bool);
itkBooleanMacro(AutoCrop);
InputImageSizeType m_Radius2;
int m_SampleRate2;
+ // Step
+ bool m_FillHoles;
+ InputImageSizeType m_FillHolesDirections;
+
virtual void GenerateOutputInformation();
virtual void GenerateData();
#include "clitkSetBackgroundImageFilter.h"
#include "clitkSegmentationUtils.h"
#include "clitkAutoCropFilter.h"
+#include "clitkFillMaskFilter.h"
// itk
#include "itkBinaryThresholdImageFilter.h"
SetRadius2(s);
SetSampleRate2(0);
AutoCropOn();
+ FillHolesOn();
}
//--------------------------------------------------------------------
SetWriteStep_GGO(mArgsInfo);
SetVerboseWarningOff_GGO(mArgsInfo);
+ SetAFDBFilename_GGO(mArgsInfo);
SetOutputBonesFilename_GGO(mArgsInfo);
SetInitialSmoothing_GGO(mArgsInfo);
SetRadius2_GGO(mArgsInfo);
SetSampleRate2_GGO(mArgsInfo);
SetAutoCrop_GGO(mArgsInfo);
-
- SetAFDBFilename_GGO(mArgsInfo);
+ SetFillHoles_GGO(mArgsInfo);
}
//--------------------------------------------------------------------
output = setBackgroundFilter->GetOutput();
+ //--------------------------------------------------------------------
+ //--------------------------------------------------------------------
+ // Fill Bones
+ if (GetFillHoles()) {
+ StartNewStep("Fill Holes");
+ typedef clitk::FillMaskFilter<InternalImageType> FillMaskFilterType;
+ typename FillMaskFilterType::Pointer fillMaskFilter = FillMaskFilterType::New();
+ fillMaskFilter->SetInput(output);
+ fillMaskFilter->AddDirection(2);
+ fillMaskFilter->Update();
+ output = fillMaskFilter->GetOutput();
+ StopCurrentStep<InternalImageType>(output);
+ }
+
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// [Optional]
cropFilter->SetCropLikeImage(patient);
cropFilter->Update();
working_input = cropFilter->GetOutput();
+ DD(working_input->GetLargestPossibleRegion());
StopCurrentStep<ImageType>(working_input);
//--------------------------------------------------------------------
autocropFilter2->SetInput(working_image);
autocropFilter2->Update();
working_image = autocropFilter2->GetOutput();
+ DD(working_image->GetLargestPossibleRegion());
StopCurrentStep<InternalImageType>(working_image);
//--------------------------------------------------------------------
// Fill Lungs
if (GetFillHoles()) {
StartNewStep("Fill Holes");
- /*
+ typedef clitk::FillMaskFilter<InternalImageType> FillMaskFilterType;
typename FillMaskFilterType::Pointer fillMaskFilter = FillMaskFilterType::New();
- fillMaskFilter(working_image);
+ fillMaskFilter->SetInput(working_image);
+ fillMaskFilter->AddDirection(2);
+ //fillMaskFilter->AddDirection(1);
fillMaskFilter->Update();
working_image = fillMaskFilter->GetOutput();
StopCurrentStep<InternalImageType>(working_image);
- */
}
//--------------------------------------------------------------------
// Decompose the first label
static const unsigned int Dim = ImageType::ImageDimension;
if (initialNumberOfLabels<2) {
+ DD(initialNumberOfLabels);
// Structuring element radius
typename ImageType::SizeType radius;
for (unsigned int i=0;i<Dim;i++) radius[i]=1;
typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> DecomposeAndReconstructFilterType;
typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
decomposeAndReconstructFilter->SetInput(working_image);
- decomposeAndReconstructFilter->SetVerbose(false);
+ decomposeAndReconstructFilter->SetVerbose(true);
decomposeAndReconstructFilter->SetRadius(radius);
decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
decomposeAndReconstructFilter->SetMinimumObjectSize(this->GetMinimalComponentSize());
f->SetLower(-2000);
f->SetUpper(GetUpperThresholdForTrachea());
f->SetMinimumLowerThreshold(-2000);
- f->SetMaximumUpperThreshold(0);
+ // f->SetMaximumUpperThreshold(0); // MAYBE TO CHANGE ???
+ f->SetMaximumUpperThreshold(-800); // MAYBE TO CHANGE ???
f->SetAdaptLowerBorder(false);
f->SetAdaptUpperBorder(true);
f->SetMinimumSize(5000);
f->SetMultiplier(GetMultiplierForTrachea());
f->SetThresholdStepSize(GetThresholdStepSizeForTrachea());
f->SetMinimumThresholdStepSize(1);
+ f->VerboseOn();
for(unsigned int i=0; i<m_Seeds.size();i++) {
f->AddSeed(m_Seeds[i]);
// DD(m_Seeds[i]);
}
f->Update();
+ writeImage<InternalImageType>(f->GetOutput(), "trg.mhd");
+
// take first (main) connected component
trachea_tmp = Labelize<InternalImageType>(f->GetOutput(),
GetBackgroundValue(),
section "I/O"
option "afdb" a "Input Anatomical Feature DB" string no
-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, with origin)" double no
-option "middleLobeBronchusZposition" b "Sup-Inf position of the middle lobe bronchus (in mm, with origin)" double no
-option "spacing" - "Intermediate resampling spacing" double no default="6"
-option "fuzzy1" - "Fuzzy relative position threshold" double no default="0.6"
+option "input" i "Input filename" string no
+option "output" o "Output lungs mask filename" string no
+
//--------------------------------------------------------------------
/*
Try to extract the LymphStations part of a thorax CT.
- Inputs :
- - Patient label image
- - Lungs label image
- - Bones label image
+ Need a set of Anatomical Features (AFDB)
*/
//--------------------------------------------------------------------
class ITK_EXPORT ExtractLymphStationsFilter:
public virtual clitk::FilterBase,
public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
- public itk::ImageToImageFilter<TImageType, TImageType>
+ public itk::ImageToImageFilter<TImageType, itk::Image<uchar, 3> >
{
public:
/** Standard class typedefs. */
- typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+ typedef itk::ImageToImageFilter<TImageType, itk::Image<uchar, 3> > Superclass;
typedef ExtractLymphStationsFilter Self;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
itkNewMacro(Self);
/** Run-time type information (and related methods). */
- itkTypeMacro(ExtractLymphStationsFilter, InPlaceImageFilter);
- FILTERBASE_INIT;
+ itkTypeMacro(ExtractLymphStationsFilter, ImageToImageFilter);
/** Some convenient typedefs. */
typedef TImageType ImageType;
typedef typename ImageType::IndexType ImageIndexType;
typedef typename ImageType::PointType ImagePointType;
- /** 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);
+ typedef uchar MaskImagePixelType;
+ typedef itk::Image<MaskImagePixelType, 3> MaskImageType;
+ typedef typename MaskImageType::Pointer MaskImagePointer;
+ typedef typename MaskImageType::RegionType MaskImageRegionType;
+ typedef typename MaskImageType::SizeType MaskImageSizeType;
+ typedef typename MaskImageType::IndexType MaskImageIndexType;
+ typedef typename MaskImageType::PointType MaskImagePointType;
- // Set all options at a time
- template<class ArgsInfoType>
- void SetArgsInfo(ArgsInfoType arg);
+ /** ImageDimension constants */
+ itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+ FILTERBASE_INIT;
- // Background / Foreground
- itkSetMacro(BackgroundValueMediastinum, ImagePixelType);
- itkGetConstMacro(BackgroundValueMediastinum, ImagePixelType);
- //GGO_DefineOption(MediastinumBG, SetBackgroundValueMediastinum, ImagePixelType);
+ /** Main options (from ggo) */
+ template <class ArgsInfoType>
+ void SetArgsInfo(ArgsInfoType & argsinfo);
+
+ itkGetConstMacro(BackgroundValue, MaskImagePixelType);
+ itkGetConstMacro(ForegroundValue, MaskImagePixelType);
+ itkSetMacro(BackgroundValue, MaskImagePixelType);
+ itkSetMacro(ForegroundValue, MaskImagePixelType);
- itkSetMacro(BackgroundValueTrachea, ImagePixelType);
- itkGetConstMacro(BackgroundValueTrachea, ImagePixelType);
- //GGO_DefineOption(TracheaBG, SetBackgroundValueTrachea, ImagePixelType);
-
- itkGetConstMacro(BackgroundValue, ImagePixelType);
- itkGetConstMacro(ForegroundValue, ImagePixelType);
-
- //itkSetMacro(CarinaZPositionInMM, double);
- void SetCarinaZPositionInMM(double d) { m_CarinaZPositionInMM = d; Modified(); m_CarinaZPositionInMMIsSet = true; }
- itkGetConstMacro(CarinaZPositionInMM, double);
- GGO_DefineOption(carenaZposition, SetCarinaZPositionInMM, double);
+ // Station 7
+ itkSetMacro(FuzzyThreshold, double);
+ itkGetConstMacro(FuzzyThreshold, double);
+ itkSetMacro(Station7Filename, std::string);
+ itkGetConstMacro(Station7Filename, std::string);
- 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_CarinaZPositionInMM;
- bool m_CarinaZPositionInMMIsSet;
- double m_MiddleLobeBronchusZPositionInMM;
- double m_IntermediateSpacing;
- double m_FuzzyThreshold1;
+ ImageConstPointer m_Input;
+ MaskImagePointer m_Support;
+ MaskImagePointer m_Working_Support;
+ MaskImagePointer m_Output;
+ MaskImagePixelType m_BackgroundValue;
+ MaskImagePixelType m_ForegroundValue;
+
+ // Common
+ MaskImagePointer m_Trachea;
+
+ // Station 7
+ void ExtractStation_7();
+ void ExtractStation_7_SI_Limits();
+ void ExtractStation_7_RL_Limits();
+ void ExtractStation_7_Posterior_Limits();
+ std::string m_Station7Filename;
+ MaskImagePointer m_working_trachea;
+ double m_FuzzyThreshold;
+ MaskImagePointer m_LeftBronchus;
+ MaskImagePointer m_RightBronchus;
+ MaskImagePointer m_Station7;
+
+ // Station 4RL
+ void ExtractStation_4RL();
+ void ExtractStation_4RL_SI_Limits();
+ void ExtractStation_4RL_LR_Limits();
+ MaskImagePointer m_Station4RL;
+
private:
ExtractLymphStationsFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
#ifndef ITK_MANUAL_INSTANTIATION
#include "clitkExtractLymphStationsFilter.txx"
+#include "clitkExtractLymphStation_7.txx"
+#include "clitkExtractLymphStation_4RL.txx"
#endif
#endif
#include <itkRegionOfInterestImageFilter.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkImageSliceConstIteratorWithIndex.h>
+#include <itkImageSliceIteratorWithIndex.h>
#include <itkBinaryThinningImageFilter.h>
// itk ENST
ExtractLymphStationsFilter():
clitk::FilterBase(),
clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
- itk::ImageToImageFilter<TImageType, TImageType>()
+ itk::ImageToImageFilter<TImageType, MaskImageType>()
{
this->SetNumberOfRequiredInputs(1);
- SetBackgroundValueMediastinum(0);
- SetBackgroundValueTrachea(0);
SetBackgroundValue(0);
SetForegroundValue(1);
- SetIntermediateSpacing(6);
- SetFuzzyThreshold1(0.6);
- m_CarinaZPositionInMMIsSet = false;
+
+ // Station 7
+ SetFuzzyThreshold(0.5);
+ SetStation7Filename("station7.mhd");
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
template <class TImageType>
+template <class ArgsInfoType>
void
clitk::ExtractLymphStationsFilter<TImageType>::
-SetInputMediastinumLabelImage(const TImageType * image, ImagePixelType bg) {
- this->SetNthInput(0, const_cast<TImageType *>(image));
- SetBackgroundValueMediastinum(bg);
+SetArgsInfo(ArgsInfoType & argsinfo) {
+ DD("SetArgsInfo");
}
//--------------------------------------------------------------------
template <class TImageType>
void
clitk::ExtractLymphStationsFilter<TImageType>::
-SetInputTracheaLabelImage(const TImageType * image, ImagePixelType bg) {
- this->SetNthInput(1, const_cast<TImageType *>(image));
- SetBackgroundValueTrachea(bg);
+GenerateOutputInformation() {
+ // Get inputs
+ LoadAFDB();
+ m_Input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
+ m_Support = GetAFDB()->template GetImage <MaskImageType>("mediastinum");
+
+ //
+ typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BFilter;
+ BFilter::Pointer merge = BFilter::New();
+
+ // Extract Station7
+ ExtractStation_7();
+ m_Output = m_Station7;
+
+ // Extract Station4RL
+ ExtractStation_4RL();
+
+ writeImage<MaskImageType>(m_Station4RL, "s4rl.mhd");
+ // writeImage<MaskImageType>(m_Output, "ouput.mhd");
+ //writeImage<MaskImageType>(m_Working_Support, "ws.mhd");
+ /*merge->SetInput1(m_Station7);
+ merge->SetInput2(m_Station4RL); // support
+ merge->SetOperationType(BFilter::AndNot); CHANGE OPERATOR
+ merge->SetForegroundValue(4);
+ merge->Update();
+ m_Output = merge->GetOutput();
+ */
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
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);
- SetAFDBFilename_GGO(mArgsInfo);
- SetCarinaZPositionInMM_GGO(mArgsInfo);
- m_CarinaZPositionInMMIsSet = false;
- SetMiddleLobeBronchusZPositionInMM_GGO(mArgsInfo);
- SetIntermediateSpacing_GGO(mArgsInfo);
- SetFuzzyThreshold1_GGO(mArgsInfo);
+GenerateInputRequestedRegion() {
+ DD("GenerateInputRequestedRegion (nothing?)");
}
//--------------------------------------------------------------------
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));
-
- // Get landmarks information
- if (!m_CarinaZPositionInMMIsSet) {
- ImagePointType carina;
- LoadAFDB();
- GetAFDB()->GetPoint3D("Carina", carina);
- DD(carina);
- m_CarinaZPositionInMM = carina[2];
- }
- DD(m_CarinaZPositionInMM);
-
- // ----------------------------------------------------------------
- // ----------------------------------------------------------------
- // Superior limit = carina
- // Inferior limit = origin right middle lobe bronchus
- StartNewStep("Inf/Sup mediastinum limits with carina/bronchus");
- ImageRegionType region = m_mediastinum->GetLargestPossibleRegion(); DD(region);
- ImageSizeType size = region.GetSize();
- ImageIndexType index = region.GetIndex();
- DD(m_CarinaZPositionInMM);
- DD(m_MiddleLobeBronchusZPositionInMM);
- index[2] = floor((m_MiddleLobeBronchusZPositionInMM - m_mediastinum->GetOrigin()[2]) / m_mediastinum->GetSpacing()[2]);
- size[2] = 1+ceil((m_CarinaZPositionInMM-m_MiddleLobeBronchusZPositionInMM) / m_mediastinum->GetSpacing()[2]); // +1 to
- 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 under carina");
- // 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);
-
- // 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;
- ImagePixelType rightLabel;
- while (!stop) {
- if (iter.Get() != m_BackgroundValueTrachea) {
- // DD(iter.GetIndex());
- // DD((int)iter.Get());
- leftLabel = iter.Get();
- stop = true;
- }
- ++iter;
- }
- if (leftLabel == 1) rightLabel = 2;
- else rightLabel = 1;
- DD((int)leftLabel);
- DD((int)rightLabel);
-
- // End step
- StopCurrentStep<ImageType>(m_working_trachea);
-
- //-----------------------------------------------------
- /* DD("TEST Skeleton");
- typedef itk::BinaryThinningImageFilter<ImageType, ImageType> SkeletonFilterType;
- typename SkeletonFilterType::Pointer skeletonFilter = SkeletonFilterType::New();
- skeletonFilter->SetInput(m_working_trachea);
- skeletonFilter->Update();
- writeImage<ImageType>(skeletonFilter->GetOutput(), "skel.mhd");
- writeImage<ImageType>(skeletonFilter->GetThinning(), "skel2.mhd");
- */
-
- //-----------------------------------------------------
- StartNewStep("Left limits with bronchus (slice by slice)");
- // Select LeftLabel (set right label to 0)
- ImagePointer temp = SetBackground<ImageType, ImageType>(m_working_trachea, m_working_trachea, rightLabel, 0);
- writeImage<ImageType>(temp, "temp1.mhd");
-
- typedef clitk::SliceBySliceRelativePositionFilter<ImageType> SliceRelPosFilterType;
- typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
- sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
- sliceRelPosFilter->VerboseStepOn();
- sliceRelPosFilter->WriteStepOn();
- sliceRelPosFilter->SetInput(m_working_image);
- sliceRelPosFilter->SetInputObject(temp);
- sliceRelPosFilter->SetDirection(2);
- sliceRelPosFilter->SetFuzzyThreshold(0.6);
- sliceRelPosFilter->SetOrientationType(SliceRelPosFilterType::RelPosFilterType::RightTo);
- sliceRelPosFilter->Update();
- m_working_image = sliceRelPosFilter->GetOutput();
- writeImage<ImageType>(m_working_image, "afterslicebyslice.mhd");
-
-
- //-----------------------------------------------------
- StartNewStep("Right limits with bronchus (slice by slice)");
- // Select LeftLabel (set right label to 0)
- temp = SetBackground<ImageType, ImageType>(m_working_trachea, m_working_trachea, leftLabel, 0);
- writeImage<ImageType>(temp, "temp2.mhd");
-
- sliceRelPosFilter = SliceRelPosFilterType::New();
- sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
- sliceRelPosFilter->VerboseStepOn();
- sliceRelPosFilter->WriteStepOn();
- sliceRelPosFilter->SetInput(m_working_image);
- sliceRelPosFilter->SetInputObject(temp);
- sliceRelPosFilter->SetDirection(2);
- sliceRelPosFilter->SetFuzzyThreshold(0.6);
- sliceRelPosFilter->SetOrientationType(SliceRelPosFilterType::RelPosFilterType::LeftTo);
- sliceRelPosFilter->Update();
- m_working_image = sliceRelPosFilter->GetOutput();
- writeImage<ImageType>(m_working_image, "afterslicebyslice.mhd");
-
-
- DD("end");
- m_output = m_working_image;
- StopCurrentStep<ImageType>(m_output);
+GenerateData() {
+ DD("GenerateData, graft 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");
+ // Final Step -> graft output (if SetNthOutput => redo)
+ this->GraftOutput(m_Output);
}
//--------------------------------------------------------------------
-
+
//--------------------------------------------------------------------
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());
+ExtractStation_7() {
+ DD("ExtractStation_7");
+ ExtractStation_7_SI_Limits();
+ ExtractStation_7_RL_Limits();
+ ExtractStation_7_Posterior_Limits();
}
//--------------------------------------------------------------------
template <class TImageType>
void
clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateData() {
- DD("GenerateData");
- // Final Step -> graft output (if SetNthOutput => redo)
- this->GraftOutput(m_output);
+ExtractStation_4RL() {
+ DD("ExtractStation_4RL");
+ writeImage<MaskImageType>(m_Support, "essai.mhd"); // OK
+
+ /*
+ WARNING ONLY 4R FIRST !!! (not same inf limits)
+ */
+
+ ExtractStation_4RL_SI_Limits();
+ ExtractStation_4RL_LR_Limits();
+
}
//--------------------------------------------------------------------
-
+
+
#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
ExtractLymphStationsGenericFilter();
//--------------------------------------------------------------------
- typedef ExtractLymphStationsGenericFilter Self;
typedef ImageToImageGenericFilter<ExtractLymphStationsGenericFilter<ArgsInfoType> > Superclass;
- typedef itk::SmartPointer<Self> Pointer;
- typedef itk::SmartPointer<const Self> ConstPointer;
+ typedef ExtractLymphStationsGenericFilter Self;
+ typedef itk::SmartPointer<Self> Pointer;
+ typedef itk::SmartPointer<const Self> ConstPointer;
//--------------------------------------------------------------------
itkNewMacro(Self);
//--------------------------------------------------------------------
void SetArgsInfo(const ArgsInfoType & a);
+ template<class FilterType>
+ void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
//--------------------------------------------------------------------
// Main function called each time the filter is updated
template<unsigned int Dim> void InitializeImageType();
ArgsInfoType mArgsInfo;
+ private:
+ ExtractLymphStationsGenericFilter(const Self&); //purposely not implemented
+ void operator=(const Self&); //purposely not implemented
+
}; // end class
//--------------------------------------------------------------------
{
// Default values
cmdline_parser_clitkExtractLymphStations_init(&mArgsInfo);
- InitializeImageType<3>();
+ InitializeImageType<3>(); // Only for 3D images
}
//--------------------------------------------------------------------
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);
+ ADD_IMAGE_TYPE(Dim, short); // Can add float later
}
//--------------------------------------------------------------------
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);
+ if (mArgsInfo.input_given) AddInputFilename(mArgsInfo.input_arg);
+ if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void
+clitk::ExtractLymphStationsGenericFilter<ArgsInfoType>::
+SetOptionsFromArgsInfoToFilter(FilterType * f)
+{
+ f->SetVerboseOption(mArgsInfo.verbose_flag);
+ f->SetVerboseStep(mArgsInfo.verboseStep_flag);
+ f->SetWriteStep(mArgsInfo.writeStep_flag);
+ f->SetAFDBFilename(mArgsInfo.afdb_arg);
}
//--------------------------------------------------------------------
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);
+ typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
// 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);
+ filter->SetInput(input);
+ SetOptionsFromArgsInfoToFilter<FilterType>(filter);
// Go !
- // try {
- filter->Update();
- // }
- // catch(std::runtime_error e) {
-
- // // Check if error
- // if (filter->HasError()) {
- // SetLastError(filter->GetLastError());
- // // No output
- // return;
- // }
+ filter->Update();
// Write/Save results
- typename ImageType::Pointer output = filter->GetOutput();
- this->template SetNextOutput<ImageType>(output);
+ typedef uchar MaskImagePixelType;
+ typedef itk::Image<MaskImagePixelType, 3> OutputImageType;
+ typename OutputImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<OutputImageType>(output);
}
//--------------------------------------------------------------------
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 "trachea" t "Input trachea mask filename" string yes
-option "tracheaBG" - "Trachea Background" int default="0" no
-option "afdb" a "Input Anatomical Feature DB" string no
+option "input" i "Input CT filename" string yes
+option "afdb" a "Input Anatomical Feature DB" string no
+option "useBones" - "If set : do use bones mask (when image is not injected)" flag off
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.4"
+option "fuzzy1" - "Fuzzy relative position threshold" double no default="0.5"
section "Step 2 : Ant/Post limits with bones"
option "fuzzy2" - "Fuzzy relative position threshold" double no default="0.6"
+option "antSpine" - "Distance max to anterior part of the spine in mm" double no default="10"
section "Step 3 : Inf limits with Lung"
-option "fuzzy3" - "Fuzzy relative position threshold" double no default="0.2"
+option "fuzzy3" - "Fuzzy relative position threshold" double no default="0.05"
+
+section "Step x : threshold for removing bones and injected parts"
+option "upper" - "Upper threshold" double no default="150"
+option "lower" - "Lower threshold" double no default="-200"
\ No newline at end of file
class ITK_EXPORT ExtractMediastinumFilter:
public virtual clitk::FilterBase,
public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
- public itk::ImageToImageFilter<TImageType, TImageType>
+ public itk::ImageToImageFilter<TImageType, itk::Image<uchar, 3> >
{
public:
+ /** 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;
+ typedef typename ImageType::PointType ImagePointType;
+
+ /** Some convenient typedefs. */
+ typedef uchar MaskImagePixelType;
+ typedef itk::Image<MaskImagePixelType, 3> MaskImageType;
+ typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
+ typedef typename MaskImageType::Pointer MaskImagePointer;
+ typedef typename MaskImageType::RegionType MaskImageRegionType;
+ typedef typename MaskImageType::SizeType MaskImageSizeType;
+ typedef typename MaskImageType::IndexType MaskImageIndexType;
+ typedef typename MaskImageType::PointType MaskImagePointType;
+
/** Standard class typedefs. */
- typedef itk::ImageToImageFilter<TImageType, TImageType> Superclass;
+ typedef itk::ImageToImageFilter<TImageType, MaskImageType> Superclass;
typedef ExtractMediastinumFilter Self;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
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;
- typedef typename ImageType::PointType ImagePointType;
-
/** 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);
- void SetInputTracheaLabelImage(const TImageType * image, ImagePixelType bg=0);
+ void SetInput(const ImageType * image);
+ void SetInputPatientLabelImage(const MaskImageType * image, MaskImagePixelType bg=0);
+ void SetInputLungLabelImage(const MaskImageType * image, MaskImagePixelType bg=0,
+ MaskImagePixelType fgLeftLung=1, MaskImagePixelType fgRightLung=2);
+ void SetInputBonesLabelImage(const MaskImageType * image, MaskImagePixelType bg=0);
+ void SetInputTracheaLabelImage(const MaskImageType * image, MaskImagePixelType bg=0);
+ // Output filename (for AFBD)
+ itkSetMacro(OutputMediastinumFilename, std::string);
+ itkGetConstMacro(OutputMediastinumFilename, std::string);
+
/** ImageDimension constants */
- itkStaticConstMacro(ImageDimension, unsigned int, TImageType::ImageDimension);
+ itkStaticConstMacro(ImageDimension, unsigned int, ImageType::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(BackgroundValuePatient, MaskImagePixelType);
+ itkGetConstMacro(BackgroundValuePatient, MaskImagePixelType);
+ // GGO_DefineOption(patientBG, SetBackgroundValuePatient, MaskImagePixelType);
- itkSetMacro(BackgroundValueLung, ImagePixelType);
- itkGetConstMacro(BackgroundValueLung, ImagePixelType);
- GGO_DefineOption(lungBG, SetBackgroundValueLung, ImagePixelType);
+ itkSetMacro(BackgroundValueLung, MaskImagePixelType);
+ itkGetConstMacro(BackgroundValueLung, MaskImagePixelType);
+ // GGO_DefineOption(lungBG, SetBackgroundValueLung, MaskImagePixelType);
- itkSetMacro(BackgroundValueBones, ImagePixelType);
- itkGetConstMacro(BackgroundValueBones, ImagePixelType);
- GGO_DefineOption(bonesBG, SetBackgroundValueBones, ImagePixelType);
+ itkSetMacro(BackgroundValueBones, MaskImagePixelType);
+ itkGetConstMacro(BackgroundValueBones, MaskImagePixelType);
+ // GGO_DefineOption(bonesBG, SetBackgroundValueBones, MaskImagePixelType);
- itkGetConstMacro(BackgroundValue, ImagePixelType);
- itkGetConstMacro(ForegroundValue, ImagePixelType);
+ itkGetConstMacro(BackgroundValue, MaskImagePixelType);
+ itkGetConstMacro(ForegroundValue, MaskImagePixelType);
- itkSetMacro(ForegroundValueLeftLung, ImagePixelType);
- itkGetConstMacro(ForegroundValueLeftLung, ImagePixelType);
- GGO_DefineOption(lungLeft, SetForegroundValueLeftLung, ImagePixelType);
+ itkSetMacro(ForegroundValueLeftLung, MaskImagePixelType);
+ itkGetConstMacro(ForegroundValueLeftLung, MaskImagePixelType);
+ // GGO_DefineOption(lungLeft, SetForegroundValueLeftLung, MaskImagePixelType);
- itkSetMacro(ForegroundValueRightLung, ImagePixelType);
- itkGetConstMacro(ForegroundValueRightLung, ImagePixelType);
- GGO_DefineOption(lungRight, SetForegroundValueRightLung, ImagePixelType);
+ itkSetMacro(ForegroundValueRightLung, MaskImagePixelType);
+ itkGetConstMacro(ForegroundValueRightLung, MaskImagePixelType);
+ // GGO_DefineOption(lungRight, SetForegroundValueRightLung, MaskImagePixelType);
- itkSetMacro(BackgroundValueTrachea, ImagePixelType);
- itkGetConstMacro(BackgroundValueTrachea, ImagePixelType);
- GGO_DefineOption(lungBG, SetBackgroundValueTrachea, ImagePixelType);
+ itkSetMacro(BackgroundValueTrachea, MaskImagePixelType);
+ itkGetConstMacro(BackgroundValueTrachea, MaskImagePixelType);
+ // GGO_DefineOption(lungBG, SetBackgroundValueTrachea, MaskImagePixelType);
itkSetMacro(IntermediateSpacing, double);
itkGetConstMacro(IntermediateSpacing, double);
itkGetConstMacro(FuzzyThreshold3, double);
GGO_DefineOption(fuzzy3, SetFuzzyThreshold3, double);
+ itkSetMacro(DistanceMaxToAnteriorPartOfTheSpine, double);
+ itkGetConstMacro(DistanceMaxToAnteriorPartOfTheSpine, double);
+ GGO_DefineOption(antSpine, SetDistanceMaxToAnteriorPartOfTheSpine, double);
+
+ itkBooleanMacro(UseBones);
+ itkSetMacro(UseBones, bool);
+ itkGetConstMacro(UseBones, bool);
+ GGO_DefineOption_Flag(useBones, SetUseBones);
+
+ itkSetMacro(UpperThreshold, double);
+ itkGetConstMacro(UpperThreshold, double);
+ GGO_DefineOption(upper, SetUpperThreshold, double);
+
+ itkSetMacro(LowerThreshold, double);
+ itkGetConstMacro(LowerThreshold, double);
+ GGO_DefineOption(lower, SetLowerThreshold, double);
+
protected:
ExtractMediastinumFilter();
virtual ~ExtractMediastinumFilter() {}
virtual void GenerateInputRequestedRegion();
virtual void GenerateData();
- itkSetMacro(BackgroundValue, ImagePixelType);
- itkSetMacro(ForegroundValue, ImagePixelType);
-
- ImagePixelType m_BackgroundValuePatient;
- ImagePixelType m_BackgroundValueLung;
- ImagePixelType m_BackgroundValueBones;
- ImagePixelType m_BackgroundValueTrachea;
- ImagePixelType m_ForegroundValueLeftLung;
- ImagePixelType m_ForegroundValueRightLung;
-
- ImagePixelType m_BackgroundValue;
- ImagePixelType m_ForegroundValue;
+ itkSetMacro(BackgroundValue, MaskImagePixelType);
+ itkSetMacro(ForegroundValue, MaskImagePixelType);
+ MaskImagePixelType m_BackgroundValuePatient;
+ MaskImagePixelType m_BackgroundValueLung;
+ MaskImagePixelType m_BackgroundValueBones;
+ MaskImagePixelType m_BackgroundValueTrachea;
+ MaskImagePixelType m_ForegroundValueLeftLung;
+ MaskImagePixelType m_ForegroundValueRightLung;
+
+ MaskImagePixelType m_BackgroundValue;
+ MaskImagePixelType m_ForegroundValue;
+
+ typename MaskImageType::Pointer output;
+
double m_IntermediateSpacing;
double m_FuzzyThreshold1;
double m_FuzzyThreshold2;
double m_FuzzyThreshold3;
+ double m_DistanceMaxToAnteriorPartOfTheSpine;
+ bool m_UseBones;
+ double m_UpperThreshold;
+ double m_LowerThreshold;
+
+ std::string m_OutputMediastinumFilename;
private:
ExtractMediastinumFilter(const Self&); //purposely not implemented
#include "clitkCommon.h"
#include "clitkExtractMediastinumFilter.h"
#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+#include "clitkSliceBySliceRelativePositionFilter.h"
#include "clitkSegmentationUtils.h"
#include "clitkExtractAirwaysTreeInfoFilter.h"
#include "clitkCropLikeImageFilter.h"
#include "itkLabelImageToStatisticsLabelMapFilter.h"
#include "itkRegionOfInterestImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
+#include "itkScalarImageKmeansImageFilter.h"
// itk ENST
#include "RelativePositionPropImageFilter.h"
ExtractMediastinumFilter():
clitk::FilterBase(),
clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
- itk::ImageToImageFilter<ImageType, ImageType>()
+ itk::ImageToImageFilter<ImageType, MaskImageType>()
{
- this->SetNumberOfRequiredInputs(4);
+ this->SetNumberOfRequiredInputs(1);
SetBackgroundValuePatient(0);
SetBackgroundValueLung(0);
SetForegroundValue(1);
SetIntermediateSpacing(6);
- SetFuzzyThreshold1(0.4);
+ SetFuzzyThreshold1(0.5);
SetFuzzyThreshold2(0.6);
- SetFuzzyThreshold3(0.2);
+ SetFuzzyThreshold3(0.05);
+
+ SetDistanceMaxToAnteriorPartOfTheSpine(10);
+ SetOutputMediastinumFilename("mediastinum.mhd");
+
+ UseBonesOff();
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-SetInputPatientLabelImage(const ImageType * image, ImagePixelType bg)
+SetInputPatientLabelImage(const MaskImageType * image, MaskImagePixelType bg)
{
- this->SetNthInput(0, const_cast<ImageType *>(image));
+ this->SetNthInput(0, const_cast<MaskImageType *>(image));
m_BackgroundValuePatient = bg;
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-SetInputLungLabelImage(const ImageType * image, ImagePixelType bg,
- ImagePixelType fgLeft, ImagePixelType fgRight)
+SetInputLungLabelImage(const MaskImageType * image, MaskImagePixelType bg,
+ MaskImagePixelType fgLeft, MaskImagePixelType fgRight)
{
- this->SetNthInput(1, const_cast<ImageType *>(image));
+ this->SetNthInput(1, const_cast<MaskImageType *>(image));
m_BackgroundValueLung = bg;
m_ForegroundValueLeftLung = fgLeft;
m_ForegroundValueRightLung = fgRight;
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-SetInputBonesLabelImage(const ImageType * image, ImagePixelType bg)
+SetInputBonesLabelImage(const MaskImageType * image, MaskImagePixelType bg)
{
- this->SetNthInput(2, const_cast<ImageType *>(image));
+ this->SetNthInput(2, const_cast<MaskImageType *>(image));
m_BackgroundValueBones = bg;
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-SetInputTracheaLabelImage(const ImageType * image, ImagePixelType bg)
+SetInputTracheaLabelImage(const MaskImageType * image, MaskImagePixelType bg)
{
- this->SetNthInput(3, const_cast<ImageType *>(image));
+ this->SetNthInput(3, const_cast<MaskImageType *>(image));
m_BackgroundValueTrachea = bg;
}
//--------------------------------------------------------------------
SetWriteStep_GGO(mArgsInfo);
SetVerboseWarningOff_GGO(mArgsInfo);
- SetBackgroundValuePatient_GGO(mArgsInfo);
- SetBackgroundValueLung_GGO(mArgsInfo);
- SetBackgroundValueTrachea_GGO(mArgsInfo);
-
- SetForegroundValueLeftLung_GGO(mArgsInfo);
- SetForegroundValueRightLung_GGO(mArgsInfo);
-
SetIntermediateSpacing_GGO(mArgsInfo);
SetFuzzyThreshold1_GGO(mArgsInfo);
SetFuzzyThreshold2_GGO(mArgsInfo);
SetFuzzyThreshold3_GGO(mArgsInfo);
- SetAFDBFilename_GGO(mArgsInfo);
+ SetAFDBFilename_GGO(mArgsInfo);
+ SetDistanceMaxToAnteriorPartOfTheSpine_GGO(mArgsInfo);
+ SetUseBones_GGO(mArgsInfo);
+
+ SetLowerThreshold_GGO(mArgsInfo);
+ SetUpperThreshold_GGO(mArgsInfo);
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-GenerateOutputInformation() {
- ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
- ImagePointer outputImage = this->GetOutput(0);
- outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+GenerateInputRequestedRegion()
+{
+ //DD("GenerateInputRequestedRegion");
+ // Do not call default
+ // Superclass::GenerateInputRequestedRegion();
+ // DD("End GenerateInputRequestedRegion");
}
+
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-GenerateInputRequestedRegion()
+SetInput(const ImageType * image)
{
- // Call default
- Superclass::GenerateInputRequestedRegion();
-
- // Get input pointers
- LoadAFDB();
- ImagePointer patient = GetAFDB()->template GetImage <ImageType>("patient");
- ImagePointer lung = GetAFDB()->template GetImage <ImageType>("lungs");
- ImagePointer bones = GetAFDB()->template GetImage <ImageType>("bones");
- ImagePointer trachea = GetAFDB()->template GetImage <ImageType>("trachea");
-
- patient->SetRequestedRegion(patient->GetLargestPossibleRegion());
- lung->SetRequestedRegion(lung->GetLargestPossibleRegion());
- bones->SetRequestedRegion(bones->GetLargestPossibleRegion());
- trachea->SetRequestedRegion(trachea->GetLargestPossibleRegion());
+ this->SetNthInput(0, const_cast<ImageType *>(image));
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::ExtractMediastinumFilter<ImageType>::
-GenerateData()
-{
+GenerateOutputInformation() {
+ // DD("GenerateOutputInformation");
+ // Do not call default
+ // Superclass::GenerateOutputInformation();
+
+ //--------------------------------------------------------------------
// Get input pointers
- ImagePointer patient = GetAFDB()->template GetImage <ImageType>("patient");
- ImagePointer lung = GetAFDB()->template GetImage <ImageType>("lungs");
- ImagePointer bones = GetAFDB()->template GetImage <ImageType>("bones");
- ImagePointer trachea = GetAFDB()->template GetImage <ImageType>("trachea");
+ LoadAFDB();
+ ImageConstPointer input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
+ MaskImagePointer patient = GetAFDB()->template GetImage <MaskImageType>("patient");
+ MaskImagePointer lung = GetAFDB()->template GetImage <MaskImageType>("lungs");
+ MaskImagePointer bones = GetAFDB()->template GetImage <MaskImageType>("bones");
+ MaskImagePointer trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");
- // Get output pointer
- ImagePointer output;
-
- // Step 0: Crop support (patient) to lung extend in RL
+ //--------------------------------------------------------------------
+ // Step 1: Crop support (patient) to lung extend in RL
StartNewStep("Crop support like lungs along LR");
- typedef clitk::CropLikeImageFilter<ImageType> CropFilterType;
+ typedef clitk::CropLikeImageFilter<MaskImageType> CropFilterType;
typename CropFilterType::Pointer cropFilter = CropFilterType::New();
cropFilter->SetInput(patient);
cropFilter->SetCropLikeImage(lung, 0);// Indicate that we only crop in X (Left-Right) axe
cropFilter->Update();
output = cropFilter->GetOutput();
- this->template StopCurrentStep<ImageType>(output);
-
- // Step 0: Crop support (previous) to bones extend in AP
- StartNewStep("Crop support like bones along AP");
- cropFilter = CropFilterType::New();
- cropFilter->SetInput(output);
- cropFilter->SetCropLikeImage(bones, 1);// Indicate that we only crop in Y (Ant-Post) axe
- cropFilter->Update();
- output = cropFilter->GetOutput();
- this->template StopCurrentStep<ImageType>(output);
-
- // Step 1: patient minus lungs, minus bones
- StartNewStep("Patient contours minus lungs and minus bones");
- typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ //--------------------------------------------------------------------
+ // Step 2: Crop support (previous) to bones extend in AP
+ if (GetUseBones()) {
+ StartNewStep("Crop support like bones along AP");
+ cropFilter = CropFilterType::New();
+ cropFilter->SetInput(output);
+ cropFilter->SetCropLikeImage(bones, 1);// Indicate that we only crop in Y (Ant-Post) axe
+ cropFilter->Update();
+ output = cropFilter->GetOutput();
+ this->template StopCurrentStep<MaskImageType>(output);
+ }
+
+ //--------------------------------------------------------------------
+ // Step 3: patient minus lungs, minus bones, minus trachea
+ StartNewStep("Patient contours minus lungs, bones, trachea");
+ typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BoolFilterType;
typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
boolFilter->InPlaceOn();
boolFilter->SetInput1(output);
boolFilter->SetInput2(lung);
boolFilter->SetOperationType(BoolFilterType::AndNot);
boolFilter->Update();
+ if (GetUseBones()) {
+ boolFilter->SetInput1(boolFilter->GetOutput());
+ boolFilter->SetInput2(bones);
+ boolFilter->SetOperationType(BoolFilterType::AndNot);
+ boolFilter->Update();
+ }
boolFilter->SetInput1(boolFilter->GetOutput());
- boolFilter->SetInput2(bones);
+ boolFilter->SetInput2(trachea);
boolFilter->SetOperationType(BoolFilterType::AndNot);
boolFilter->Update();
output = boolFilter->GetOutput();
// Auto crop to gain support area
- output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
- this->template StopCurrentStep<ImageType>(output);
-
- // Step 2: LR limits from lung (need separate lung ?)
+ output = clitk::AutoCrop<MaskImageType>(output, GetBackgroundValue());
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ //--------------------------------------------------------------------
+ // Step 4: LR limits from lung (need separate lung ?)
+ // Get separate lung images to get only the right and left lung
+ // (because RelativePositionPropImageFilter only consider fg=1);
+ // (label must be '1' because right is greater than left). (WE DO
+ // NOT NEED TO SEPARATE ? )
StartNewStep("Left/Right limits with lungs");
-
/*
- // WE DO NOT NEED THE FOLLOWING ?
- // Get separate lung images to get only the right and left lung (because RelativePositionPropImageFilter only consider fg=1);
- // (label must be '1' because right is greater than left).
- ImagePointer right_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 2, 0);
- ImagePointer left_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 1, 0);
- writeImage<ImageType>(right_lung, "right.mhd");
- writeImage<ImageType>(left_lung, "left.mhd");
+ ImagePointer right_lung = clitk::SetBackground<MaskImageType, MaskImageType>(lung, lung, 2, 0);
+ ImagePointer left_lung = clitk::SetBackground<MaskImageType, MaskImageType>(lung, lung, 1, 0);
+ writeImage<MaskImageType>(right_lung, "right.mhd");
+ writeImage<MaskImageType>(left_lung, "left.mhd");
*/
-
- typedef clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType> RelPosFilterType;
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> RelPosFilterType;
typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
relPosFilter->VerboseStepOff();
relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
relPosFilter->Update();
output = relPosFilter->GetOutput();
- // writeImage<ImageType>(right_lung, "step4-left.mhd");
+ //writeImage<MaskImageType>(right_lung, "step4-left.mhd");
relPosFilter->SetInput(output);
relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
relPosFilter->Update();
output = relPosFilter->GetOutput();
- this->template StopCurrentStep<ImageType>(output);
-
- // Step 3: AP limits from bones
- StartNewStep("Ant/Post limits with bones");
- ImageConstPointer bones_ant;
- ImageConstPointer bones_post;
-
- // Find ant-post coordinate of trachea (assume the carena position is a
- // good estimation of the ant-post position of the trachea)
- ImagePointType carina;
- LoadAFDB();
- GetAFDB()->GetPoint3D("Carina", carina);
- DD(carina);
- ImageIndexType index_trachea;
- bones->TransformPhysicalPointToIndex(carina, index_trachea);
- DD(index_trachea);
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ //--------------------------------------------------------------------
+ // Step 5: AP limits from bones
+ // Separate the bones in the ant-post middle
+ MaskImageConstPointer bones_ant;
+ MaskImageConstPointer bones_post;
+ MaskImagePointType middle_AntPost__position;
+ if (GetUseBones()) {
+ StartNewStep("Ant/Post limits with bones");
+ middle_AntPost__position[0] = middle_AntPost__position[2] = 0;
+ middle_AntPost__position[1] = bones->GetOrigin()[1]+(bones->GetLargestPossibleRegion().GetSize()[1]*bones->GetSpacing()[1])/2.0;
+ MaskImageIndexType index_bones_middle;
+ bones->TransformPhysicalPointToIndex(middle_AntPost__position, index_bones_middle);
- // Split bone image first into two parts (ant and post)
- typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> ROIFilterType;
- // typedef itk::ExtractImageFilter<ImageType, ImageType> ROIFilterType;
- typename ROIFilterType::Pointer roiFilter = ROIFilterType::New();
- ImageRegionType region = bones->GetLargestPossibleRegion();
- ImageSizeType size = region.GetSize();
- DD(size);
- size[1] = index_trachea[1]; //size[1]/2.0;
- DD(size);
- region.SetSize(size);
- roiFilter->SetInput(bones);
- // roiFilter->SetExtractionRegion(region);
- roiFilter->SetRegionOfInterest(region);
- roiFilter->ReleaseDataFlagOff();
- roiFilter->Update();
- bones_ant = roiFilter->GetOutput();
- writeImage<ImageType>(bones_ant, "b_ant.mhd");
-
- // roiFilter->ResetPipeline();// = ROIFilterType::New();
- roiFilter = ROIFilterType::New();
- ImageIndexType index = region.GetIndex();
- index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1;
- size[1] = bones->GetLargestPossibleRegion().GetSize()[1] - size[1];
- DD(size);
- region.SetIndex(index);
- region.SetSize(size);
- roiFilter->SetInput(bones);
- // roiFilter->SetExtractionRegion(region);
- roiFilter->SetRegionOfInterest(region);
- roiFilter->ReleaseDataFlagOff();
- roiFilter->Update();
- bones_post = roiFilter->GetOutput();
- writeImage<ImageType>(bones_post, "b_post.mhd");
-
- // Go !
- relPosFilter->SetCurrentStepNumber(0);
- relPosFilter->ResetPipeline();// = RelPosFilterType::New();
- relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
- relPosFilter->VerboseStepOff();
- relPosFilter->WriteStepOff();
- relPosFilter->SetInput(output);
- relPosFilter->SetInputObject(bones_post);
- relPosFilter->SetOrientationType(RelPosFilterType::AntTo);
- relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
- relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
- relPosFilter->Update();
- output = relPosFilter->GetOutput();
- writeImage<ImageType>(output, "post.mhd");
-
- relPosFilter->SetInput(relPosFilter->GetOutput());
- relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
- relPosFilter->VerboseStepOff();
- relPosFilter->WriteStepOff();
- relPosFilter->SetInput(output);
- relPosFilter->SetInputObject(bones_ant);
- relPosFilter->SetOrientationType(RelPosFilterType::PostTo);
- relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
- relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
- relPosFilter->Update();
- output = relPosFilter->GetOutput();
- this->template StopCurrentStep<ImageType>(output);
-
- // Get CCL
+ // Split bone image first into two parts (ant and post), and crop
+ // lateraly to get vertebral
+ typedef itk::RegionOfInterestImageFilter<MaskImageType, MaskImageType> ROIFilterType;
+ // typedef itk::ExtractImageFilter<MaskImageType, MaskImageType> ROIFilterType;
+ typename ROIFilterType::Pointer roiFilter = ROIFilterType::New();
+ MaskImageRegionType region = bones->GetLargestPossibleRegion();
+ MaskImageSizeType size = region.GetSize();
+ MaskImageIndexType index = region.GetIndex();
+ // ANT part
+ // crop LR to keep 1/4 center part
+ index[0] = size[0]/4+size[0]/8;
+ size[0] = size[0]/4;
+ // crop AP to keep first (ant) part
+ size[1] = index_bones_middle[1]; //size[1]/2.0;
+ region.SetSize(size);
+ region.SetIndex(index);
+ roiFilter->SetInput(bones);
+ roiFilter->SetRegionOfInterest(region);
+ roiFilter->ReleaseDataFlagOff();
+ roiFilter->Update();
+ bones_ant = roiFilter->GetOutput();
+ writeImage<MaskImageType>(bones_ant, "b_ant.mhd");
+ // POST part
+ roiFilter = ROIFilterType::New();
+ index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1;
+ size[1] = bones->GetLargestPossibleRegion().GetSize()[1] - size[1];
+ region.SetIndex(index);
+ region.SetSize(size);
+ roiFilter->SetInput(bones);
+ roiFilter->SetRegionOfInterest(region);
+ roiFilter->ReleaseDataFlagOff();
+ roiFilter->Update();
+ bones_post = roiFilter->GetOutput();
+ writeImage<MaskImageType>(bones_post, "b_post.mhd");
+
+ // Go !
+ relPosFilter->SetCurrentStepNumber(0);
+ relPosFilter->ResetPipeline();// = RelPosFilterType::New();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInput(output);
+ relPosFilter->SetInputObject(bones_post);
+ relPosFilter->SetOrientationType(RelPosFilterType::AntTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
+ relPosFilter->Update();
+ output = relPosFilter->GetOutput();
+ writeImage<MaskImageType>(output, "post.mhd");
+
+ relPosFilter->SetInput(relPosFilter->GetOutput());
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInput(output);
+ relPosFilter->SetInputObject(bones_ant);
+ relPosFilter->SetOrientationType(RelPosFilterType::PostTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
+ relPosFilter->Update();
+ output = relPosFilter->GetOutput();
+ this->template StopCurrentStep<MaskImageType>(output);
+ }
+
+ //--------------------------------------------------------------------
+ // Step 6: Get CCL
StartNewStep("Keep main connected component");
- output = clitk::Labelize<ImageType>(output, GetBackgroundValue(), true, 500);
- // output = RemoveLabels<ImageType>(output, BG, param->GetLabelsToRemove());
- output = clitk::KeepLabels<ImageType>(output, GetBackgroundValue(),
- GetForegroundValue(), 1, 1, 0);
- this->template StopCurrentStep<ImageType>(output);
-
- // Step : Lower limits from lung (need separate lung ?)
- StartNewStep("Lower limits with lungs");
- relPosFilter = RelPosFilterType::New();
- relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
- relPosFilter->VerboseStepOff();
- relPosFilter->WriteStepOff();
- relPosFilter->SetInput(output);
- DD(output->GetLargestPossibleRegion().GetIndex());
- // relPosFilter->SetInputObject(left_lung);
- relPosFilter->SetInputObject(lung);
- relPosFilter->SetOrientationType(RelPosFilterType::SupTo);
- relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
- relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold3());
- relPosFilter->Update();
- output = relPosFilter->GetOutput();
- DD(output->GetLargestPossibleRegion());
+ output = clitk::Labelize<MaskImageType>(output, GetBackgroundValue(), false, 500);
+ // output = RemoveLabels<MaskImageType>(output, BG, param->GetLabelsToRemove());
+ output = clitk::KeepLabels<MaskImageType>(output, GetBackgroundValue(),
+ GetForegroundValue(), 1, 1, 0);
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ //--------------------------------------------------------------------
+ // Step 7 : Slice by Slice to optimize posterior part
+ // Warning slice does not necesseraly correspond between 'output' and 'bones'
+ typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
+ typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
+ typedef typename ExtractSliceFilterType::SliceType SliceType;
+ std::vector<typename SliceType::Pointer> mSlices;
+ if (GetUseBones()) {
+ StartNewStep("Rafine posterior part according to vertebral body");
+ extractSliceFilter->SetInput(bones_post);
+ extractSliceFilter->SetDirection(2);
+ extractSliceFilter->Update();
+ std::vector<double> mVertebralAntPositionBySlice;
+ extractSliceFilter->GetOutputSlices(mSlices);
+ for(unsigned int i=0; i<mSlices.size(); i++) {
+ mSlices[i] = Labelize<SliceType>(mSlices[i], 0, true, 10);
+ mSlices[i] = KeepLabels<SliceType>(mSlices[i],
+ GetBackgroundValue(),
+ GetForegroundValue(), 1, 2, true); // keep two first
+ // Find most anterior point (start of the vertebral)
+ typename itk::ImageRegionIteratorWithIndex<SliceType>
+ iter(mSlices[i], mSlices[i]->GetLargestPossibleRegion());
+ iter.GoToBegin();
+ bool stop = false;
+ while (!stop) {
+ if (iter.Get() != GetBackgroundValue())
+ stop = true; // not foreground because we keep two main label
+ ++iter;
+ if (iter.IsAtEnd()) stop = true;
+ }
+ if (!iter.IsAtEnd()) {
+ typename SliceType::PointType p;
+ mSlices[i]->TransformIndexToPhysicalPoint(iter.GetIndex(),p);
+ mVertebralAntPositionBySlice.push_back(p[1]);
+ }
+ else {
+ mVertebralAntPositionBySlice.push_back(bones_post->GetOrigin()[1]+(bones->GetLargestPossibleRegion().GetSize()[1]*bones->GetSpacing()[1]));
+ DD(mVertebralAntPositionBySlice.back());
+ DD("ERROR ?? NO FG in bones here ?");
+ }
+ }
+
+ // Cut Post position slice by slice
+ {
+ MaskImageRegionType region;
+ MaskImageSizeType size;
+ MaskImageIndexType start;
+ size[2] = 1;
+ start[0] = output->GetLargestPossibleRegion().GetIndex()[0];
+ for(unsigned int i=0; i<mSlices.size(); i++) {
+ // Compute index
+ MaskImagePointType point;
+ point[0] = 0;
+
+ //TODO 10 mm OPTION
+
+ point[1] = mVertebralAntPositionBySlice[i]+GetDistanceMaxToAnteriorPartOfTheSpine();// ADD ONE CM
+ point[2] = bones_post->GetOrigin()[2]+(bones_post->GetLargestPossibleRegion().GetIndex()[2]+i)*bones_post->GetSpacing()[2];
+ MaskImageIndexType index;
+ output->TransformPhysicalPointToIndex(point, index);
+ // Compute region
+ start[2] = index[2];
+ start[1] = output->GetLargestPossibleRegion().GetIndex()[1]+index[1];
+ size[0] = output->GetLargestPossibleRegion().GetSize()[0];
+ size[1] = output->GetLargestPossibleRegion().GetSize()[1]-start[1];
+ region.SetSize(size);
+ region.SetIndex(start);
+ // Fill Region
+ if (output->GetLargestPossibleRegion().IsInside(start)) {
+ itk::ImageRegionIteratorWithIndex<MaskImageType> it(output, region);
+ it.GoToBegin();
+ while (!it.IsAtEnd()) {
+ it.Set(GetBackgroundValue());
+ ++it;
+ }
+ }
+ }
+ }
+ this->template StopCurrentStep<MaskImageType>(output);
+ }
+
+ //--------------------------------------------------------------------
+ // Step 8: Trial segmentation KMeans
+ if (0) {
+ StartNewStep("K means");
+ // Take input, crop like current mask
+ typedef CropLikeImageFilter<ImageType> CropLikeFilterType;
+ typename CropLikeFilterType::Pointer cropLikeFilter = CropLikeFilterType::New();
+ cropLikeFilter->SetInput(input);
+ cropLikeFilter->SetCropLikeImage(output);
+ cropLikeFilter->Update();
+ ImagePointer working_input = cropLikeFilter->GetOutput();
+ writeImage<ImageType>(working_input, "crop-input.mhd");
+ // Set bG at -1000
+ working_input = clitk::SetBackground<ImageType, MaskImageType>(working_input, output, GetBackgroundValue(), -1000);
+ writeImage<ImageType>(working_input, "crop-input2.mhd");
+ // Kmeans
+ typedef itk::ScalarImageKmeansImageFilter<ImageType> KMeansFilterType;
+ typename KMeansFilterType::Pointer kmeansFilter = KMeansFilterType::New();
+ kmeansFilter->SetInput(working_input);
+ // const unsigned int numberOfInitialClasses = 3;
+ // const unsigned int useNonContiguousLabels = 0;
+ kmeansFilter->AddClassWithInitialMean(-1000);
+ kmeansFilter->AddClassWithInitialMean(30);
+ kmeansFilter->AddClassWithInitialMean(-40); // ==> I want this one
+ DD("Go!");
+ kmeansFilter->Update();
+ DD("End");
+ typename KMeansFilterType::ParametersType estimatedMeans = kmeansFilter->GetFinalMeans();
+ const unsigned int numberOfClasses = estimatedMeans.Size();
+ for ( unsigned int i = 0 ; i < numberOfClasses ; ++i ) {
+ std::cout << "cluster[" << i << "] ";
+ std::cout << " estimated mean : " << estimatedMeans[i] << std::endl;
+ }
+ MaskImageType::Pointer kmeans = kmeansFilter->GetOutput();
+ kmeans = clitk::SetBackground<MaskImageType, MaskImageType>(kmeans, kmeans,
+ 1, GetBackgroundValue());
+ writeImage<MaskImageType>(kmeans, "kmeans.mhd");
+ // Get final results, and remove from current mask
+ boolFilter = BoolFilterType::New();
+ boolFilter->InPlaceOn();
+ boolFilter->SetInput1(output);
+ boolFilter->SetInput2(kmeans);
+ boolFilter->SetOperationType(BoolFilterType::And);
+ boolFilter->Update();
+ output = boolFilter->GetOutput();
+ writeImage<MaskImageType>(output, "out-kmean.mhd");
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ // TODO -> FillMASK ?
+ // comment speed ? mask ? 2 class ?
+
+
+ //TODO
+ // Confidence connected ?
+
+ }
+
+ //--------------------------------------------------------------------
+ // Step 8: Lower limits from lung (need separate lung ?)
+ if (1) {
+ // StartNewStep("Trial : minus segmented struct");
+ // MaskImagePointer heart = GetAFDB()->template GetImage <MaskImageType>("heart");
+ // boolFilter = BoolFilterType::New();
+ // boolFilter->InPlaceOn();
+ // boolFilter->SetInput1(output);
+ // boolFilter->SetInput2(heart);
+ // boolFilter->SetOperationType(BoolFilterType::AndNot);
+ // boolFilter->Update();
+ // output = boolFilter->GetOutput(); // not needed because InPlace
+
+ // Not below the heart
+ // relPosFilter = RelPosFilterType::New();
+ // relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ // relPosFilter->VerboseStepOff();
+ // relPosFilter->WriteStepOff();
+ // relPosFilter->SetInput(output);
+ // relPosFilter->SetInputObject(heart);
+ // relPosFilter->SetOrientationType(RelPosFilterType::SupTo);
+ // relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ // relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold3());
+ // relPosFilter->Update();
+ // output = relPosFilter->GetOutput();
+ }
+
+ //--------------------------------------------------------------------
+ // Step 8: Lower limits from lung (need separate lung ?)
+ if (0) {
+ StartNewStep("Lower limits with lungs");
+ // TODO BOFFF ????
+ relPosFilter = RelPosFilterType::New();
+ relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+ relPosFilter->VerboseStepOff();
+ relPosFilter->WriteStepOff();
+ relPosFilter->SetInput(output);
+ // relPosFilter->SetInputObject(left_lung);
+ relPosFilter->SetInputObject(lung);
+ relPosFilter->SetOrientationType(RelPosFilterType::SupTo);
+ relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
+ relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold3());
+ relPosFilter->Update();
+ output = relPosFilter->GetOutput();
+ this->template StopCurrentStep<MaskImageType>(output);
+ }
+
+ //--------------------------------------------------------------------
+ // Step 10: Slice by Slice CCL
+ StartNewStep("Slice by Slice keep only one component");
+ typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
+ // typename ExtractSliceFilterType::Pointer
+ extractSliceFilter = ExtractSliceFilterType::New();
+ extractSliceFilter->SetInput(output);
+ extractSliceFilter->SetDirection(2);
+ extractSliceFilter->Update();
+ typedef typename ExtractSliceFilterType::SliceType SliceType;
+ // std::vector<typename SliceType::Pointer>
+ mSlices.clear();
+ extractSliceFilter->GetOutputSlices(mSlices);
+ for(unsigned int i=0; i<mSlices.size(); i++) {
+ mSlices[i] = Labelize<SliceType>(mSlices[i], 0, true, 100);
+ mSlices[i] = KeepLabels<SliceType>(mSlices[i], 0, 1, 1, 1, true);
+ }
+ typedef itk::JoinSeriesImageFilter<SliceType, MaskImageType> JoinSeriesFilterType;
+ typename JoinSeriesFilterType::Pointer joinFilter = JoinSeriesFilterType::New();
+ joinFilter->SetOrigin(output->GetOrigin()[2]);
+ joinFilter->SetSpacing(output->GetSpacing()[2]);
+ for(unsigned int i=0; i<mSlices.size(); i++) {
+ joinFilter->PushBackInput(mSlices[i]);
+ }
+ joinFilter->Update();
+ output = joinFilter->GetOutput();
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ //--------------------------------------------------------------------
+ // Step 9: Binarize to remove too high HU
+ // --> warning CCL slice by slice must be done before
+ StartNewStep("Remove hypersignal (bones and injected part");
+ // Crop initial ct like current support
+ typedef CropLikeImageFilter<ImageType> CropLikeFilterType;
+ typename CropLikeFilterType::Pointer cropLikeFilter = CropLikeFilterType::New();
+ cropLikeFilter->SetInput(input);
+ cropLikeFilter->SetCropLikeImage(output);
+ cropLikeFilter->Update();
+ ImagePointer working_input = cropLikeFilter->GetOutput();
+ writeImage<ImageType>(working_input, "crop-ct.mhd");
+ // Binarize
+ typedef itk::BinaryThresholdImageFilter<ImageType, MaskImageType> InputBinarizeFilterType;
+ typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
+ binarizeFilter->SetInput(working_input);
+ binarizeFilter->SetLowerThreshold(GetLowerThreshold());
+ binarizeFilter->SetUpperThreshold(GetUpperThreshold());
+ binarizeFilter->SetInsideValue(this->GetBackgroundValue()); // opposite
+ binarizeFilter->SetOutsideValue(this->GetForegroundValue()); // opposite
+ binarizeFilter->Update();
+ MaskImagePointer working_bin = binarizeFilter->GetOutput();
+ writeImage<MaskImageType>(working_bin, "bin.mhd");
+ // Remove from support
+ boolFilter = BoolFilterType::New();
+ boolFilter->InPlaceOn();
+ boolFilter->SetInput1(output);
+ boolFilter->SetInput2(working_bin);
+ boolFilter->SetOperationType(BoolFilterType::AndNot);
+ boolFilter->Update();
+ output = boolFilter->GetOutput();
+ StopCurrentStep<MaskImageType>(output);
+
+ //--------------------------------------------------------------------
+ // Step 10 : AutoCrop
+ StartNewStep("AutoCrop");
+ output = clitk::AutoCrop<MaskImageType>(output, GetBackgroundValue());
+ this->template StopCurrentStep<MaskImageType>(output);
+
+ // Bones ? pb with RAM ? FillHoles ?
+
+ // how to do with post part ? spine /lung ?
+ // POST the spine (should be separated from the rest)
+ /// DO THAT ---->>
+ // histo Y on the whole bones_post (3D) -> result is the Y center on the spine (?)
+ // by slice on bones_post
+ // find the most ant point in the center
+ // from this point go to post until out of bones.
+ //
+
+
+ // End, set the real size
+ this->GetOutput(0)->SetRegions(output->GetLargestPossibleRegion());
+ this->GetOutput(0)->SetLargestPossibleRegion(output->GetLargestPossibleRegion());
+ this->GetOutput(0)->SetRequestedRegion(output->GetLargestPossibleRegion());
+ this->GetOutput(0)->SetBufferedRegion(output->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
- output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
- // roiFilter = ROIFilterType::New();
- //roiFilter->SetInput(output);
- //roiFilter->Update();
- //output = roiFilter->GetOutput();
- // Final Step -> set output
- this->SetNthOutput(0, output);
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractMediastinumFilter<ImageType>::
+GenerateData()
+{
+ DD("GenerateData");
+ this->GraftOutput(output);
+ // Store image filenames into AFDB
+ GetAFDB()->SetImageFilename("mediastinum", this->GetOutputMediastinumFilename());
+ WriteAFDB();
}
//--------------------------------------------------------------------
template<unsigned int Dim>
void clitk::ExtractMediastinumGenericFilter<ArgsInfoType>::InitializeImageType()
{
- ADD_IMAGE_TYPE(Dim, uchar);
+ ADD_IMAGE_TYPE(Dim, short);
// ADD_IMAGE_TYPE(Dim, short);
// ADD_IMAGE_TYPE(Dim, int);
// ADD_IMAGE_TYPE(Dim, float);
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.trachea_given) AddInputFilename(mArgsInfo.trachea_arg);
+ if (mArgsInfo.input_given) AddInputFilename(mArgsInfo.input_arg);
+ //if (mArgsInfo.patient_given) AddInputFilename(mArgsInfo.patient_arg);
+ //if (mArgsInfo.lung_given) AddInputFilename(mArgsInfo.lung_arg);
+ //if (mArgsInfo.bones_given) AddInputFilename(mArgsInfo.bones_arg);
+ //if (mArgsInfo.trachea_given) AddInputFilename(mArgsInfo.trachea_arg);
if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg);
}
//--------------------------------------------------------------------
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);
- typename ImageType::Pointer trachea = this->template GetInput<ImageType>(3);
+ typename ImageType::Pointer input = this->template GetInput<ImageType>(0);
+ // typename ImageType::Pointer patient = this->template GetInput<ImageType>(0);
+ // typename ImageType::Pointer lung = this->template GetInput<ImageType>(1);
+ // typename ImageType::Pointer bones = this->template GetInput<ImageType>(2);
+ // typename ImageType::Pointer trachea = this->template GetInput<ImageType>(3);
// Create filter
typedef clitk::ExtractMediastinumFilter<ImageType> FilterType;
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->SetInputTracheaLabelImage(trachea, mArgsInfo.tracheaBG_arg);
+ filter->SetInput(input);
+ // filter->SetInputPatientLabelImage(patient, mArgsInfo.patientBG_arg);
+ // filter->SetInputLungLabelImage(lung, mArgsInfo.lungBG_arg, mArgsInfo.lungRight_arg, mArgsInfo.lungLeft_arg);
+ // filter->SetInputBonesLabelImage(bones, mArgsInfo.bonesBG_arg);
+ filter->SetOutputMediastinumFilename(mArgsInfo.output_arg);
filter->SetArgsInfo(mArgsInfo);
// Go !
filter->Update();
// Write/Save results
- typename ImageType::Pointer output = filter->GetOutput();
- this->template SetNextOutput<ImageType>(output);
+ typename FilterType::MaskImageType::Pointer output = filter->GetOutput();
+ this->template SetNextOutput<typename FilterType::MaskImageType>(output);
}
//--------------------------------------------------------------------