00001 #include "vpgl_rational_adjust_onept.h"
00002
00003
00004 #include <vcl_cmath.h>
00005 #include <vcl_cassert.h>
00006 #include <vgl/vgl_plane_3d.h>
00007 #include <vgl/vgl_point_3d.h>
00008 #include <vnl/vnl_numeric_traits.h>
00009 #include <vnl/algo/vnl_levenberg_marquardt.h>
00010 #include <vpgl/algo/vpgl_backproject.h>
00011 #include <vpgl/algo/vpgl_ray_intersect.h>
00012
00013 #include <vcl_limits.h>
00014
00015
00016
00017 static const double vpgl_trans_z_step = 30.0;
00018 static double
00019 scatter_var(vcl_vector<vpgl_rational_camera<double> > const& cams,
00020 vcl_vector<vgl_point_2d<double> > const& image_pts,
00021 vgl_point_3d<double> const& initial_pt,
00022 double elevation, double& xm, double& ym)
00023 {
00024 unsigned int n = cams.size();
00025 vgl_plane_3d<double> pl(0, 0, 1, -elevation);
00026 double xsq = 0, ysq = 0;
00027 xm = 0; ym = 0;
00028 for (unsigned int i = 0; i<n; ++i)
00029 {
00030 vgl_point_3d<double> pb_pt;
00031 if (!vpgl_backproject::bproj_plane(cams[i],
00032 image_pts[i], pl,
00033 initial_pt, pb_pt))
00034 return false;
00035 double x = pb_pt.x(), y = pb_pt.y();
00036 xm+=x; ym +=y;
00037 xsq+=x*x; ysq+=y*y;
00038 }
00039 xm/=n; ym/=n;
00040 double xvar = xsq-(n*xm*xm);
00041 double yvar = ysq-(n*ym*ym);
00042 xvar/=n; yvar/=n;
00043 double var = vcl_sqrt(xvar*xvar + yvar*yvar);
00044 return var;
00045 }
00046
00047 vpgl_z_search_lsqr::
00048 vpgl_z_search_lsqr(vcl_vector<vpgl_rational_camera<double> > const& cams,
00049 vcl_vector<vgl_point_2d<double> > const& image_pts,
00050 vgl_point_3d<double> const& initial_pt)
00051 : vnl_least_squares_function(1, 1,
00052 vnl_least_squares_function::no_gradient ),
00053 initial_pt_(initial_pt),
00054 cameras_(cams),
00055 image_pts_(image_pts),
00056 xm_(0), ym_(0)
00057 {}
00058
00059 void vpgl_z_search_lsqr::f(vnl_vector<double> const& elevation,
00060 vnl_vector<double>& variance)
00061 {
00062 variance[0] = scatter_var(cameras_, image_pts_,initial_pt_, elevation[0], xm_, ym_);
00063 }
00064
00065 bool vpgl_rational_adjust_onept::
00066 find_intersection_point(vcl_vector<vpgl_rational_camera<double> > const& cams,
00067 vcl_vector<vgl_point_2d<double> > const& corrs,
00068 vgl_point_3d<double>& p_3d)
00069 {
00070 unsigned int n = cams.size();
00071 if (!n || n!=corrs.size())
00072 return false;
00073
00074 double x0=0, y0=0;
00075
00076 double zmax = vnl_numeric_traits<double>::maxval, zmin = -zmax;
00077 for (vcl_vector<vpgl_rational_camera<double> >::const_iterator cit = cams.begin(); cit != cams.end(); ++cit)
00078 {
00079 x0+=(*cit).offset(vpgl_rational_camera<double>::X_INDX);
00080 y0+=(*cit).offset(vpgl_rational_camera<double>::Y_INDX);
00081
00082 double zoff = (*cit).offset(vpgl_rational_camera<double>::Z_INDX);
00083 double zscale = (*cit).scale(vpgl_rational_camera<double>::Z_INDX);
00084 double zplus = zoff+zscale;
00085 double zminus = zoff-zscale;
00086 if (zminus>zmin) zmin = zminus;
00087 if (zplus<zmax) zmax = zplus;
00088 }
00089 assert(zmin<=zmax);
00090 x0/=n; y0/=n;
00091
00092 double error = vnl_numeric_traits<double>::maxval;
00093 vgl_point_3d<double> initial_point(x0, y0, zmin);
00094 double xopt=0, yopt=0, zopt = 0;
00095 for (double z = zmin; z<=zmax; z+=vpgl_trans_z_step)
00096 {
00097 double xm = 0, ym = 0;
00098 double var = scatter_var(cams, corrs,initial_point, z, xm, ym);
00099 if (var<error)
00100 {
00101 error = var;
00102 xopt = xm;
00103 yopt = ym;
00104 zopt = z;
00105 }
00106 initial_point.set(xm, ym, z);
00107 #ifdef TRANS_ONE_DEBUG
00108 vcl_cout << z << '\t' << var << '\n';
00109 #endif
00110 }
00111
00112
00113 if (zopt == zmin||zopt == zmax)
00114 return false;
00115 p_3d.set(xopt, yopt, zopt);
00116 return true;
00117 }
00118
00119 bool vpgl_rational_adjust_onept::
00120 refine_intersection_pt(vcl_vector<vpgl_rational_camera<double> > const& cams,
00121 vcl_vector<vgl_point_2d<double> > const& image_pts,
00122 vgl_point_3d<double> const& initial_pt,
00123 vgl_point_3d<double>& final_pt)
00124 {
00125 vpgl_z_search_lsqr zsf(cams, image_pts, initial_pt);
00126 vnl_levenberg_marquardt levmarq(zsf);
00127 #ifdef TRANS_ONE_DEBUG
00128 levmarq.set_verbose(true);
00129 #endif
00130
00131
00132 levmarq.set_x_tolerance(1e-10);
00133
00134
00135 levmarq.set_epsilon_function(1);
00136
00137
00138
00139 levmarq.set_f_tolerance(1e-15);
00140
00141
00142 levmarq.set_max_function_evals(10000);
00143
00144 vnl_vector<double> elevation(1);
00145 elevation[0]=initial_pt.z();
00146
00147
00148 levmarq.minimize(elevation);
00149 #ifdef TRANS_ONE_DEBUG
00150 levmarq.diagnose_outcome();
00151 #endif
00152 final_pt.set(zsf.xm(), zsf.ym(), elevation[0]);
00153 return true;
00154 }
00155
00156 bool vpgl_rational_adjust_onept::
00157 adjust(vcl_vector<vpgl_rational_camera<double> > const& cams,
00158 vcl_vector<vgl_point_2d<double> > const& corrs,
00159 vcl_vector<vgl_vector_2d<double> >& cam_translations,
00160 vgl_point_3d<double>& final)
00161 {
00162 cam_translations.clear();
00163 vgl_point_3d<double> intersection;
00164 if (!find_intersection_point(cams, corrs,intersection))
00165 return false;
00166
00167 if (!refine_intersection_pt(cams, corrs,intersection, final))
00168 return false;
00169 vcl_vector<vpgl_rational_camera<double> >::const_iterator cit = cams.begin();
00170 vcl_vector<vgl_point_2d<double> >::const_iterator rit = corrs.begin();
00171 for (; cit!=cams.end() && rit!=corrs.end(); ++cit, ++rit)
00172 {
00173 vgl_point_2d<double> uvp = (*cit).project(final);
00174 vgl_point_2d<double> uv = *rit;
00175 vgl_vector_2d<double> t(uv.x()-uvp.x(), uv.y()-uvp.y());
00176 cam_translations.push_back(t);
00177 }
00178 return true;
00179 }