00001
00002 #ifndef bsta_gaussian_full_txx_
00003 #define bsta_gaussian_full_txx_
00004
00005
00006
00007 #include "bsta_gaussian_full.h"
00008 #include <vcl_algorithm.h>
00009 #include <vcl_limits.h>
00010 #if 0
00011 #include <vcl_cassert.h>
00012 #endif
00013
00014 #include <vnl/algo/vnl_svd.h>
00015 #include <vnl/algo/vnl_determinant.h>
00016 #include <vnl/vnl_inverse.h>
00017
00018 namespace {
00019
00020
00021 template <class T, unsigned n, unsigned i, unsigned j>
00022 struct compute_sqr_mahalanobis_helper
00023 {
00024 static inline T value(const vnl_vector_fixed<T,n>& d,
00025 const vnl_matrix_fixed<T,n,n>& inv_covar)
00026 {
00027 return 2*d[i-1]*d[j-1]*inv_covar(i-1,j-1)
00028 + compute_sqr_mahalanobis_helper<T,n,i,j-1>::value(d,inv_covar);
00029 }
00030 };
00031
00032
00033
00034 template <class T, unsigned n, unsigned i>
00035 struct compute_sqr_mahalanobis_helper<T,n,i,0>
00036 {
00037 static inline T value(const vnl_vector_fixed<T,n>& ,
00038 const vnl_matrix_fixed<T,n,n>& )
00039 { return 0; }
00040 };
00041
00042
00043 template <class T, unsigned n, unsigned i>
00044 struct bsta_gaussian_full_compute_sqr_mahalanobis
00045 {
00046 static inline T value(const vnl_vector_fixed<T,n>& d,
00047 const vnl_matrix_fixed<T,n,n>& inv_covar)
00048 {
00049 return d[i-1]*d[i-1]*inv_covar(i-1,i-1)
00050 + compute_sqr_mahalanobis_helper<T,n,i,i-1>::value(d,inv_covar)
00051 + bsta_gaussian_full_compute_sqr_mahalanobis<T,n,i-1>::value(d,inv_covar);
00052 }
00053 };
00054
00055
00056
00057 template <class T, unsigned n>
00058 struct bsta_gaussian_full_compute_sqr_mahalanobis<T,n,0>
00059 {
00060 static inline T value(const vnl_vector_fixed<T,n>& ,
00061 const vnl_matrix_fixed<T,n,n>& )
00062 { return 0; }
00063 };
00064
00065
00066
00067 template <class T, unsigned n>
00068 inline vnl_matrix_fixed<T,n,n>* make_inverse(const vnl_matrix_fixed<T,n,n>& M)
00069 { return new vnl_matrix_fixed<T,n,n>(vnl_svd_inverse(M.as_ref())); }
00070
00071 template <class T>
00072 inline vnl_matrix_fixed<T,4,4>* make_inverse(const vnl_matrix_fixed<T,4,4>& M)
00073 { return new vnl_matrix_fixed<T,4,4>(vnl_inverse(M)); }
00074
00075 template <class T>
00076 inline vnl_matrix_fixed<T,3,3>* make_inverse(const vnl_matrix_fixed<T,3,3>& M)
00077 { return new vnl_matrix_fixed<T,3,3>(vnl_inverse(M)); }
00078
00079 template <class T>
00080 inline vnl_matrix_fixed<T,2,2>* make_inverse(const vnl_matrix_fixed<T,2,2>& M)
00081 { return new vnl_matrix_fixed<T,2,2>(vnl_inverse(M)); }
00082
00083 template <class T>
00084 inline vnl_matrix_fixed<T,1,1>* make_inverse(const vnl_matrix_fixed<T,1,1>& M)
00085 { return new vnl_matrix_fixed<T,1,1>(vnl_inverse(M)); }
00086
00087 };
00088
00089
00090
00091 template <class T, unsigned int n>
00092 T
00093 bsta_gaussian_full<T,n>::sqr_mahalanobis_dist(const vnl_vector_fixed<T,n>& pt) const
00094 {
00095 if (det_covar_<=T(0))
00096 return vcl_numeric_limits<T>::infinity();
00097 vnl_vector_fixed<T,n> d = bsta_gaussian<T,n>::mean_-pt;
00098 #if 0
00099 assert((sqr_mahalanobis_dist<T,n,n>::value(d,diag_covar_)) > 0);
00100 #endif
00101 return bsta_gaussian_full_compute_sqr_mahalanobis<T,n,n>::value(d,inv_covar());
00102 }
00103
00104
00105
00106 template <class T, unsigned int n>
00107 void
00108 bsta_gaussian_full<T,n>::compute_det()
00109 {
00110 det_covar_ = vnl_determinant(covar_);
00111 }
00112
00113
00114
00115 template <class T, unsigned int n>
00116 void
00117 bsta_gaussian_full<T,n>::set_covar(const vnl_matrix_fixed<T,n,n>& covar)
00118 {
00119 delete inv_covar_;
00120 inv_covar_ = NULL;
00121 covar_ = covar;
00122 compute_det();
00123 }
00124
00125
00126
00127
00128 template <class T, unsigned int n>
00129 const vnl_matrix_fixed<T,n,n>&
00130 bsta_gaussian_full<T,n>::inv_covar() const
00131 {
00132 if (!inv_covar_){
00133 vnl_matrix_fixed<T,n,n> C = covar_;
00134 if (det_covar_ == T(0)){
00135
00136
00137
00138 T lambda = T(0);
00139 for (unsigned i=0; i<n; ++i)
00140 lambda = vcl_max(lambda,C(i,i));
00141 lambda *= 1e-4f;
00142 for (unsigned i=0; i<n; ++i)
00143 C(i,i) += lambda;
00144 }
00145 inv_covar_ = make_inverse(C);
00146 }
00147 return *inv_covar_;
00148 }
00149
00150
00151 #define BSTA_GAUSSIAN_FULL_INSTANTIATE(T,n) \
00152 template class bsta_gaussian_full<T,n >
00153
00154
00155 #endif // bsta_gaussian_full_txx_