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