]> Creatis software - clitk.git/blob - itk/clitkSegmentationUtils.txx
itkv4 Replace ITK_TYPENAME by typename
[clitk.git] / itk / clitkSegmentationUtils.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ======================================================================-====*/
18
19 // clitk
20 #include "clitkSetBackgroundImageFilter.h"
21 #include "clitkSliceBySliceRelativePositionFilter.h"
22 #include "clitkCropLikeImageFilter.h"
23 #include "clitkMemoryUsage.h"
24
25 // itk
26 #include <itkConnectedComponentImageFilter.h>
27 #include <itkRelabelComponentImageFilter.h>
28 #include <itkBinaryThresholdImageFilter.h>
29 #include <itkPasteImageFilter.h>
30 #include <itkStatisticsLabelMapFilter.h>
31 #include <itkBinaryBallStructuringElement.h>
32 #include <itkBinaryDilateImageFilter.h>
33 #include <itkConstantPadImageFilter.h>
34 #include <itkImageSliceIteratorWithIndex.h>
35 #include <itkBinaryMorphologicalOpeningImageFilter.h>
36 #include <itkImageDuplicator.h>
37
38 namespace clitk {
39
40   //--------------------------------------------------------------------
41   template<class ImageType>
42   void ComputeBBFromImageRegion(const ImageType * image, 
43                                 typename ImageType::RegionType region,
44                                 typename itk::BoundingBox<unsigned long, 
45                                 ImageType::ImageDimension>::Pointer bb) {
46     typedef typename ImageType::IndexType IndexType;
47     IndexType firstIndex;
48     IndexType lastIndex;
49     for(unsigned int i=0; i<image->GetImageDimension(); i++) {
50       firstIndex[i] = region.GetIndex()[i];
51       lastIndex[i] = firstIndex[i]+region.GetSize()[i];
52     }
53
54     typedef itk::BoundingBox<unsigned long, 
55                              ImageType::ImageDimension> BBType;
56     typedef typename BBType::PointType PointType;
57     PointType lastPoint;
58     PointType firstPoint;
59     image->TransformIndexToPhysicalPoint(firstIndex, firstPoint);
60     image->TransformIndexToPhysicalPoint(lastIndex, lastPoint);
61
62     bb->SetMaximum(lastPoint);
63     bb->SetMinimum(firstPoint);
64   }
65   //--------------------------------------------------------------------
66
67
68   //--------------------------------------------------------------------
69   template<int Dimension>
70   void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
71                              typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
72                              typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
73
74     typedef itk::BoundingBox<unsigned long, Dimension> BBType;
75     typedef typename BBType::PointType PointType;
76     PointType lastPoint;
77     PointType firstPoint;
78
79     for(unsigned int i=0; i<Dimension; i++) {
80       firstPoint[i] = std::max(bbi1->GetMinimum()[i], 
81                                bbi2->GetMinimum()[i]);
82       lastPoint[i] = std::min(bbi1->GetMaximum()[i], 
83                               bbi2->GetMaximum()[i]);
84     }
85
86     bbo->SetMaximum(lastPoint);
87     bbo->SetMinimum(firstPoint);
88   }
89   //--------------------------------------------------------------------
90
91
92   //--------------------------------------------------------------------
93   template<class ImageType>
94   void ComputeRegionFromBB(const ImageType * image, 
95                            const typename itk::BoundingBox<unsigned long, 
96                                                            ImageType::ImageDimension>::Pointer bb, 
97                            typename ImageType::RegionType & region) {
98     // Types
99     typedef typename ImageType::IndexType  IndexType;
100     typedef typename ImageType::PointType  PointType;
101     typedef typename ImageType::RegionType RegionType;
102     typedef typename ImageType::SizeType   SizeType;
103
104     // Region starting point
105     IndexType regionStart;
106     PointType start = bb->GetMinimum();
107     image->TransformPhysicalPointToIndex(start, regionStart);
108     
109     // Region size
110     SizeType regionSize;
111     PointType maxs = bb->GetMaximum();
112     PointType mins = bb->GetMinimum();
113     for(unsigned int i=0; i<ImageType::ImageDimension; i++) {
114       regionSize[i] = lrint((maxs[i] - mins[i])/image->GetSpacing()[i]);
115     }
116    
117     // Create region
118     region.SetIndex(regionStart);
119     region.SetSize(regionSize);
120   }
121   //--------------------------------------------------------------------
122
123   //--------------------------------------------------------------------
124   template<class ImageType, class TMaskImageType>
125   typename ImageType::Pointer
126   SetBackground(const ImageType * input, 
127                 const TMaskImageType * mask, 
128                 typename TMaskImageType::PixelType maskBG,
129                 typename ImageType::PixelType outValue, 
130                 bool inPlace) {
131     typedef SetBackgroundImageFilter<ImageType, TMaskImageType, ImageType> 
132       SetBackgroundImageFilterType;
133     typename SetBackgroundImageFilterType::Pointer setBackgroundFilter 
134       = SetBackgroundImageFilterType::New();
135     //  if (inPlace) setBackgroundFilter->ReleaseDataFlagOn(); // No seg fault
136     setBackgroundFilter->SetInPlace(inPlace); // This is important to keep memory low
137     setBackgroundFilter->SetInput(input);
138     setBackgroundFilter->SetInput2(mask);
139     setBackgroundFilter->SetMaskValue(maskBG);
140     setBackgroundFilter->SetOutsideValue(outValue);
141     setBackgroundFilter->Update();
142     return setBackgroundFilter->GetOutput();
143   }
144   //--------------------------------------------------------------------
145
146
147   //--------------------------------------------------------------------
148   template<class ImageType>
149   int GetNumberOfConnectedComponentLabels(const ImageType * input, 
150                                           typename ImageType::PixelType BG, 
151                                           bool isFullyConnected) {
152     // Connected Component label 
153     typedef itk::ConnectedComponentImageFilter<ImageType, ImageType> ConnectFilterType;
154     typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
155     connectFilter->SetInput(input);
156     connectFilter->SetBackgroundValue(BG);
157     connectFilter->SetFullyConnected(isFullyConnected);
158     connectFilter->Update();
159   
160     // Return result
161     return connectFilter->GetObjectCount();
162   }
163   //--------------------------------------------------------------------
164
165   //--------------------------------------------------------------------
166   /*
167     Warning : in this cas, we consider outputType like inputType, not
168     InternalImageType. Be sure it fits.
169   */
170   template<class ImageType>
171   typename ImageType::Pointer
172   Labelize(const ImageType * input, 
173            typename ImageType::PixelType BG, 
174            bool isFullyConnected, 
175            int minimalComponentSize) {
176     // InternalImageType for storing large number of component
177     typedef itk::Image<int, ImageType::ImageDimension> InternalImageType;
178   
179     // Connected Component label 
180     typedef itk::ConnectedComponentImageFilter<ImageType, InternalImageType> ConnectFilterType;
181     typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
182     //  connectFilter->ReleaseDataFlagOn(); 
183     connectFilter->SetInput(input);
184     connectFilter->SetBackgroundValue(BG);
185     connectFilter->SetFullyConnected(isFullyConnected);
186   
187     // Sort by size and remove too small area.
188     typedef itk::RelabelComponentImageFilter<InternalImageType, ImageType> RelabelFilterType;
189     typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
190     //  relabelFilter->ReleaseDataFlagOn(); // if yes, fail when ExplosionControlledThresholdConnectedImageFilter ???
191     relabelFilter->SetInput(connectFilter->GetOutput());
192     relabelFilter->SetMinimumObjectSize(minimalComponentSize);
193     relabelFilter->Update();
194
195     // Return result
196     typename ImageType::Pointer output = relabelFilter->GetOutput();
197     return output;
198   }
199   //--------------------------------------------------------------------
200
201
202   //--------------------------------------------------------------------
203   /*
204     Warning : in this cas, we consider outputType like inputType, not
205     InternalImageType. Be sure it fits.
206   */
207   template<class ImageType>
208   typename ImageType::Pointer
209   LabelizeAndCountNumberOfObjects(const ImageType * input, 
210                                   typename ImageType::PixelType BG, 
211                                   bool isFullyConnected, 
212                                   int minimalComponentSize, 
213                                   int & nb) {
214     // InternalImageType for storing large number of component
215     typedef itk::Image<int, ImageType::ImageDimension> InternalImageType;
216   
217     // Connected Component label 
218     typedef itk::ConnectedComponentImageFilter<ImageType, InternalImageType> ConnectFilterType;
219     typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
220     //  connectFilter->ReleaseDataFlagOn(); 
221     connectFilter->SetInput(input);
222     connectFilter->SetBackgroundValue(BG);
223     connectFilter->SetFullyConnected(isFullyConnected);
224   
225     // Sort by size and remove too small area.
226     typedef itk::RelabelComponentImageFilter<InternalImageType, ImageType> RelabelFilterType;
227     typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
228     //  relabelFilter->ReleaseDataFlagOn(); // if yes, fail when ExplosionControlledThresholdConnectedImageFilter ???
229     relabelFilter->SetInput(connectFilter->GetOutput());
230     relabelFilter->SetMinimumObjectSize(minimalComponentSize);
231     relabelFilter->Update();
232
233     nb = relabelFilter->GetNumberOfObjects();
234     // DD(relabelFilter->GetOriginalNumberOfObjects());
235     // DD(relabelFilter->GetSizeOfObjectsInPhysicalUnits()[0]);
236
237     // Return result
238     typename ImageType::Pointer output = relabelFilter->GetOutput();
239     return output;
240   }
241   //--------------------------------------------------------------------
242
243
244
245   //--------------------------------------------------------------------
246   template<class ImageType>
247   typename ImageType::Pointer
248   RemoveLabels(const ImageType * input, 
249                typename ImageType::PixelType BG,
250                std::vector<typename ImageType::PixelType> & labelsToRemove) {
251     assert(labelsToRemove.size() != 0);
252     typename ImageType::Pointer working_image;// = input;
253     for (unsigned int i=0; i <labelsToRemove.size(); i++) {
254       typedef SetBackgroundImageFilter<ImageType, ImageType> SetBackgroundImageFilterType;
255       typename SetBackgroundImageFilterType::Pointer setBackgroundFilter = SetBackgroundImageFilterType::New();
256       setBackgroundFilter->SetInput(input);
257       setBackgroundFilter->SetInput2(input);
258       setBackgroundFilter->SetMaskValue(labelsToRemove[i]);
259       setBackgroundFilter->SetOutsideValue(BG);
260       setBackgroundFilter->Update();
261       working_image = setBackgroundFilter->GetOutput();
262     }
263     return working_image;
264   }
265   //--------------------------------------------------------------------
266
267
268   //--------------------------------------------------------------------
269   template<class ImageType>
270   typename ImageType::Pointer
271   KeepLabels(const ImageType * input, 
272              typename ImageType::PixelType BG, 
273              typename ImageType::PixelType FG, 
274              typename ImageType::PixelType firstKeep, 
275              typename ImageType::PixelType lastKeep, 
276              bool useLastKeep) {
277     typedef itk::BinaryThresholdImageFilter<ImageType, ImageType> BinarizeFilterType; 
278     typename BinarizeFilterType::Pointer binarizeFilter = BinarizeFilterType::New();
279     binarizeFilter->SetInput(input);
280     binarizeFilter->SetLowerThreshold(firstKeep);
281     if (useLastKeep) binarizeFilter->SetUpperThreshold(lastKeep);
282     binarizeFilter->SetInsideValue(FG);
283     binarizeFilter->SetOutsideValue(BG);
284     binarizeFilter->Update();
285     return binarizeFilter->GetOutput();
286   }
287   //--------------------------------------------------------------------
288
289
290   //--------------------------------------------------------------------
291   template<class ImageType>
292   typename ImageType::Pointer
293   LabelizeAndSelectLabels(const ImageType * input,
294                           typename ImageType::PixelType BG, 
295                           typename ImageType::PixelType FG, 
296                           bool isFullyConnected,
297                           int minimalComponentSize,
298                           LabelizeParameters<typename ImageType::PixelType> * param)
299   {
300     typename ImageType::Pointer working_image;
301     working_image = Labelize<ImageType>(input, BG, isFullyConnected, minimalComponentSize);
302     if (param->GetLabelsToRemove().size() != 0)
303       working_image = RemoveLabels<ImageType>(working_image, BG, param->GetLabelsToRemove());
304     working_image = KeepLabels<ImageType>(working_image, 
305                                           BG, FG, 
306                                           param->GetFirstKeep(), 
307                                           param->GetLastKeep(), 
308                                           param->GetUseLastKeep());
309     return working_image;
310   }
311   //--------------------------------------------------------------------
312
313
314   //--------------------------------------------------------------------
315   template<class ImageType>
316   typename ImageType::Pointer
317   ResizeImageLike(const ImageType * input,                       
318                   const itk::ImageBase<ImageType::ImageDimension> * like, 
319                   typename ImageType::PixelType backgroundValue) 
320   {
321     typedef CropLikeImageFilter<ImageType> CropFilterType;
322     typename CropFilterType::Pointer cropFilter = CropFilterType::New();
323     cropFilter->SetInput(input);
324     cropFilter->SetCropLikeImage(like);
325     cropFilter->SetBackgroundValue(backgroundValue);
326     cropFilter->Update();
327     return cropFilter->GetOutput();  
328   }
329   //--------------------------------------------------------------------
330
331
332   //--------------------------------------------------------------------
333   template<class MaskImageType>
334   typename MaskImageType::Pointer
335   SliceBySliceRelativePosition(const MaskImageType * input,
336                                const MaskImageType * object,
337                                int direction, 
338                                double threshold, 
339                                std::string orientation, 
340                                bool uniqueConnectedComponent, 
341                                double spacing, 
342                                bool autocropFlag, 
343                                bool singleObjectCCL) 
344   {
345     typedef SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
346     typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
347     sliceRelPosFilter->VerboseStepFlagOff();
348     sliceRelPosFilter->WriteStepFlagOff();
349     sliceRelPosFilter->SetInput(input);
350     sliceRelPosFilter->SetInputObject(object);
351     sliceRelPosFilter->SetDirection(direction);
352     sliceRelPosFilter->SetFuzzyThreshold(threshold);
353     sliceRelPosFilter->AddOrientationTypeString(orientation);
354     sliceRelPosFilter->SetIntermediateSpacingFlag((spacing != -1));
355     sliceRelPosFilter->SetIntermediateSpacing(spacing);
356     sliceRelPosFilter->SetUniqueConnectedComponentBySlice(uniqueConnectedComponent);
357     sliceRelPosFilter->CCLSelectionFlagOff();
358     sliceRelPosFilter->SetUseASingleObjectConnectedComponentBySliceFlag(singleObjectCCL);
359     //    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
360     sliceRelPosFilter->SetAutoCropFlag(autocropFlag); 
361     sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
362     sliceRelPosFilter->Update();
363     return sliceRelPosFilter->GetOutput();
364   }
365   //--------------------------------------------------------------------
366
367   //--------------------------------------------------------------------
368   template<class ImageType>
369   bool
370   FindExtremaPointInAGivenDirection(const ImageType * input, 
371                                     typename ImageType::PixelType bg, 
372                                     int direction, bool opposite, 
373                                     typename ImageType::PointType & point)
374   {
375     typename ImageType::PointType dummy;
376     return FindExtremaPointInAGivenDirection(input, bg, direction, 
377                                              opposite, dummy, 0, point);
378   }
379   //--------------------------------------------------------------------
380
381   //--------------------------------------------------------------------
382   template<class ImageType>
383   bool
384   FindExtremaPointInAGivenDirection(const ImageType * input, 
385                                     typename ImageType::PixelType bg, 
386                                     int direction, bool opposite, 
387                                     typename ImageType::PointType refpoint,
388                                     double distanceMax, 
389                                     typename ImageType::PointType & point)
390   {
391     /*
392       loop over input pixels, store the index in the fg that is max
393       according to the given direction. 
394     */    
395     typedef itk::ImageRegionConstIteratorWithIndex<ImageType> IteratorType;
396     IteratorType iter(input, input->GetLargestPossibleRegion());
397     iter.GoToBegin();
398     typename ImageType::IndexType max = input->GetLargestPossibleRegion().GetIndex();
399     if (opposite) max = max+input->GetLargestPossibleRegion().GetSize();
400     bool found=false;
401     while (!iter.IsAtEnd()) {
402       if (iter.Get() != bg) {
403         bool test = iter.GetIndex()[direction] >  max[direction];
404         if (opposite) test = !test;
405         if (test) {
406           typename ImageType::PointType p;
407           input->TransformIndexToPhysicalPoint(iter.GetIndex(), p);
408           if ((distanceMax==0) || (p.EuclideanDistanceTo(refpoint) < distanceMax)) {
409             max = iter.GetIndex();
410             found = true;
411           }
412         }
413       }
414       ++iter;
415     }
416     if (!found) return false;
417     input->TransformIndexToPhysicalPoint(max, point);
418     return true;
419   }
420   //--------------------------------------------------------------------
421
422
423   //--------------------------------------------------------------------
424   template<class ImageType>
425   typename ImageType::Pointer
426   CropImageRemoveGreaterThan(const ImageType * image, 
427                  int dim, double min, bool autoCrop,
428                  typename ImageType::PixelType BG) 
429   {
430     return CropImageAlongOneAxis<ImageType>(image, dim, 
431                                             image->GetOrigin()[dim], 
432                                             min,
433                                             autoCrop, BG);
434   }
435   //--------------------------------------------------------------------
436
437
438   //--------------------------------------------------------------------
439   template<class ImageType>
440   typename ImageType::Pointer
441   CropImageRemoveLowerThan(const ImageType * image, 
442                  int dim, double max, bool autoCrop,
443                  typename ImageType::PixelType BG) 
444   {
445     typename ImageType::PointType p;
446     image->TransformIndexToPhysicalPoint(image->GetLargestPossibleRegion().GetIndex()+
447                                          image->GetLargestPossibleRegion().GetSize(), p);
448     return CropImageAlongOneAxis<ImageType>(image, dim, max, p[dim], autoCrop, BG);
449   }
450   //--------------------------------------------------------------------
451
452
453   //--------------------------------------------------------------------
454   template<class ImageType>
455   typename ImageType::Pointer
456   CropImageAlongOneAxis(const ImageType * image, 
457                         int dim, double min, double max, 
458                         bool autoCrop, typename ImageType::PixelType BG) 
459   {
460     // Compute region size
461     typename ImageType::RegionType region;
462     typename ImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();
463     typename ImageType::PointType p = image->GetOrigin();
464     p[dim] = min;
465     typename ImageType::IndexType start;
466     image->TransformPhysicalPointToIndex(p, start);
467     p[dim] = max;
468     typename ImageType::IndexType end;
469     image->TransformPhysicalPointToIndex(p, end);
470     size[dim] = abs(end[dim]-start[dim]);
471     region.SetIndex(start);
472     region.SetSize(size);
473   
474     // Perform Crop
475     typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
476     typename CropFilterType::Pointer cropFilter = CropFilterType::New();
477     cropFilter->SetInput(image);
478     cropFilter->SetRegionOfInterest(region);
479     cropFilter->Update();
480     typename ImageType::Pointer result = cropFilter->GetOutput();
481   
482     // Auto Crop
483     if (autoCrop) {
484       result = AutoCrop<ImageType>(result, BG);
485     }
486     return result;
487   }
488   //--------------------------------------------------------------------
489
490
491   //--------------------------------------------------------------------
492   template<class ImageType>
493   void
494   ComputeCentroids(const ImageType * image, 
495                    typename ImageType::PixelType BG, 
496                    std::vector<typename ImageType::PointType> & centroids) 
497   {
498     typedef long LabelType;
499     static const unsigned int Dim = ImageType::ImageDimension;
500     typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType;
501     typedef itk::LabelMap< LabelObjectType > LabelMapType;
502     typedef itk::LabelImageToLabelMapFilter<ImageType, LabelMapType> ImageToMapFilterType;
503     typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); 
504     typedef itk::ShapeLabelMapFilter<LabelMapType, ImageType> ShapeFilterType; 
505     typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New();
506     imageToLabelFilter->SetBackgroundValue(BG);
507     imageToLabelFilter->SetInput(image);
508     statFilter->SetInput(imageToLabelFilter->GetOutput());
509     statFilter->Update();
510     typename LabelMapType::Pointer labelMap = statFilter->GetOutput();
511
512     centroids.clear();
513     typename ImageType::PointType dummy;
514     centroids.push_back(dummy); // label 0 -> no centroid, use dummy point for BG 
515     //DS FIXME (not useful ! to change ..)
516     for(uint i=0; i<labelMap->GetNumberOfLabelObjects(); i++) {
517       int label = labelMap->GetLabels()[i];
518       centroids.push_back(labelMap->GetLabelObject(label)->GetCentroid());
519     } 
520   }
521   //--------------------------------------------------------------------
522
523
524   //--------------------------------------------------------------------
525   template<class ImageType, class LabelType>
526   typename itk::LabelMap< itk::ShapeLabelObject<LabelType, ImageType::ImageDimension> >::Pointer
527   ComputeLabelMap(const ImageType * image, 
528                   typename ImageType::PixelType BG, 
529                   bool computePerimeterFlag) 
530   {
531     static const unsigned int Dim = ImageType::ImageDimension;
532     typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType;
533     typedef itk::LabelMap< LabelObjectType > LabelMapType;
534     typedef itk::LabelImageToLabelMapFilter<ImageType, LabelMapType> ImageToMapFilterType;
535     typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); 
536     typedef itk::ShapeLabelMapFilter<LabelMapType, ImageType> ShapeFilterType; 
537     typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New();
538     imageToLabelFilter->SetBackgroundValue(BG);
539     imageToLabelFilter->SetInput(image);
540     statFilter->SetInput(imageToLabelFilter->GetOutput());
541     statFilter->SetComputePerimeter(computePerimeterFlag);
542     statFilter->Update();
543     return statFilter->GetOutput();
544   }
545   //--------------------------------------------------------------------
546
547
548   //--------------------------------------------------------------------
549   template<class ImageType>
550   void
551   ComputeCentroids2(const ImageType * image, 
552                    typename ImageType::PixelType BG, 
553                    std::vector<typename ImageType::PointType> & centroids) 
554   {
555     typedef long LabelType;
556     static const unsigned int Dim = ImageType::ImageDimension;
557     typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType;
558     typedef itk::LabelMap< LabelObjectType > LabelMapType;
559     typedef itk::LabelImageToLabelMapFilter<ImageType, LabelMapType> ImageToMapFilterType;
560     typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); 
561     typedef itk::ShapeLabelMapFilter<LabelMapType, ImageType> ShapeFilterType; 
562     typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New();
563     imageToLabelFilter->SetBackgroundValue(BG);
564     imageToLabelFilter->SetInput(image);
565     statFilter->SetInput(imageToLabelFilter->GetOutput());
566     statFilter->Update();
567     typename LabelMapType::Pointer labelMap = statFilter->GetOutput();
568
569     centroids.clear();
570     typename ImageType::PointType dummy;
571     centroids.push_back(dummy); // label 0 -> no centroid, use dummy point
572     for(uint i=1; i<labelMap->GetNumberOfLabelObjects()+1; i++) {
573       centroids.push_back(labelMap->GetLabelObject(i)->GetCentroid());
574     } 
575     
576     for(uint i=1; i<labelMap->GetNumberOfLabelObjects()+1; i++) {
577       DD(labelMap->GetLabelObject(i)->GetBinaryPrincipalAxes());
578       DD(labelMap->GetLabelObject(i)->GetBinaryFlatness());
579       DD(labelMap->GetLabelObject(i)->GetRoundness ());      
580
581       // search for the point on the boundary alog PA
582
583     }
584
585   }
586   //--------------------------------------------------------------------
587
588
589   //--------------------------------------------------------------------
590   template<class ImageType>
591   void
592   PointsUtils<ImageType>::Convert2DTo3D(const PointType2D & p2D, 
593                                         const ImageType * image, 
594                                         const int slice, 
595                                         PointType3D & p3D)  
596   {
597     IndexType3D index3D;
598     index3D[0] = index3D[1] = 0;
599     index3D[2] = image->GetLargestPossibleRegion().GetIndex()[2]+slice;
600     image->TransformIndexToPhysicalPoint(index3D, p3D);
601     p3D[0] = p2D[0]; 
602     p3D[1] = p2D[1];
603     //  p3D[2] = p[2];//(image->GetLargestPossibleRegion().GetIndex()[2]+slice)*image->GetSpacing()[2] 
604     //    + image->GetOrigin()[2];
605   }
606   //--------------------------------------------------------------------
607
608
609   //--------------------------------------------------------------------
610   template<class ImageType>
611   void 
612   PointsUtils<ImageType>::Convert2DMapTo3DList(const MapPoint2DType & map, 
613                                             const ImageType * image, 
614                                             VectorPoint3DType & list)
615   {
616     typename MapPoint2DType::const_iterator iter = map.begin();
617     while (iter != map.end()) {
618       PointType3D p;
619       Convert2DTo3D(iter->second, image, iter->first, p);
620       list.push_back(p);
621       ++iter;
622     }
623   }
624   //--------------------------------------------------------------------
625
626
627   //--------------------------------------------------------------------
628   template<class ImageType>
629   void 
630   PointsUtils<ImageType>::Convert2DListTo3DList(const VectorPoint2DType & p2D, 
631                                                 int slice,
632                                                 const ImageType * image, 
633                                                 VectorPoint3DType & list) 
634   {
635     for(uint i=0; i<p2D.size(); i++) {
636       PointType3D p;
637       Convert2DTo3D(p2D[i], image, slice, p);
638       list.push_back(p);
639     }
640   }
641   //--------------------------------------------------------------------
642
643
644   //--------------------------------------------------------------------
645   template<class ImageType>
646   void 
647   WriteListOfLandmarks(std::vector<typename ImageType::PointType> points, 
648                        std::string filename)
649   {
650     std::ofstream os; 
651     openFileForWriting(os, filename); 
652     os << "LANDMARKS1" << std::endl;  
653     for(uint i=0; i<points.size(); i++) {
654       const typename ImageType::PointType & p = points[i];
655       // Write it in the file
656       os << i << " " << p[0] << " " << p[1] << " " << p[2] << " 0 0 " << std::endl;
657     }
658     os.close();
659   }
660   //--------------------------------------------------------------------
661
662
663   //--------------------------------------------------------------------
664   template<class ImageType>
665   typename ImageType::Pointer 
666   Dilate(const ImageType * image, double radiusInMM,               
667          typename ImageType::PixelType BG,
668          typename ImageType::PixelType FG,  
669          bool extendSupport)
670   {
671     typename ImageType::SizeType r;
672     for(uint i=0; i<ImageType::ImageDimension; i++) 
673       r[i] = (uint)lrint(radiusInMM/image->GetSpacing()[i]);
674     return Dilate<ImageType>(image, r, BG, FG, extendSupport);
675   }
676   //--------------------------------------------------------------------
677
678
679   //--------------------------------------------------------------------
680   template<class ImageType>
681   typename ImageType::Pointer 
682   Dilate(const ImageType * image, typename ImageType::PointType radiusInMM, 
683          typename ImageType::PixelType BG, 
684          typename ImageType::PixelType FG, 
685          bool extendSupport)
686   {
687     typename ImageType::SizeType r;
688     for(uint i=0; i<ImageType::ImageDimension; i++) 
689       r[i] = (uint)lrint(radiusInMM[i]/image->GetSpacing()[i]);
690     return Dilate<ImageType>(image, r, BG, FG, extendSupport);
691   }
692   //--------------------------------------------------------------------
693
694
695   //--------------------------------------------------------------------
696   template<class ImageType>
697   typename ImageType::Pointer 
698   Dilate(const ImageType * image, typename ImageType::SizeType radius, 
699          typename ImageType::PixelType BG, 
700          typename ImageType::PixelType FG, 
701          bool extendSupport)
702   {
703     // Create kernel for dilatation
704     typedef itk::BinaryBallStructuringElement<typename ImageType::PixelType, 
705                                               ImageType::ImageDimension> KernelType;
706     KernelType structuringElement;
707     structuringElement.SetRadius(radius);
708     structuringElement.CreateStructuringElement();
709
710     typename ImageType::Pointer output;
711     if (extendSupport) {
712       typedef itk::ConstantPadImageFilter<ImageType, ImageType> PadFilterType;
713       typename PadFilterType::Pointer padFilter = PadFilterType::New();
714       padFilter->SetInput(image);
715       typename ImageType::SizeType lower;
716       typename ImageType::SizeType upper;
717       for(uint i=0; i<3; i++) {
718         lower[i] = upper[i] = 2*(radius[i]+1);
719       }
720       padFilter->SetPadLowerBound(lower);
721       padFilter->SetPadUpperBound(upper);
722       padFilter->Update();
723       output = padFilter->GetOutput();
724     }
725
726     // Dilate  filter
727     typedef itk::BinaryDilateImageFilter<ImageType, ImageType , KernelType> DilateFilterType;
728     typename DilateFilterType::Pointer dilateFilter = DilateFilterType::New();
729     dilateFilter->SetBackgroundValue(BG);
730     dilateFilter->SetForegroundValue(FG);
731     dilateFilter->SetBoundaryToForeground(false);
732     dilateFilter->SetKernel(structuringElement);
733     if (extendSupport) dilateFilter->SetInput(output);
734     else dilateFilter->SetInput(image);
735     dilateFilter->Update();
736     return dilateFilter->GetOutput();
737   }
738   //--------------------------------------------------------------------
739
740
741   //--------------------------------------------------------------------
742   template<class ImageType>
743   typename ImageType::Pointer 
744   Opening(const ImageType * image, typename ImageType::SizeType radius,
745          typename ImageType::PixelType BG,
746          typename ImageType::PixelType FG)
747   {
748     // Kernel 
749     typedef itk::BinaryBallStructuringElement<typename ImageType::PixelType, 
750                                               ImageType::ImageDimension> KernelType;    
751     KernelType structuringElement;
752     structuringElement.SetRadius(radius);
753     structuringElement.CreateStructuringElement();
754     
755     // Filter
756     typedef itk::BinaryMorphologicalOpeningImageFilter<ImageType, ImageType , KernelType> OpeningFilterType;
757     typename OpeningFilterType::Pointer open = OpeningFilterType::New();
758     open->SetInput(image);
759     open->SetBackgroundValue(BG);
760     open->SetForegroundValue(FG);
761     open->SetKernel(structuringElement);
762     open->Update();
763     return open->GetOutput();
764   }
765   //--------------------------------------------------------------------
766
767
768
769   //--------------------------------------------------------------------
770   template<class ValueType, class VectorType>
771   void ConvertOption(std::string optionName, uint given, 
772                      ValueType * values, VectorType & p, 
773                      uint dim, bool required) 
774   {
775     if (required && (given == 0)) {
776       clitkExceptionMacro("The option --" << optionName << " must be set and have 1 or " 
777                           << dim << " values.");
778     }
779     if (given == 1) {
780       for(uint i=0; i<dim; i++) p[i] = values[0];
781       return;
782     }
783     if (given == dim) {
784       for(uint i=0; i<dim; i++) p[i] = values[i];
785       return;
786     }
787     if (given == 0) return;
788     clitkExceptionMacro("The option --" << optionName << " must have 1 or " 
789                         << dim << " values.");
790   }
791   //--------------------------------------------------------------------
792
793
794   //--------------------------------------------------------------------
795   /*
796     http://www.gamedev.net/community/forums/topic.asp?topic_id=542870
797     Assuming the points are (Ax,Ay) (Bx,By) and (Cx,Cy), you need to compute:
798     (Bx - Ax) * (Cy - Ay) - (By - Ay) * (Cx - Ax)
799     This will equal zero if the point C is on the line formed by
800     points A and B, and will have a different sign depending on the
801     side. Which side this is depends on the orientation of your (x,y)
802     coordinates, but you can plug test values for A,B and C into this
803     formula to determine whether negative values are to the left or to
804     the right.
805     => to accelerate, start with formula, when change sign -> stop and fill
806
807     offsetToKeep = is used to determine which side of the line we
808     keep. The point along the mainDirection but 'offsetToKeep' mm away
809     is kept.
810   
811   */
812   template<class ImageType>
813   void 
814   SliceBySliceSetBackgroundFromLineSeparation(ImageType * input, 
815                                               std::vector<typename ImageType::PointType> & lA, 
816                                               std::vector<typename ImageType::PointType> & lB, 
817                                               typename ImageType::PixelType BG, 
818                                               int mainDirection, 
819                                               double offsetToKeep)
820   {
821     typedef itk::ImageSliceIteratorWithIndex<ImageType> SliceIteratorType;
822     SliceIteratorType siter = SliceIteratorType(input, 
823                                                 input->GetLargestPossibleRegion());
824     siter.SetFirstDirection(0);
825     siter.SetSecondDirection(1);
826     siter.GoToBegin();
827     uint i=0;
828     typename ImageType::PointType A;
829     typename ImageType::PointType B;
830     typename ImageType::PointType C;
831     assert(lA.size() == lB.size());
832     while ((i<lA.size()) && (!siter.IsAtEnd())) {
833       // Check that the current slice correspond to the current point
834       input->TransformIndexToPhysicalPoint(siter.GetIndex(), C);
835       if ((fabs(C[2] - lA[i][2]))>0.01) { // is !equal with a tolerance of 0.01 mm
836       }
837       else {
838         // Define A,B,C points
839         A = lA[i];
840         B = lB[i];
841         C = A;
842       
843         // Check that the line is not a point (A=B)
844         bool p = (A[0] == B[0]) && (A[1] == B[1]);
845       
846         if (!p) {
847           C[mainDirection] += offsetToKeep; // I know I must keep this point
848           double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
849           bool isPositive = s<0;
850           while (!siter.IsAtEndOfSlice()) {
851             while (!siter.IsAtEndOfLine()) {
852               // Very slow, I know ... but image should be very small
853               input->TransformIndexToPhysicalPoint(siter.GetIndex(), C);
854               double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
855               if (s == 0) siter.Set(BG); // on the line, we decide to remove
856               if (isPositive) {
857                 if (s > 0) siter.Set(BG);
858               }
859               else {
860                 if (s < 0) siter.Set(BG); 
861               }
862               ++siter;
863             }
864             siter.NextLine();
865           } // end loop slice
866         }      
867
868         ++i;
869       } // End of current slice
870       siter.NextSlice();
871     }
872   }                                                   
873   //--------------------------------------------------------------------
874
875
876   //--------------------------------------------------------------------
877   template<class ImageType>
878   void 
879   AndNot(ImageType * input, 
880          const ImageType * object, 
881          typename ImageType::PixelType BG)
882   {
883     typename ImageType::Pointer o;
884     bool resized=false;
885     if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(input, object)) {
886       o = clitk::ResizeImageLike<ImageType>(object, input, BG);
887       resized = true;
888     }
889
890     typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
891     typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
892     boolFilter->InPlaceOn();
893     boolFilter->SetInput1(input);
894     if (resized) boolFilter->SetInput2(o);  
895     else boolFilter->SetInput2(object);
896     boolFilter->SetBackgroundValue1(BG);
897     boolFilter->SetBackgroundValue2(BG);
898     boolFilter->SetOperationType(BoolFilterType::AndNot);
899     boolFilter->Update();
900   }
901   //--------------------------------------------------------------------
902
903
904   //--------------------------------------------------------------------
905   template<class ImageType>
906   void 
907   And(ImageType * input, 
908       const ImageType * object, 
909       typename ImageType::PixelType BG)
910   {
911     typename ImageType::Pointer o;
912     bool resized=false;
913     if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(input, object)) {
914       o = clitk::ResizeImageLike<ImageType>(object, input, BG);
915       resized = true;
916     }
917
918     typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
919     typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
920     boolFilter->InPlaceOn();
921     boolFilter->SetInput1(input);
922     if (resized) boolFilter->SetInput2(o);  
923     else boolFilter->SetInput2(object);
924     boolFilter->SetBackgroundValue1(BG);
925     boolFilter->SetBackgroundValue2(BG);
926     boolFilter->SetOperationType(BoolFilterType::And);
927     boolFilter->Update();
928   }
929   //--------------------------------------------------------------------
930
931
932   //--------------------------------------------------------------------
933   template<class ImageType>
934   typename ImageType::Pointer
935   Binarize(const ImageType * input, 
936            typename ImageType::PixelType lower, 
937            typename ImageType::PixelType upper, 
938            typename ImageType::PixelType BG,
939            typename ImageType::PixelType FG) 
940   {
941     typedef itk::BinaryThresholdImageFilter<ImageType, ImageType> BinaryThresholdFilterType;
942     typename BinaryThresholdFilterType::Pointer binarizeFilter = BinaryThresholdFilterType::New();
943     binarizeFilter->SetInput(input);
944     binarizeFilter->InPlaceOff();
945     binarizeFilter->SetLowerThreshold(lower);
946     binarizeFilter->SetUpperThreshold(upper);
947     binarizeFilter->SetInsideValue(FG);
948     binarizeFilter->SetOutsideValue(BG);
949     binarizeFilter->Update();
950     return binarizeFilter->GetOutput();
951   }
952   //--------------------------------------------------------------------
953
954
955   //--------------------------------------------------------------------
956   template<class ImageType>
957   void
958   GetMinMaxPointPosition(const ImageType * input, 
959                          typename ImageType::PointType & min,
960                          typename ImageType::PointType & max) 
961   {
962     typename ImageType::IndexType index = input->GetLargestPossibleRegion().GetIndex();
963     input->TransformIndexToPhysicalPoint(index, min);
964     index = index+input->GetLargestPossibleRegion().GetSize();
965     input->TransformIndexToPhysicalPoint(index, max);
966   }
967   //--------------------------------------------------------------------
968
969
970   //--------------------------------------------------------------------
971   template<class ImageType>
972   typename ImageType::PointType
973   FindExtremaPointInAGivenLine(const ImageType * input, 
974                                int dimension, 
975                                bool inverse, 
976                                typename ImageType::PointType p, 
977                                typename ImageType::PixelType BG, 
978                                double distanceMax) 
979   {
980     // Which direction ?  Increasing or decreasing.
981     int d=1;
982     if (inverse) d=-1;
983   
984     // Transform to pixel index
985     typename ImageType::IndexType index;
986     input->TransformPhysicalPointToIndex(p, index);
987
988     // Loop while inside the mask;
989     while (input->GetPixel(index) != BG) {
990       index[dimension] += d;
991     }
992
993     // Transform back to Physical Units
994     typename ImageType::PointType result;
995     input->TransformIndexToPhysicalPoint(index, result);
996
997     // Check that is is not too far away
998     double distance = p.EuclideanDistanceTo(result);
999     if (distance > distanceMax) {
1000       result = p; // Get back to initial value
1001     }
1002
1003     return result;
1004   }
1005   //--------------------------------------------------------------------
1006
1007
1008   //--------------------------------------------------------------------
1009   template<class PointType>
1010   bool
1011   IsOnTheSameLineSide(PointType C, PointType A, PointType B, PointType like) 
1012   {
1013     // Look at the position of point 'like' according to the AB line
1014     double s = (B[0] - A[0]) * (like[1] - A[1]) - (B[1] - A[1]) * (like[0] - A[0]);
1015     bool negative = s<0;
1016   
1017     // Look the C position
1018     s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
1019
1020     if (negative && (s<=0)) return true;
1021     if (!negative && (s>=0)) return true;
1022     return false;
1023   }
1024   //--------------------------------------------------------------------
1025
1026
1027   //--------------------------------------------------------------------
1028   /* Consider an input object, for each slice, find the extrema
1029      position according to a given direction and build a line segment
1030      passing throught this point in a given direction.  Output is a
1031      vector of line (from point A to B), for each slice;
1032    */
1033   template<class ImageType>
1034   void 
1035   SliceBySliceBuildLineSegmentAccordingToExtremaPosition(const ImageType * input, 
1036                                                          typename ImageType::PixelType BG, 
1037                                                          int sliceDimension, 
1038                                                          int extremaDirection, 
1039                                                          bool extremaOppositeFlag, 
1040                                                          int lineDirection,
1041                                                          double margin,
1042                                                          std::vector<typename ImageType::PointType> & A, 
1043                                                          std::vector<typename ImageType::PointType> & B)
1044   {
1045     // Type of a slice
1046     typedef typename itk::Image<typename ImageType::PixelType, ImageType::ImageDimension-1> SliceType;
1047     
1048     // Build the list of slices
1049     std::vector<typename SliceType::Pointer> slices;
1050     clitk::ExtractSlices<ImageType>(input, sliceDimension, slices);
1051
1052     // Build the list of 2D points
1053     std::map<int, typename SliceType::PointType> position2D;
1054     for(uint i=0; i<slices.size(); i++) {
1055       typename SliceType::PointType p;
1056       bool found = 
1057         clitk::FindExtremaPointInAGivenDirection<SliceType>(slices[i], BG, 
1058                                                             extremaDirection, extremaOppositeFlag, p);
1059       if (found) {
1060         position2D[i] = p;
1061       }
1062     }
1063     
1064     // Convert 2D points in slice into 3D points
1065     clitk::PointsUtils<ImageType>::Convert2DMapTo3DList(position2D, input, A);
1066     
1067     // Create additional point just right to the previous ones, on the
1068     // given lineDirection, in order to create a horizontal/vertical line.
1069     for(uint i=0; i<A.size(); i++) {
1070       typename ImageType::PointType p = A[i];
1071       p[lineDirection] += 10;
1072       B.push_back(p);
1073       // Margins ?
1074       A[i][extremaDirection] += margin;
1075       B[i][extremaDirection] += margin;
1076     }
1077
1078   }
1079   //--------------------------------------------------------------------
1080
1081
1082   //--------------------------------------------------------------------
1083   template<class ImageType>
1084   typename ImageType::Pointer
1085   SliceBySliceKeepMainCCL(const ImageType * input, 
1086                           typename ImageType::PixelType BG,
1087                           typename ImageType::PixelType FG)  {
1088     
1089     // Extract slices
1090     const int d = ImageType::ImageDimension-1;
1091     typedef typename itk::Image<typename ImageType::PixelType, d> SliceType;
1092     std::vector<typename SliceType::Pointer> slices;
1093     clitk::ExtractSlices<ImageType>(input, d, slices);
1094     
1095     // Labelize and keep the main one
1096     std::vector<typename SliceType::Pointer> o;
1097     for(uint i=0; i<slices.size(); i++) {
1098       o.push_back(clitk::Labelize<SliceType>(slices[i], BG, false, 1));
1099       o[i] = clitk::KeepLabels<SliceType>(o[i], BG, FG, 1, 1, true);
1100     }
1101     
1102     // Join slices
1103     typename ImageType::Pointer output;
1104     output = clitk::JoinSlices<ImageType>(o, input, d);
1105     return output;
1106   }
1107   //--------------------------------------------------------------------
1108
1109
1110   //--------------------------------------------------------------------
1111   template<class ImageType>
1112   typename ImageType::Pointer
1113   Clone(const ImageType * input) {
1114     typedef itk::ImageDuplicator<ImageType> DuplicatorType;
1115     typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
1116     duplicator->SetInputImage(input);
1117     duplicator->Update();
1118     return duplicator->GetOutput();
1119   }
1120   //--------------------------------------------------------------------
1121
1122
1123   //--------------------------------------------------------------------
1124   /* Consider an input object, start at A, for each slice (dim1): 
1125      - compute the intersection between the AB line and the current slice
1126      - remove what is at lower or greater according to dim2 of this point
1127      - stop at B
1128   */
1129   template<class ImageType>
1130   typename ImageType::Pointer
1131   SliceBySliceSetBackgroundFromSingleLine(const ImageType * input, 
1132                                           typename ImageType::PixelType BG, 
1133                                           typename ImageType::PointType & A, 
1134                                           typename ImageType::PointType & B, 
1135                                           int dim1, int dim2, bool removeLowerPartFlag)
1136     
1137   {
1138     // Extract slices
1139     typedef typename itk::Image<typename ImageType::PixelType, ImageType::ImageDimension-1> SliceType;
1140     typedef typename SliceType::Pointer SlicePointer;
1141     std::vector<SlicePointer> slices;
1142     clitk::ExtractSlices<ImageType>(input, dim1, slices);
1143
1144     // Start at slice that contains A, and stop at B
1145     typename ImageType::IndexType Ap;
1146     typename ImageType::IndexType Bp;
1147     input->TransformPhysicalPointToIndex(A, Ap);
1148     input->TransformPhysicalPointToIndex(B, Bp);
1149     
1150     // Determine slice largest region
1151     typename SliceType::RegionType region = slices[0]->GetLargestPossibleRegion();
1152     typename SliceType::SizeType size = region.GetSize();
1153     typename SliceType::IndexType index = region.GetIndex();
1154
1155     // Line slope
1156     double a = (Bp[dim2]-Ap[dim2])/(Bp[dim1]-Ap[dim1]);
1157     double b = Ap[dim2];
1158
1159     // Loop from slice A to slice B
1160     for(uint i=0; i<(Bp[dim1]-Ap[dim1]); i++) {
1161       // Compute intersection between line AB and current slice for the dim2
1162       double p = a*i+b;
1163       // Change region (lower than dim2)
1164       if (removeLowerPartFlag) {
1165         size[dim2] = p-Ap[dim2];
1166       }
1167       else {
1168         size[dim2] = slices[0]->GetLargestPossibleRegion().GetSize()[dim2]-p;
1169         index[dim2] = p;
1170       }
1171       region.SetSize(size);
1172       region.SetIndex(index);
1173       // Fill region with BG (simple region iterator)
1174       FillRegionWithValue<SliceType>(slices[i+Ap[dim1]], BG, region);
1175       /*
1176       typedef itk::ImageRegionIterator<SliceType> IteratorType;
1177       IteratorType iter(slices[i+Ap[dim1]], region);
1178       iter.GoToBegin();
1179       while (!iter.IsAtEnd()) {
1180         iter.Set(BG);
1181         ++iter;
1182       }
1183       */
1184       // Loop
1185     }
1186     
1187     // Merge slices
1188     typename ImageType::Pointer output;
1189     output = clitk::JoinSlices<ImageType>(slices, input, dim1);
1190     return output;
1191   }
1192   //--------------------------------------------------------------------
1193
1194   //--------------------------------------------------------------------
1195   /* Consider an input object, slice by slice, use the point A and set
1196      pixel to BG according to their position relatively to A
1197   */
1198   template<class ImageType>
1199   typename ImageType::Pointer
1200   SliceBySliceSetBackgroundFromPoints(const ImageType * input, 
1201                                       typename ImageType::PixelType BG, 
1202                                       int sliceDim,
1203                                       std::vector<typename ImageType::PointType> & A, 
1204                                       bool removeGreaterThanXFlag,
1205                                       bool removeGreaterThanYFlag)
1206     
1207   {
1208     // Extract slices
1209     typedef typename itk::Image<typename ImageType::PixelType, ImageType::ImageDimension-1> SliceType;
1210     typedef typename SliceType::Pointer SlicePointer;
1211     std::vector<SlicePointer> slices;
1212     clitk::ExtractSlices<ImageType>(input, sliceDim, slices);
1213
1214     // Start at slice that contains A
1215     typename ImageType::IndexType Ap;
1216     
1217     // Determine slice largest region
1218     typename SliceType::RegionType region = slices[0]->GetLargestPossibleRegion();
1219     typename SliceType::SizeType size = region.GetSize();
1220     typename SliceType::IndexType index = region.GetIndex();
1221
1222     // Loop from slice A to slice B
1223     for(uint i=0; i<A.size(); i++) {
1224       input->TransformPhysicalPointToIndex(A[i], Ap);
1225       uint sliceIndex = Ap[2] - input->GetLargestPossibleRegion().GetIndex()[2];
1226       if ((sliceIndex < 0) || (sliceIndex >= slices.size())) {
1227         continue; // do not consider this slice
1228       }
1229       
1230       // Compute region for BG
1231       if (removeGreaterThanXFlag) {
1232         index[0] = Ap[0];
1233         size[0] = region.GetSize()[0]-(index[0]-region.GetIndex()[0]);
1234       }
1235       else {
1236         index[0] = region.GetIndex()[0];
1237         size[0] = Ap[0] - index[0];
1238       }
1239
1240       if (removeGreaterThanYFlag) {
1241         index[1] = Ap[1];
1242         size[1] = region.GetSize()[1]-(index[1]-region.GetIndex()[1]);
1243       }
1244       else {
1245         index[1] = region.GetIndex()[1];
1246         size[1] = Ap[1] - index[1];
1247       }
1248
1249       // Set region
1250       region.SetSize(size);
1251       region.SetIndex(index);
1252
1253       // Fill region with BG (simple region iterator)
1254       FillRegionWithValue<SliceType>(slices[sliceIndex], BG, region);
1255       // Loop
1256     }
1257     
1258     // Merge slices
1259     typename ImageType::Pointer output;
1260     output = clitk::JoinSlices<ImageType>(slices, input, sliceDim);
1261     return output;
1262   }
1263   //--------------------------------------------------------------------
1264
1265
1266   //--------------------------------------------------------------------
1267   template<class ImageType>
1268   void
1269   FillRegionWithValue(ImageType * input, typename ImageType::PixelType value, typename ImageType::RegionType & region)
1270   {
1271     typedef itk::ImageRegionIterator<ImageType> IteratorType;
1272     IteratorType iter(input, region);
1273     iter.GoToBegin();
1274     while (!iter.IsAtEnd()) {
1275       iter.Set(value);
1276       ++iter;
1277     }    
1278   }
1279   //--------------------------------------------------------------------
1280
1281
1282   //--------------------------------------------------------------------
1283   template<class ImageType>
1284   void
1285   GetMinMaxBoundary(ImageType * input, typename ImageType::PointType & min, 
1286                     typename ImageType::PointType & max)
1287   {
1288     typedef typename ImageType::PointType PointType;
1289     typedef typename ImageType::IndexType IndexType;
1290     IndexType min_i, max_i;
1291     min_i = input->GetLargestPossibleRegion().GetIndex();
1292     for(uint i=0; i<ImageType::ImageDimension; i++)
1293       max_i[i] = input->GetLargestPossibleRegion().GetSize()[i] + min_i[i];
1294     input->TransformIndexToPhysicalPoint(min_i, min);
1295     input->TransformIndexToPhysicalPoint(max_i, max);  
1296   }
1297   //--------------------------------------------------------------------
1298
1299 } // end of namespace
1300