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 itkBayesianClassifierImageFilter_h 19 #define itkBayesianClassifierImageFilter_h 20 21 #include "itkVectorImage.h" 22 #include "itkImageToImageFilter.h" 23 #include "itkMaximumDecisionRule.h" 24 #include "itkImageRegionIterator.h" 25 26 namespace itk 27 { 28 /** \class BayesianClassifierImageFilter 29 * 30 * \brief Performs Bayesian Classification on an image. 31 * 32 * \par Inputs and Outputs 33 * The input to this filter is an itk::VectorImage that represents pixel 34 * memberships to 'n' classes. This image is conveniently generated by the 35 * BayesianClassifierInitializationImageFilter. You may use that filter to 36 * generate the membership images or specify your own. 37 * 38 * \par 39 * The output of the filter is a label map (an image of unsigned char's is the 40 * default.) with pixel values indicating the classes they correspond to. Pixels 41 * with intensity 0 belong to the 0th class, 1 belong to the 1st class etc.... 42 * The classification is done by applying a Maximum decision rule to the posterior 43 * image. 44 * 45 * \par Parameters 46 * The filter optionally allows you to specify a prior image as well. The prior 47 * image, if specified must be a VectorImage with as many components as the 48 * number of classes. The posterior image is then generated by multiplying the 49 * prior image with the membership image. If the prior image is not specified, 50 * the posterior image is the same as the membership image. Another way to 51 * look at it is that the priors default to having a uniform distribution over 52 * the number of classes. 53 * Posterior membership of a pixel = Prior * Membership 54 * 55 * \par 56 * The filter optionally accepts a smoothing filter and number of iterations 57 * associated with the smoothing filter. 58 * The philosophy is that the filter allows you to iteratively 59 * smooth the posteriors prior to applying the decision rule. It is hoped 60 * that this would yield a better classification. The user will need to plug 61 * in his own smoothing filter with all the parameters set. 62 * 63 * \par Template parameters 64 * InputVectorImage, datatype of the output labelmap, precision of the posterior 65 * image, precision of the prior image. 66 * 67 * \author John Melonakos, Georgia Tech 68 * 69 * \note 70 * This work is part of the National Alliance for Medical Image Computing 71 * (NAMIC), funded by the National Institutes of Health through the NIH Roadmap 72 * for Medical Research, Grant U54 EB005149. 73 * 74 * \sa VectorImage 75 * \sa BayesianClassifierInitializationImageFilter 76 * \ingroup ClassificationFilters 77 * \ingroup ITKClassifiers 78 */ 79 template< typename TInputVectorImage, typename TLabelsType = unsigned char, 80 typename TPosteriorsPrecisionType = double, typename TPriorsPrecisionType = double > 81 class ITK_TEMPLATE_EXPORT BayesianClassifierImageFilter: 82 public ImageToImageFilter< 83 TInputVectorImage, Image< TLabelsType, 84 TInputVectorImage ::ImageDimension > > 85 { 86 public: 87 ITK_DISALLOW_COPY_AND_ASSIGN(BayesianClassifierImageFilter); 88 89 /** Standard class type aliases. */ 90 using Self = BayesianClassifierImageFilter; 91 using Superclass = ImageToImageFilter< 92 TInputVectorImage, 93 Image< TLabelsType, TInputVectorImage::ImageDimension > >; 94 95 using Pointer = SmartPointer< Self >; 96 using ConstPointer = SmartPointer< const Self >; 97 98 /** Method for creation through the object factory. */ 99 itkNewMacro(Self); 100 101 /** Run-time type information (and related methods). */ 102 itkTypeMacro(BayesianClassifierImageFilter, ImageToImageFilter); 103 104 /** Input and Output image types. */ 105 using InputImageType = typename Superclass::InputImageType; 106 107 /** Dimension of the input image. */ 108 static constexpr unsigned int Dimension = InputImageType ::ImageDimension; 109 110 using OutputImageType = Image< TLabelsType, 111 Self::Dimension >; 112 using InputImagePointer = typename InputImageType::ConstPointer; 113 using OutputImagePointer = typename OutputImageType::Pointer; 114 using ImageRegionType = typename InputImageType::RegionType; 115 116 /** Input and Output image iterators. */ 117 using InputImageIteratorType = ImageRegionConstIterator< InputImageType >; 118 using OutputImageIteratorType = ImageRegionIterator< OutputImageType >; 119 120 /** Pixel types. */ 121 using InputPixelType = typename InputImageType::PixelType; 122 using OutputPixelType = typename OutputImageType::PixelType; 123 124 /** Image Type and Pixel type for the images representing the Prior 125 * probability of a pixel belonging to a particular class. This image has 126 * arrays as pixels, the number of elements in the array is the same as the 127 * number of classes to be used. */ 128 using PriorsImageType = VectorImage< TPriorsPrecisionType, 129 Self::Dimension >; 130 using PriorsPixelType = typename PriorsImageType::PixelType; 131 using PriorsImagePointer = typename PriorsImageType::Pointer; 132 using PriorsImageIteratorType = ImageRegionConstIterator< PriorsImageType >; 133 134 /** Image Type and Pixel type for the images representing the membership of a 135 * pixel to a particular class. This image has arrays as pixels, the number of 136 * elements in the array is the same as the number of classes to be used. */ 137 using MembershipImageType = TInputVectorImage; 138 using MembershipPixelType = typename MembershipImageType::PixelType; 139 using MembershipImagePointer = typename MembershipImageType::Pointer; 140 using MembershipImageIteratorType = ImageRegionConstIterator< MembershipImageType >; 141 142 /** Image Type and Pixel type for the images representing the Posterior 143 * probability of a pixel belonging to a particular class. This image has 144 * arrays as pixels, the number of elements in the array is the same as the 145 * number of classes to be used. */ 146 using PosteriorsImageType = VectorImage< TPosteriorsPrecisionType, 147 Self::Dimension >; 148 using PosteriorsPixelType = typename PosteriorsImageType::PixelType; 149 using PosteriorsImagePointer = typename PosteriorsImageType::Pointer; 150 using PosteriorsImageIteratorType = ImageRegionIterator< PosteriorsImageType >; 151 152 /** Decision rule to use for defining the label. */ 153 using DecisionRuleType = Statistics::MaximumDecisionRule; 154 using DecisionRulePointer = DecisionRuleType::Pointer; 155 156 using DataObjectPointer = typename Superclass::DataObjectPointer; 157 158 /** An image from a single component of the Posterior. */ 159 using ExtractedComponentImageType = itk::Image< TPosteriorsPrecisionType, 160 Self::Dimension >; 161 162 /** Optional Smoothing filter that will be applied to the Posteriors. */ 163 using SmoothingFilterType = ImageToImageFilter< 164 ExtractedComponentImageType, 165 ExtractedComponentImageType >; 166 167 using SmoothingFilterPointer = typename SmoothingFilterType::Pointer; 168 169 /** Set/Get the smoothing filter that may optionally be applied to the 170 * posterior image. */ 171 void SetSmoothingFilter(SmoothingFilterType *); 172 itkGetConstMacro(SmoothingFilter, SmoothingFilterPointer); 173 174 /** Set the priors image. */ 175 virtual void SetPriors(const PriorsImageType *); 176 177 /** Number of iterations to apply the smoothing filter. */ 178 itkSetMacro(NumberOfSmoothingIterations, unsigned int); 179 itkGetConstMacro(NumberOfSmoothingIterations, unsigned int); 180 181 /** This is overloaded to create the Posteriors output image. */ 182 using DataObjectPointerArraySizeType = ProcessObject::DataObjectPointerArraySizeType; 183 using Superclass::MakeOutput; 184 DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override; 185 186 #ifdef ITK_USE_CONCEPT_CHECKING 187 // Begin concept checking 188 itkConceptMacro( UnsignedIntConvertibleToLabelsCheck, 189 ( Concept::Convertible< unsigned int, TLabelsType > ) ); 190 itkConceptMacro( PosteriorsAdditiveOperatorsCheck, 191 ( Concept::AdditiveOperators< TPosteriorsPrecisionType > ) ); 192 itkConceptMacro( IntConvertibleToPosteriorsCheck, 193 ( Concept::Convertible< int, TPosteriorsPrecisionType > ) ); 194 itkConceptMacro( InputHasNumericTraitsCheck, 195 ( Concept::HasNumericTraits< typename InputPixelType::ValueType > ) ); 196 itkConceptMacro( PosteriorsHasNumericTraitsCheck, 197 ( Concept::HasNumericTraits< TPosteriorsPrecisionType > ) ); 198 itkConceptMacro( PriorsHasNumericTraitsCheck, 199 ( Concept::HasNumericTraits< TPriorsPrecisionType > ) ); 200 itkConceptMacro( InputPriorsPosteriorsMultiplyOperatorCheck, 201 ( Concept::MultiplyOperator< typename InputPixelType::ValueType, 202 PriorsPixelType, PosteriorsPixelType > ) ); 203 // End concept checking 204 #endif 205 206 protected: 207 208 BayesianClassifierImageFilter(); 209 ~BayesianClassifierImageFilter() override = default; 210 void PrintSelf(std::ostream & os, Indent indent) const override; 211 212 void GenerateData() override; 213 214 void GenerateOutputInformation() override; 215 216 /** Compute the posteriors using the Bayes rule. If no priors are available, 217 * then the posteriors are just a copy of the memberships. 218 * Computes the labeled map for all combinations of conditions. */ 219 virtual void ComputeBayesRule(); 220 221 /** Normalize the posteriors and smooth them using a user-provided. */ 222 virtual void NormalizeAndSmoothPosteriors(); 223 224 /** Compute the labeled map based on the Maximum rule applied to the posteriors. */ 225 virtual void ClassifyBasedOnPosteriors(); 226 227 /** Get the Posteriors Image. */ 228 PosteriorsImageType * GetPosteriorImage(); 229 230 private: 231 232 233 bool m_UserProvidedPriors{ false }; 234 235 bool m_UserProvidedSmoothingFilter{ false }; 236 237 SmoothingFilterPointer m_SmoothingFilter; 238 239 unsigned int m_NumberOfSmoothingIterations{ 0 }; 240 }; 241 } // end namespace itk 242 243 #ifndef ITK_MANUAL_INSTANTIATION 244 #include "itkBayesianClassifierImageFilter.hxx" 245 #endif 246 247 #endif 248