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