1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 #ifndef itkKLMSegmentationBorder_h 19 #define itkKLMSegmentationBorder_h 20 21 #include "itkSegmentationBorder.h" 22 #include "itkKLMSegmentationRegion.h" 23 #include "itkMacro.h" 24 #include "ITKKLMRegionGrowingExport.h" 25 26 #include "itkMath.h" 27 #include "vnl/vnl_vector.h" 28 #include "itkMath.h" 29 30 namespace itk 31 { 32 /** \class KLMDynamicBorderArray 33 * \brief Object maintaining a reference to a list of borders associated 34 * with a region. 35 * 36 * This is a tiny class similar to smart pointers that maintains a reference 37 * to a list of borders pointed by a region. 38 * 39 * \ingroup RegionGrowingSegmentation 40 * \ingroup ITKKLMRegionGrowing 41 */ 42 43 template< typename TBorder > 44 class KLMDynamicBorderArray 45 { 46 public: 47 /** Greater than operators defined to work with both static objects 48 * or pointer to objects. In the degenerate 49 * case of an image where all (or many) Lambda's are equal to some 50 * constant value, this operator will ensure that the future 51 * merged regions do not gain more borders than other regions, 52 * thus avoiding pathologically slow behavior. 53 */ 54 bool operator>(const KLMDynamicBorderArray< TBorder > & rhs) const 55 { 56 if ( Math::ExactlyEquals(m_Pointer->GetLambda(), rhs.m_Pointer->GetLambda()) ) 57 { 58 if ( m_Pointer->GetLambda() < 0 ) 59 { 60 return ( m_Pointer > rhs.m_Pointer ); 61 } 62 else 63 { 64 // The purpose of this comparison is to not let any one region 65 // get more borders than another region. In the degenerate 66 // case of an image where the Lambdas are always equal to some 67 // constant C, allowing a single region to be repeatedly 68 // merged so that it gains many borders will result in 69 // pathologically slow behavior. 70 double v1 = std::max( 71 static_cast< double >( m_Pointer->GetRegion1()->GetRegionBorderSize() ), 72 static_cast< double >( m_Pointer->GetRegion2()->GetRegionBorderSize() ) ); 73 74 double v2 = std::max( 75 static_cast< double >( rhs.m_Pointer->GetRegion1()->GetRegionBorderSize() ), 76 static_cast< double >( rhs.m_Pointer->GetRegion2()->GetRegionBorderSize() ) ); 77 78 return ( v1 > v2 ); 79 } 80 } 81 return ( m_Pointer->GetLambda() > rhs.m_Pointer->GetLambda() ); 82 } 83 84 bool operator>(const KLMDynamicBorderArray< TBorder > *rhs) const 85 { 86 if ( m_Pointer->GetLambda() == rhs->m_Pointer->GetLambda() ) 87 { 88 if ( m_Pointer->GetLambda() < 0 ) 89 { 90 return ( m_Pointer > rhs->m_Pointer ); 91 } 92 else 93 { 94 // The purpose of this comparison is to not let any one region 95 // get more borders than another region. In the degenerate 96 // case of an image where the Lambdas are always equal to some 97 // constant C, allowing a single region to be repeatedly 98 // merged so that it gains many borders will result in 99 // pathologically slow behavior. 100 double v1 = std::max( 101 static_cast< double >( m_Pointer->GetRegion1()->GetRegionBorderSize() ), 102 static_cast< double >( m_Pointer->GetRegion2()->GetRegionBorderSize() ) ); 103 104 double v2 = std::max( 105 static_cast< double >( rhs->m_Pointer->GetRegion1()->GetRegionBorderSize() ), 106 static_cast< double >( rhs->m_Pointer->GetRegion2()->GetRegionBorderSize() ) ); 107 108 return ( v1 > v2 ); 109 } 110 } 111 return ( m_Pointer->GetLambda() > rhs->m_Pointer->GetLambda() ); 112 } 113 114 TBorder *m_Pointer; 115 }; 116 117 /** \class KLMSegmentationBorder 118 * \brief Base class for KLMSegmentationBorder object 119 * 120 * itkKLMSegmentationBorder is the base class for the KLMSegmentationBorder 121 * objects. It provides the basic function definitons that are inherent to a 122 * KLMSegmentationBorder objects. 123 * 124 * This class implements the border object that is used in particular with 125 * the KLM algorithm (see also KLMRegionGrowImageFilter). The border is 126 * defined by the adjacency of two regions. The parameter Lambda ascertains 127 * the importance of the border in defining the regions. The higher the 128 * values of Lambda the more dominant is its presence in the a region. In 129 * case of removal of a border during the region growing process the one with 130 * least Lambda value is eliminated. 131 * 132 * \ingroup RegionGrowingSegmentation 133 * \ingroup ITKKLMRegionGrowing 134 */ 135 136 // Forward reference because of circular dependencies 137 class ITK_FORWARD_EXPORT KLMSegmentationRegion; 138 139 class ITKKLMRegionGrowing_EXPORT KLMSegmentationBorder:public SegmentationBorder 140 { 141 public: 142 ITK_DISALLOW_COPY_AND_ASSIGN(KLMSegmentationBorder); 143 144 /** Standard class type aliases. */ 145 using Self = KLMSegmentationBorder; 146 using Superclass = SegmentationBorder; 147 using Pointer = SmartPointer< Self >; 148 using ConstPointer = SmartPointer< const Self >; 149 150 /** Method for creation through the object factory. */ 151 itkNewMacro(Self); 152 153 /** Run-time type information (and related methods). */ 154 itkTypeMacro(KLMSegmentationBorder, SegmentationBorder); 155 156 /** Set the region 1 associated with the border */ 157 void SetRegion1(KLMSegmentationRegion *Region1); 158 159 /** Get the region 1 associated with the border. */ 160 KLMSegmentationRegion * GetRegion1(); 161 162 /** Set the region 2 associated with the border. */ 163 void SetRegion2(KLMSegmentationRegion *Region2); 164 165 /** Get the region 2 associated with the border. */ 166 KLMSegmentationRegion * GetRegion2(); 167 168 /** Set/Get the Lambda parameter associate with the borders 169 * in the KLM algorithm */ 170 itkSetMacro(Lambda, double); 171 itkGetConstReferenceMacro(Lambda, double); 172 173 /** Evaluate the Lambda for a given border. */ 174 void EvaluateLambda(); 175 176 /** Print the data associated with each border. */ 177 void PrintBorderInfo(); 178 179 protected: 180 /** Constructor. */ 181 KLMSegmentationBorder(); 182 183 /** Destructor. */ 184 ~KLMSegmentationBorder() override; 185 186 /** Print self identity */ 187 void PrintSelf(std::ostream & os, Indent indent) const override; 188 189 private: 190 double m_Lambda; 191 KLMSegmentationRegion *m_Region1; 192 KLMSegmentationRegion *m_Region2; 193 }; 194 } // end namespace itk 195 196 #endif 197