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 itkGaussianMembershipFunction_h
19 #define itkGaussianMembershipFunction_h
20 
21 #include "itkMatrix.h"
22 #include "itkMembershipFunctionBase.h"
23 
24 namespace itk
25 {
26 namespace Statistics
27 {
28 /** \class GaussianMembershipFunction
29  * \brief GaussianMembershipFunction models class membership through a
30  * multivariate Gaussian function.
31  *
32  * GaussianMembershipFunction is a subclass of MembershipFunctionBase
33  * that models class membership (or likelihood) using a multivariate
34  * Gaussian function. The mean and covariance structure of the
35  * Gaussian are established using the methods SetMean() and
36  * SetCovariance(). The mean is a vector-type that is the same
37  * vector-type as the measurement vector but guaranteed to have a real
38  * element type. For instance, if the measurement type is an
39  * Vector<int,3>, then the mean is Vector<double,3>. If the
40  * measurement type is a VariableLengthVector<float>, then the mean is
41  * VariableLengthVector<double>. In contrast to this behavior, the
42  * covariance is always a VariableSizeMatrix<double>.
43  *
44  * If the covariance is singular or nearly singular, the membership function
45  * behaves somewhat like an impulse located at the mean. In this case,
46  * we specify the covariance to be a diagonal matrix with large values
47  * along the diagonal. This membership function, therefore,
48  * will return small but differentiable values everywher and increase
49  * sharply near the mean.
50  *
51  * \ingroup ITKStatistics
52  */
53 
54 template< typename TMeasurementVector >
55 class ITK_TEMPLATE_EXPORT GaussianMembershipFunction:
56   public MembershipFunctionBase< TMeasurementVector >
57 {
58 public:
59   ITK_DISALLOW_COPY_AND_ASSIGN(GaussianMembershipFunction);
60 
61   /** Standard class type aliases */
62   using Self = GaussianMembershipFunction;
63   using Superclass = MembershipFunctionBase< TMeasurementVector >;
64   using Pointer = SmartPointer< Self >;
65   using ConstPointer = SmartPointer< const Self >;
66 
67   /** Standard macros */
68   itkTypeMacro(GaussianMembershipFunction, MembershipFunction);
69   itkNewMacro(Self);
70 
71   /** SmartPointer class for superclass */
72   using MembershipFunctionPointer = typename Superclass::Pointer;
73 
74   /** Typedef alias for the measurement vectors */
75   using MeasurementVectorType = TMeasurementVector;
76 
77   /** Length of each measurement vector */
78   using MeasurementVectorSizeType = typename Superclass::MeasurementVectorSizeType;
79 
80   /** Type of the mean vector. RealType on a vector-type is the same
81    * vector-type but with a real element type.  */
82   using MeasurementVectorRealType = typename itk::NumericTraits< MeasurementVectorType >::RealType;
83   using MeanVectorType = MeasurementVectorRealType;
84 
85   /** Type of the covariance matrix */
86   using CovarianceMatrixType = VariableSizeMatrix< double >;
87 
88   /** Set the mean of the Gaussian distribution. Mean is a vector type
89    * similar to the measurement type but with a real element type. */
90   void SetMean(const MeanVectorType & mean);
91 
92   /** Get the mean of the Gaussian distribution. Mean is a vector type
93    * similar to the measurement type but with a real element type. */
94   itkGetConstReferenceMacro(Mean, MeanVectorType);
95 
96   /** Set the covariance matrix. Covariance matrix is a
97    * VariableSizeMatrix of doubles. The inverse of the covariance
98    * matrix and the normlization term for the multivariate Gaussian
99    * are calculate whenever the covaraince matrix is changed. */
100   void SetCovariance(const CovarianceMatrixType & cov);
101 
102   /* Get the covariance matrix. Covariance matrix is a
103   VariableSizeMatrix of doubles. */
104   itkGetConstReferenceMacro(Covariance, CovarianceMatrixType);
105 
106   /* Get the inverse covariance matrix. Covariance matrix is a
107   VariableSizeMatrix of doubles. */
108   itkGetConstReferenceMacro(InverseCovariance, CovarianceMatrixType);
109 
110   /** Evaluate the probability density of a measurement vector. */
111   double Evaluate(const MeasurementVectorType & measurement) const override;
112 
113   /** Method to clone a membership function, i.e. create a new instance of
114    * the same type of membership function and configure its ivars to
115    * match. */
116   typename LightObject::Pointer InternalClone() const override;
117 
118 protected:
119   GaussianMembershipFunction();
120   ~GaussianMembershipFunction() override = default;
121   void PrintSelf(std::ostream & os, Indent indent) const override;
122 
123 private:
124   MeanVectorType       m_Mean;            // mean
125   CovarianceMatrixType m_Covariance;      // covariance matrix
126 
127   // inverse covariance matrix. automatically calculated
128   // when covariace matirx is set.
129   CovarianceMatrixType m_InverseCovariance;
130 
131   // pre_factor (normalization term). automatically calculated
132   // when covariace matirx is set.
133   double m_PreFactor;
134 
135   /** Boolean to cache whether the covarinace is singular or nearly singular */
136   bool m_CovarianceNonsingular;
137 };
138 } // end of namespace Statistics
139 } // end namespace itk
140 
141 #ifndef ITK_MANUAL_INSTANTIATION
142 #include "itkGaussianMembershipFunction.hxx"
143 #endif
144 
145 #endif
146