00001 #include "brip_filter_bank.h"
00002
00003 #include <brip/brip_vil_float_ops.h>
00004 #include <brip/brip_vil_ops.h>
00005 #include <vil/vil_resample_bicub.h>
00006 #include <vil/vil_save.h>
00007 #include <vcl_cmath.h>
00008 #include <vcl_cassert.h>
00009 #include <vcl_sstream.h>
00010 #include <vul/vul_file.h>
00011
00012
00013 static int gauss_radius(float sigma, float cutoff_ratio)
00014 {
00015 double sigma_sq_inv = 1/(sigma*sigma);
00016 return static_cast<int>(vcl_sqrt((-2.0*vcl_log(cutoff_ratio))/sigma_sq_inv)+0.5);
00017 }
00018
00019 brip_filter_bank::brip_filter_bank(unsigned n_levels,
00020 double scale_range, float lambda0,
00021 float lambda1, float theta_interval,
00022 float cutoff_ratio)
00023 : ni_(0), nj_(0),n_levels_(n_levels), lambda0_(lambda0), lambda1_(lambda1),
00024 theta_interval_(theta_interval), cutoff_ratio_(cutoff_ratio)
00025 {
00026 assert(n_levels_);
00027 if (n_levels == 1) {
00028 scale_ratio_ = 1.0;
00029 }
00030 else {
00031 double ninv = 1.0/(n_levels-1);
00032 scale_ratio_ = vcl_pow(scale_range, ninv);
00033 }
00034 }
00035
00036 brip_filter_bank::brip_filter_bank(unsigned n_levels,
00037 double scale_range, float lambda0,
00038 float lambda1, float theta_interval,
00039 float cutoff_ratio,
00040 vil_image_view<float> const& image):
00041 n_levels_(n_levels), lambda0_(lambda0), lambda1_(lambda1),
00042 theta_interval_(theta_interval), cutoff_ratio_(cutoff_ratio)
00043 {
00044 assert(n_levels_);
00045 ni_ = image.ni(); nj_ = image.nj();
00046 scale_pyramid_ = vil_pyramid_image_view<float>(image);
00047 if (n_levels == 1) {
00048 scale_ratio_ = 1.0;
00049 }
00050 else {
00051 double ninv = 1.0/(n_levels-1);
00052 scale_ratio_ = vcl_pow(scale_range, ninv);
00053 this->construct_scale_pyramid();
00054 }
00055 this->compute_filter_responses();
00056 }
00057
00058 void brip_filter_bank::set_image(vil_image_view<float> const& image)
00059 {
00060 ni_ = image.ni(); nj_ = image.nj();
00061 scale_pyramid_ = vil_pyramid_image_view<float>(image);
00062 if (scale_ratio_ != 1.0) this->construct_scale_pyramid();
00063 this->compute_filter_responses();
00064 }
00065
00066 void brip_filter_bank::construct_scale_pyramid()
00067 {
00068
00069 unsigned radius =
00070 static_cast<unsigned>(gauss_radius(static_cast<float>(scale_ratio_), cutoff_ratio_));
00071 unsigned int n_samples = 2*radius +1;
00072 for (unsigned level = 1; level<n_levels_; ++level) {
00073 vil_image_view<float> smooth;
00074 double scale_m1;
00075
00076 vil_image_view<float> level_m1_view = scale_pyramid_.get_view(level-1,
00077 scale_m1);
00078
00079 brip_gauss_filter(level_m1_view, smooth, scale_ratio_, n_samples,
00080 vil_convolve_no_extend);
00081
00082 double dni = level_m1_view.ni(), dnj = level_m1_view.nj();
00083
00084 dni /= scale_ratio_; dnj /= scale_ratio_;
00085 double scale = scale_m1 / scale_ratio_;
00086 unsigned sni = static_cast<unsigned>(dni+0.5);
00087 unsigned snj = static_cast<unsigned>(dnj+0.5);
00088 vil_image_view<float>* lview = new vil_image_view<float>();
00089 vil_image_view_base_sptr lview_ptr = lview;
00090 vil_resample_bicub(smooth, *lview, sni, snj);
00091 scale_pyramid_.add_view(lview_ptr, scale);
00092 }
00093 }
00094
00095 void brip_filter_bank::compute_filter_responses()
00096 {
00097 filter_responses_.clear();
00098 filter_responses_.resize(n_levels_);
00099 vcl_cout << '(' << lambda0_ << ' ' << lambda1_ << ")\n";
00100 for (unsigned level = 0; level<n_levels_; ++level) {
00101 vil_image_view<float>& level_view = scale_pyramid_(level);
00102
00103 vil_image_view<float> resp =
00104 brip_vil_float_ops::fast_extrema_rotational(level_view,
00105 lambda0_,
00106 lambda1_,
00107 theta_interval_,
00108 false,
00109 false,
00110 true,
00111 true,
00112 false,
00113 cutoff_ratio_);
00114
00115 vil_image_view<float> upsamp_response;
00116 vil_resample_bicub(resp, upsamp_response, ni_, nj_);
00117 filter_responses_[level] = upsamp_response;
00118 vcl_cout << 1.0/scale_pyramid_.scale(level) << ' ' << vcl_flush;
00119 }
00120 vcl_cout << '\n' << vcl_flush;
00121 }
00122
00123 unsigned brip_filter_bank::invalid_border() const
00124 {
00125
00126 double g_rad = gauss_radius(static_cast<float>(scale_ratio_), cutoff_ratio_);
00127
00128 double f_rad = gauss_radius(lambda0_, cutoff_ratio_);
00129 double r = 0.42*vcl_sqrt(g_rad*g_rad + f_rad*f_rad);
00130 double scale_int = vcl_pow(scale_ratio_, double(n_levels_-1));
00131 r *= scale_int;
00132 return static_cast<unsigned>(r+0.5);
00133 }
00134
00135 bool brip_filter_bank::save_filter_responses(vcl_string const& dir) const
00136 {
00137 if (!vul_file::is_directory(dir)) {
00138 vcl_cout << "filepath is not a directory in brip_filter_bank::save_filter_responses(.)\n";
00139 return false;
00140 }
00141 for (unsigned level = 0; level<n_levels_; ++level) {
00142 vcl_stringstream str;
00143 str << "/filter_response_" << level << ".tiff" << vcl_ends;
00144 vcl_string path = dir + str.str();
00145 vil_save(filter_responses_[level], path.c_str());
00146 }
00147 return true;
00148 }
00149
00150 vcl_ostream& operator<<(vcl_ostream& s, brip_filter_bank const& r)
00151 {
00152 s << "size:(" << r.ni() << ' ' << r.nj() << ") n_levels:" << r.n_levels()
00153 << " scale ratio:" << r.scale_ratio() << '\n'
00154 << "lambda0:" << r.lambda0() << " lambda1:" << r.lambda1()
00155 << " theta_interval:" << r.theta_interval() << '\n';
00156 return s;
00157 }