00001 #include "fhs_searcher.h"
00002
00003
00004
00005
00006
00007 #include <vcl_cassert.h>
00008 #include <vcl_cmath.h>
00009 #include <vcl_cstdlib.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vgl/vgl_vector_2d.h>
00013 #include <vil/vil_bilin_interp.h>
00014 #include <vil/algo/vil_quad_distance_function.h>
00015 #include <vimt/vimt_bilin_interp.h>
00016
00017
00018 fhs_searcher::fhs_searcher()
00019 : geom_wt_(1.0)
00020 {
00021 }
00022
00023
00024
00025
00026 void fhs_searcher::set_tree(const vcl_vector<fhs_arc>& arcs,
00027 unsigned root_node)
00028 {
00029 if (!fhs_order_tree_from_root(arcs,arc_,children_,root_node))
00030 {
00031 vcl_cerr<<"fhs_searcher::set_tree() Failed to set up the tree.\n";
00032 return;
00033 }
00034
00035
00036 arc_to_j_.resize(arc_.size()+1);
00037 for (unsigned i=0;i<arc_.size();++i)
00038 arc_to_j_[arc_[i].j()]=i;
00039 }
00040
00041
00042 void fhs_searcher::set_geom_wt(double geom_wt)
00043 {
00044 geom_wt_=geom_wt;
00045 }
00046
00047
00048
00049 unsigned fhs_searcher::root_node() const
00050 {
00051 assert(arc_.size()>0);
00052 return arc_[0].i();
00053 }
00054
00055
00056 void fhs_searcher::combine_responses(unsigned im_index,
00057 const vimt_image_2d_of<float>& feature_response)
00058 {
00059 sum_im_[im_index].deep_copy(feature_response);
00060
00061 for (unsigned ci = 0; ci<children_[im_index].size();++ci)
00062 {
00063 unsigned child_node = children_[im_index][ci];
00064 const fhs_arc& arc_to_c = arc_[arc_to_j_[child_node]];
00065
00066
00067
00068
00069
00070 vimt_transform_2d i2w = sum_im_[im_index].world2im().inverse();
00071 vimt_transform_2d c_w2i = sum_im_[child_node].world2im();
00072
00073 vgl_vector_2d<double> dp(arc_to_c.dx(),arc_to_c.dy());
00074
00075
00076 vgl_point_2d<double> p0 = c_w2i(i2w(0,0)+dp);
00077 vgl_point_2d<double> p1 = c_w2i(i2w(1,0)+dp);
00078 vgl_point_2d<double> p2 = c_w2i(i2w(0,1)+dp);
00079 vgl_vector_2d<double> dx = p1-p0;
00080 vgl_vector_2d<double> dy = p2-p0;
00081
00082 bool is_int_transform = (vcl_fabs(dx.x()-1)<1e-4) &&
00083 (vcl_fabs(dx.y() )<1e-4) &&
00084 (vcl_fabs(dy.x() )<1e-4) &&
00085 (vcl_fabs(dy.y()-1)<1e-4);
00086
00087 vil_image_view<float>& sum_image = sum_im_[im_index].image();
00088 unsigned ni = sum_image.ni();
00089 unsigned nj = sum_image.nj();
00090 float* s_data = sum_image.top_left_ptr();
00091 vcl_ptrdiff_t s_istep = sum_image.istep();
00092 vcl_ptrdiff_t s_jstep = sum_image.jstep();
00093 unsigned cni = dist_im_[child_node].image().ni();
00094 unsigned cnj = dist_im_[child_node].image().nj();
00095 const float* c_data = dist_im_[child_node].image().top_left_ptr();
00096 vcl_ptrdiff_t c_istep = dist_im_[child_node].image().istep();
00097 vcl_ptrdiff_t c_jstep = dist_im_[child_node].image().jstep();
00098
00099 if (is_int_transform)
00100 {
00101
00102 int ci0 = vnl_math_rnd(p0.x());
00103 int cj = vnl_math_rnd(p0.y());
00104 const float * c_row = c_data + cj*c_jstep + ci0*c_istep;
00105 float *s_row = s_data;
00106 for (unsigned j=0;j<nj;++j,++cj,c_row+=c_jstep,s_row+=s_jstep)
00107 {
00108 int ci = ci0;
00109 const float *c_pix = c_row;
00110 float * s_pix = s_row;
00111
00112 if (cj<0 || (unsigned int)cj+1>=cnj)
00113 {
00114 for (unsigned i=0;i<ni;++i, s_pix+=s_istep)
00115 *s_pix += 9999;
00116 }
00117 else
00118 {
00119 for (unsigned i=0;i<ni;++i,++ci,c_pix+=c_istep, s_pix+=s_istep)
00120 {
00121 if (ci<0 || (unsigned int)ci+1>=cni)
00122 *s_pix += 9999;
00123 else
00124 *s_pix += *c_pix;
00125 }
00126 }
00127 }
00128 }
00129 else
00130 {
00131 for (unsigned j=0;j<nj;++j)
00132 for (unsigned i=0;i<ni;++i)
00133 {
00134
00135 vgl_point_2d<double> p = c_w2i(i2w(i,j)+dp);
00136
00137 if (p.x()<0 || p.y()<0 || p.x()+1>=cni || p.y()+1>=cnj)
00138 sum_image(i,j) += 9999.0f;
00139 else
00140 sum_image(i,j) += (float)vil_bilin_interp_unsafe(p.x(),p.y(),
00141 c_data,c_istep,c_jstep);
00142 }
00143 }
00144 }
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 void fhs_searcher::search(const vcl_vector<vimt_image_2d_of<float> >& feature_response)
00156 {
00157 assert(feature_response.size()==n_points());
00158
00159 sum_im_.resize(n_points());
00160 dist_im_.resize(n_points());
00161 pos_im_.resize(n_points());
00162
00163
00164 for (int a=int(arc_.size())-1; a>=0; --a)
00165 {
00166
00167 unsigned node_a = arc_[a].j();
00168
00169
00170
00171
00172 combine_responses(node_a,feature_response[node_a]);
00173
00174
00175 const vimt_transform_2d& w2im = feature_response[node_a].world2im();
00176 double sx = w2im.delta(vgl_point_2d<double>(0,0),
00177 vgl_vector_2d<double>(1,0)).length();
00178 double sy = w2im.delta(vgl_point_2d<double>(0,0),
00179 vgl_vector_2d<double>(0,1)).length();
00180
00181
00182 vil_quad_distance_function(sum_im_[node_a].image(),
00183 geom_wt_/(sx*sx*arc_[a].var_x()),
00184 geom_wt_/(sy*sy*arc_[a].var_y()),
00185 dist_im_[node_a].image(),
00186 pos_im_[node_a].image());
00187 dist_im_[node_a].set_world2im(sum_im_[node_a].world2im());
00188 pos_im_[node_a].set_world2im(sum_im_[node_a].world2im());
00189 }
00190
00191
00192 unsigned root_node = arc_[0].i();
00193 combine_responses(root_node,feature_response[root_node]);
00194
00195
00196 }
00197
00198
00199
00200 void fhs_searcher::points_from_root(const vgl_point_2d<double>& root_pt,
00201 vcl_vector<vgl_point_2d<double> >& pts) const
00202 {
00203 if (n_points()<2)
00204 {
00205 vcl_cerr<<"fhs_searcher::points_from_root() Not initialised.\n";
00206 vcl_abort();
00207 }
00208
00209 pts.resize(n_points());
00210 pts[root_node()]=root_pt;
00211
00212
00213
00214 for (vcl_vector<fhs_arc>::const_iterator a=arc_.begin();a!=arc_.end();++a)
00215 {
00216
00217 vgl_point_2d<double> p_j0 = pts[a->i()]
00218 +vgl_vector_2d<double>(a->dx(),a->dy());
00219
00220
00221 double px = vimt_bilin_interp_safe(pos_im_[a->j()],p_j0,0);
00222 double py = vimt_bilin_interp_safe(pos_im_[a->j()],p_j0,1);
00223
00224 pts[a->j()] = pos_im_[a->j()].world2im().inverse()(px,py);
00225 }
00226 }
00227
00228 static vgl_point_2d<int> min_image_point(const vil_image_view<float>& image)
00229 {
00230 const unsigned ni=image.ni(),nj=image.nj();
00231 const vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00232 const float* row = image.top_left_ptr();
00233 unsigned best_i=0,best_j=0;
00234 float min_val = *row;
00235 for (unsigned j=0;j<nj;++j,row+=jstep)
00236 {
00237 const float* pixel = row;
00238 for (unsigned i=0;i<ni;++i,pixel+=istep)
00239 if (*pixel<min_val) {min_val=*pixel, best_i=i; best_j=j; }
00240 }
00241
00242 return vgl_point_2d<int>(best_i,best_j);
00243 }
00244
00245
00246
00247 double fhs_searcher::best_points(vcl_vector<vgl_point_2d<double> >& pts) const
00248 {
00249
00250 vgl_point_2d<int> p_im = min_image_point(sum_im_[root_node()].image());
00251 vgl_point_2d<double> root_pt = sum_im_[root_node()].world2im().inverse()(p_im.x(),p_im.y());
00252 points_from_root(root_pt,pts);
00253
00254 return sum_im_[root_node()].image()(p_im.x(),p_im.y());
00255 }
00256
00257
00258 const vimt_image_2d_of<float>& fhs_searcher::root_cost_image() const
00259 {
00260 return sum_im_[root_node()];
00261 }