Go to the documentation of this file.00001
00002 #include "vil_gauss_filter.h"
00003
00004
00005
00006
00007
00008 #include <vcl_cmath.h>
00009 #include <vcl_cassert.h>
00010 #include <vcl_algorithm.h>
00011 #include <vcl_functional.h>
00012 #include <vnl/vnl_erf.h>
00013 #include <vnl/vnl_double_2.h>
00014 #include <vnl/vnl_real_polynomial.h>
00015
00016 vil_gauss_filter_5tap_params::vil_gauss_filter_5tap_params(double val_sigma)
00017 {
00018 sigma_ = val_sigma;
00019 const double z = 1/(vcl_sqrt(2.0)*val_sigma);
00020 filt0_ = vnl_erf(0.5 * z) - vnl_erf(-0.5 * z);
00021 filt1_ = vnl_erf(1.5 * z) - vnl_erf(0.5 * z);
00022 filt2_ = vnl_erf(2.5 * z) - vnl_erf(1.5 * z);
00023
00024 double five_tap_total = 2*(filt2_ + filt1_) + filt0_;
00025
00026
00027
00028
00029 filt_edge0_ = (filt0_ + filt1_ + filt2_) / five_tap_total;
00030 filt_edge1_ = filt1_ / five_tap_total;
00031 filt_edge2_ = filt2_ / five_tap_total;
00032 #if 0
00033 filt_edge0_ = 1.0;
00034 filt_edge1_ = 0.0;
00035 filt_edge2_ = 0.0;
00036 #endif
00037
00038 filt_pen_edge_n1_ = (filt1_+filt2_) / five_tap_total;
00039 filt_pen_edge0_ = filt0_ / five_tap_total;
00040 filt_pen_edge1_ = filt1_ / five_tap_total;
00041 filt_pen_edge2_ = filt2_ / five_tap_total;
00042
00043
00044 filt0_ = filt0_ / five_tap_total;
00045 filt1_ = filt1_ / five_tap_total;
00046 filt2_ = filt2_ / five_tap_total;
00047
00048 assert(filt_edge0_ >= filt_edge1_);
00049 assert(filt_edge1_ >= filt_edge2_);
00050 }
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 void vil_gauss_filter_gen_ntap(double sd, unsigned diff,
00066 vcl_vector<double> &filter)
00067 {
00068 vcl_size_t centre = filter.size()/2;
00069 double sum=0.0;
00070 double tap;
00071
00072 if (diff==0)
00073 {
00074 const double z = 1/(vcl_sqrt(2.0)*sd);
00075 if (filter.size() % 2 == 0)
00076 {
00077 for (unsigned i=0 ; i<centre; ++i)
00078 {
00079 tap = vnl_erf((i+1.0) * z) - vnl_erf(i * z);
00080 sum += tap;
00081 filter[centre+i] = filter[centre-i-1] = tap;
00082 }
00083 sum *= 2.0;
00084 }
00085 else
00086 {
00087 for (unsigned i=1 ; i<=centre; ++i)
00088 {
00089 tap = vnl_erf((i+0.5) * z) - vnl_erf((i-0.5) * z);
00090 sum += tap;
00091 filter[centre+i] = filter[centre-i] = tap;
00092 }
00093 sum *= 2.0;
00094 tap = vnl_erf(0.5 * z) - vnl_erf(-0.5 * z);
00095 sum += tap;
00096 filter[centre] = tap;
00097 }
00098 }
00099 else
00100 {
00101 const double offset = filter.size() % 2 == 0 ? 0.0 : -0.5;
00102 vnl_real_polynomial poly(1.0);
00103 const double eta = -0.5/(sd*sd);
00104 const vnl_real_polynomial d_gauss(vnl_double_2(eta, 0.0).as_ref());
00105 for (unsigned i=1; i<diff; ++i)
00106 {
00107
00108
00109 poly = poly * d_gauss + poly.derivative();
00110 }
00111
00112 for (int i=-(int)centre ; i+centre<filter.size(); ++i)
00113 {
00114 tap = poly.evaluate(i+1.0+offset)*vcl_exp(eta*(i+1.0+offset)*(i+1.0+offset))
00115 - poly.evaluate(i+ offset)*vcl_exp(eta*(i+ offset)*(i+ offset));
00116 sum += vcl_abs(tap);
00117 filter[centre+i] = tap;
00118 }
00119 }
00120
00121
00122 assert(sum >= 0.0);
00123 double norm = 1.0 / sum;
00124 vcl_transform(filter.begin(), filter.end(), filter.begin(),
00125 vcl_bind2nd(vcl_multiplies<double>(), norm));
00126 }