00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef SLOW_GAUSSIAN_HXX
00030 # define SLOW_GAUSSIAN_HXX
00031 # include <oln/core/image1d.hh>
00032 # include <oln/core/image2d.hh>
00033 # include <oln/core/image3d.hh>
00034
00035 namespace oln {
00036 namespace convol {
00037 namespace slow {
00038 namespace internal {
00039
00040
00041
00042
00043 template<class T>
00044 inline T
00045 normalise(const oln::abstract::non_vectorial_image<T> &in)
00046 {
00047 T w(in.size());
00048 ntg::float_d sum = 0.;
00049 oln_iter_type(T) i(in);
00050 for_all(i)
00051 sum += in[i];
00052 sum = 1. / sum;
00053 assert(finite(sum));
00054 for_all(i)
00055 w[i] = in[i] * sum;
00056 return w;
00057 }
00058
00059
00060 }
00061
00063 template<>
00064 struct gaussian_kernel<1>
00065 {
00066 typedef oln::image1d<ntg::float_d> ret;
00067 enum {dim = 1};
00068
00070
00071 static image1d<ntg::float_d>
00072 kernel(ntg::float_d sigma,
00073 ntg::float_d radius_factor)
00074 {
00075 precondition(sigma > 0.);
00076 precondition(radius_factor >= 0.);
00077 return internal::normalise(kernel_values(sigma, radius_factor));
00078 }
00079
00081
00082
00083
00084 static image1d<ntg::float_d>
00085 kernel_values(ntg::float_d sigma,
00086 ntg::float_d radius_factor)
00087 {
00088 precondition(sigma > 0.);
00089 precondition(radius_factor >= 0.);
00090
00091 const int size = int(sigma * radius_factor);
00092 image1d<ntg::float_d> w(size * 2 + 1);
00093
00094 const ntg::float_d inv_sigma_sqrt_2pi
00095 = 1. / (sigma * sqrt(M_PI * 2.));
00096 for (int x = -size; x <= size; ++x)
00097 w(x + size) = inv_sigma_sqrt_2pi * exp(-x * x /(2 * sigma * sigma));
00098 return w;
00099 }
00100 };
00101
00103 template<>
00104 struct gaussian_kernel<2>
00105 {
00106 typedef image2d<ntg::float_d> ret;
00107 enum {dim = 2};
00108
00110
00111 static image2d<ntg::float_d>
00112 kernel(ntg::float_d sigma,
00113 ntg::float_d radius_factor)
00114 {
00115 precondition(sigma > 0.);
00116 precondition(radius_factor >= 0.);
00117
00118 return internal::normalise(kernel_values(sigma, radius_factor));
00119 }
00120
00122
00123
00124
00125 static image2d<ntg::float_d>
00126 kernel_values(ntg::float_d sigma,
00127 ntg::float_d radius_factor)
00128 {
00129 precondition(sigma > 0.);
00130 precondition(radius_factor >= 0.);
00131 const int size = int(sigma * radius_factor);
00132 image2d<ntg::float_d> w = image2d<ntg::float_d>(size * 2 + 1,
00133 size * 2 + 1);
00134
00135 const ntg::float_d inv_sigma_sigma_pi_2 = 1. / (sigma * sigma *
00136 M_PI * 2.);
00137 for (int x = -size ; x <= size; ++x)
00138 for (int y = -size ; y <= size; ++y)
00139 if (x * x + y * y <= size * size)
00140 w(x + size, y + size) = inv_sigma_sigma_pi_2
00141 * exp(- (x * x + y * y)
00142 / ( 2. * sigma * sigma)
00143 );
00144 else
00145 w(x + size, y + size) = 0;
00146 return w;
00147 }
00148 };
00149
00151 template<>
00152 struct gaussian_kernel<3>
00153 {
00154 typedef image3d<ntg::float_d> ret;
00155 enum {dim = 3};
00156
00158
00159 static image3d<ntg::float_d>
00160 kernel(ntg::float_d sigma,
00161 ntg::float_d radius_factor)
00162 {
00163 precondition(sigma > 0.);
00164 precondition(radius_factor >= 0.);
00165
00166 return internal::normalise(kernel_values(sigma, radius_factor));
00167 }
00168
00169
00171
00172
00173
00174 static image3d<ntg::float_d>
00175 kernel_values(ntg::float_d sigma,
00176 ntg::float_d radius_factor)
00177 {
00178 precondition(sigma > 0.);
00179 precondition(radius_factor >= 0.);
00180
00181 const int size = int(sigma * radius_factor);
00182 image3d<ntg::float_d> w(size * 2 + 1,
00183 size * 2 + 1,
00184 size * 2 + 1);
00185
00186 const ntg::float_d k = 1. / (sigma * sigma * sigma *
00187 sqrt((M_PI * 2.) * (M_PI * 2.) *
00188 (M_PI * 2.)));
00189
00190 for (int x = -size; x <= +size; ++x)
00191 for (int y = -size; y <= +size; ++y)
00192 for (int z = -size; z <= +size; ++z)
00193 if (x * x + y * y + z * z <= size)
00194 w(x + size, y + size, z + size) = k *
00195 exp(-(x * x + y * y + z * z)
00196 ) / (2. * sigma * sigma);
00197 else
00198 w(x + size, y + size, z + size) = 0;
00199 return w;
00200 }
00201 };
00202
00203 }
00204 }
00205 }
00206 #endif // end SLOW_GAUSSIAN_HXX