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