00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __itkWatershedSegmenter_h
00018 #define __itkWatershedSegmenter_h
00019
00020 #if defined(_MSC_VER)
00021 #pragma warning ( disable : 4786 )
00022 #endif
00023
00024 #include "itk_hash_map.h"
00025 #include "itkWatershedBoundary.h"
00026 #include "itkWatershedSegmentTable.h"
00027 #include "itkEquivalencyTable.h"
00028 #include "itkImage.h"
00029
00030 namespace itk
00031 {
00032 namespace watershed
00033 {
00089 template <class TInputImage>
00090 class ITK_EXPORT Segmenter
00091 : public ProcessObject
00092 {
00093 public:
00095 typedef Segmenter Self;
00096
00098 typedef TInputImage InputImageType;
00099 itkStaticConstMacro(ImageDimension, unsigned int,
00100 TInputImage::ImageDimension);
00101
00102 typedef Image<unsigned long, itkGetStaticConstMacro(ImageDimension)>
00103 OutputImageType;
00104 typedef typename InputImageType::RegionType ImageRegionType;
00105 typedef typename InputImageType::PixelType InputPixelType;
00106 typedef Boundary<InputPixelType, itkGetStaticConstMacro(ImageDimension)>
00107 BoundaryType;
00108 typedef typename BoundaryType::IndexType BoundaryIndexType;
00109 typedef typename BoundaryType::FlatHashValueType BoundaryFlatHashValueType;
00110 typedef SegmentTable<InputPixelType> SegmentTableType;
00111 typedef DataObject::Pointer DataObjectPointer;
00112
00115 typedef ProcessObject Superclass;
00116 typedef SmartPointer<Self> Pointer;
00117 typedef SmartPointer<const Self> ConstPointer;
00118 itkNewMacro(Self);
00119 itkTypeMacro(WatershedSegmenter, ProcessObject);
00121
00123 typedef typename InputImageType::Pointer InputImageTypePointer;
00124 typedef typename OutputImageType::Pointer OutputImageTypePointer;
00125 typedef typename SegmentTableType::Pointer SegmentTableTypePointer;
00126 typedef typename BoundaryType::Pointer BoundaryTypePointer;
00127
00129 static unsigned long NULL_LABEL;
00130
00132 static short NULL_FLOW;
00133
00135 InputImageType * GetInputImage(void)
00136 {
00137 return static_cast<InputImageType *>
00138 (this->ProcessObject::GetInput(0));
00139 }
00140 void SetInputImage(InputImageType *img)
00141 { this->ProcessObject::SetNthInput(0, img); }
00143
00146 OutputImageType * GetOutputImage(void)
00147 {
00148 return static_cast<OutputImageType *>
00149 (this->ProcessObject::GetOutput(0));
00150 }
00151 void SetOutputImage(OutputImageType *img)
00152 { this->ProcessObject::SetNthOutput(0, img); }
00154
00157 SegmentTableType * GetSegmentTable(void)
00158 {
00159 return static_cast<SegmentTableType *>
00160 (this->ProcessObject::GetOutput(1));
00161 }
00162 void SetSegmentTable(SegmentTableType *s)
00163 { this->ProcessObject::SetNthOutput(1, s); }
00165
00168 BoundaryType * GetBoundary(void)
00169 {
00170 return static_cast<BoundaryType *>
00171 (this->ProcessObject::GetOutput(2));
00172 }
00173 void SetBoundary(BoundaryType *b)
00174 { this->ProcessObject::SetNthOutput(2,b); }
00176
00178 void GenerateData();
00179
00186 void SetLargestPossibleRegion(ImageRegionType reg)
00187 {
00188 if (reg == m_LargestPossibleRegion) return;
00189 m_LargestPossibleRegion = reg;
00190 this->Modified();
00191 }
00192 ImageRegionType GetLargestPossibleRegion() const
00193 { return m_LargestPossibleRegion; }
00195
00198 static void RelabelImage(OutputImageTypePointer,
00199 ImageRegionType,
00200 EquivalencyTable::Pointer);
00201
00203 virtual DataObjectPointer MakeOutput(unsigned int idx);
00204
00207 itkSetMacro(CurrentLabel, unsigned long);
00208 itkGetConstMacro(CurrentLabel, unsigned long);
00210
00221 itkSetClampMacro(Threshold, double, 0.0, 1.0);
00222 itkGetConstMacro(Threshold, double);
00224
00228 itkSetMacro(DoBoundaryAnalysis, bool);
00229 itkGetConstMacro(DoBoundaryAnalysis, bool);
00231
00236 itkGetConstMacro(SortEdgeLists, bool);
00237 itkSetMacro(SortEdgeLists, bool);
00239
00240 protected:
00243 struct flat_region_t
00244 {
00245 unsigned long *min_label_ptr;
00246 InputPixelType bounds_min;
00247
00248 InputPixelType value;
00249 bool is_on_boundary;
00250 flat_region_t() : is_on_boundary(false) {}
00251 };
00252
00254 typedef itk::hash_map<unsigned long, flat_region_t, itk::hash<unsigned long> >
00255 flat_region_table_t;
00256
00257 struct connectivity_t
00258 {
00259 unsigned int size;
00260 unsigned int *index;
00261 typename InputImageType::OffsetType *direction;
00262 };
00263
00268 typedef itk::hash_map<unsigned long, InputPixelType, itk::hash<unsigned long>
00269 > edge_table_t;
00270
00271 typedef itk::hash_map<unsigned long, edge_table_t, itk::hash<unsigned long>
00272 > edge_table_hash_t;
00273
00274 Segmenter();
00275 Segmenter(const Self&) {}
00276 virtual ~Segmenter();
00277 void PrintSelf(std::ostream& os, Indent indent) const;
00278 void operator=(const Self&) {}
00279
00282 virtual void GenerateConnectivity();
00283
00287 void GenerateInputRequestedRegion();
00288 void GenerateOutputRequestedRegion(DataObject *output);
00289 void UpdateOutputInformation();
00291
00294 void InitializeBoundary();
00295
00299 void AnalyzeBoundaryFlow(InputImageTypePointer,
00300 flat_region_table_t &,
00301 InputPixelType);
00302
00306 void BuildRetainingWall(InputImageTypePointer,
00307 ImageRegionType, InputPixelType);
00308
00311 void LabelMinima(InputImageTypePointer,
00312 ImageRegionType, flat_region_table_t &,
00313 InputPixelType);
00314
00318 void GradientDescent(InputImageTypePointer, ImageRegionType);
00319
00322 void DescendFlatRegions(flat_region_table_t &, ImageRegionType);
00323
00326 void UpdateSegmentTable(InputImageTypePointer, ImageRegionType);
00327
00331 void CollectBoundaryInformation(flat_region_table_t &);
00332
00338 static void Threshold(InputImageTypePointer destination,
00339 InputImageTypePointer source,
00340 const ImageRegionType source_region,
00341 const ImageRegionType destination_region,
00342 InputPixelType threshold);
00343
00345 static void MinMax(InputImageTypePointer img,
00346 ImageRegionType region,
00347 InputPixelType &min,
00348 InputPixelType &max);
00349
00351 static void MergeFlatRegions(flat_region_table_t &, EquivalencyTable::Pointer);
00352
00354 static void SetInputImageValues(InputImageTypePointer img,
00355 const ImageRegionType region,
00356 InputPixelType value);
00357
00358 static void SetOutputImageValues(OutputImageTypePointer img,
00359 const ImageRegionType region,
00360 unsigned long value);
00361
00363
00364
00367 connectivity_t m_Connectivity;
00368
00369 private:
00371
00372
00376 ImageRegionType m_LargestPossibleRegion;
00377
00378 bool m_SortEdgeLists;
00379 bool m_DoBoundaryAnalysis;
00380 double m_Threshold;
00381 double m_MaximumFloodLevel;
00382 unsigned long m_CurrentLabel;
00383 };
00384
00385 }
00386 }
00387
00388 #ifndef ITK_MANUAL_INSTANTIATION
00389 #include "itkWatershedSegmenter.txx"
00390 #endif
00391
00392 #endif
00393