vpgl_backproject.cxx
Go to the documentation of this file.
1 #include "vpgl_backproject.h"
2 //:
3 // \file
5 #include <vgl/vgl_point_2d.h>
6 #include <vgl/vgl_point_3d.h>
7 #include <vgl/vgl_plane_3d.h>
8 #include <vnl/algo/vnl_amoeba.h>
9 #include <vgl/vgl_intersection.h>
11 #include <vnl/vnl_random.h>
12 
13 //: Backproject an image point onto a plane, start with initial_guess
15  vnl_double_2 const& image_point,
16  vnl_double_4 const& plane,
17  vnl_double_3 const& initial_guess,
18  vnl_double_3& world_point,
19  double error_tol,
20  double relative_diameter)
21 {
22  // special case of a generic camera
23  if (cam->type_name()=="vpgl_generic_camera")
24  {
27  vgl_plane_3d<double> gplane(plane[0], plane[1], plane[2], plane[3]);
28  const auto* gcam = dynamic_cast<const vpgl_generic_camera<double>*>(cam);
29  ray = gcam->ray(image_point[0], image_point[1]);
30  if (!vgl_intersection<double>(ray, gplane, ipt))
31  return false;
32  world_point[0]=ipt.x(); world_point[1]=ipt.y(); world_point[2]=ipt.z();
33  return true;
34  }
35  // general case
36  vpgl_invmap_cost_function cf(image_point, plane, cam);
37  vnl_double_2 x1(0.000, 0.0000);
38  cf.set_params(initial_guess, x1);
39  vnl_amoeba amoeba(cf);
40  amoeba.set_max_iterations(100000);
41  amoeba.set_relative_diameter(relative_diameter);
42  amoeba.set_zero_term_delta(0.025);
43  vnl_vector<double> x(&x1[0], 2);
44  amoeba.minimize(x);
45  x1 = x;
46  cf.point_3d(x1, world_point);
47  double u=0, v=0, X=world_point[0], Y=world_point[1], Z=world_point[2];
48  cam->project(X, Y, Z, u, v);
49  vnl_double_2 final_proj;
50  final_proj[0]=u; final_proj[1]=v;
51  double err = (final_proj-image_point).magnitude();
52  // was: double err = std::sqrt(cf.f(x));
53  if (err > error_tol) // greater than a 20th of a pixel
54  {
55  std::cerr << "ERROR: backprojection error = " << err << std::endl;
56  return false;
57  }
58  return true;
59 }
60 
61  // vgl interface
62 
63 //: Backproject an image point onto a plane, start with initial_guess
65  vgl_point_2d<double> const& image_point,
66  vgl_plane_3d<double> const& plane,
67  vgl_point_3d<double> const& initial_guess,
68  vgl_point_3d<double>& world_point,
69  double error_tol,
70  double relative_diameter)
71 {
72  //simply convert to vnl interface
73  vnl_double_2 ipt;
74  vnl_double_3 ig, wp;
75  vnl_double_4 pl;
76  ipt[0]=image_point.x(); ipt[1]=image_point.y();
77  pl[0]=plane.a(); pl[1]=plane.b(); pl[2]=plane.c(); pl[3]=plane.d();
78  ig[0]=initial_guess.x(); ig[1]=initial_guess.y(); ig[2]=initial_guess.z();
79  bool success = vpgl_backproject::bproj_plane(cam, ipt, pl, ig, wp, error_tol, relative_diameter);
80  world_point.set(wp[0], wp[1], wp[2]);
81  return success;
82 }
83 
84 
85 //: Backproject an image point onto a world plane
87  vnl_double_2 const& image_point,
88  vnl_double_4 const& plane,
89  vnl_double_3 const& initial_guess,
90  vnl_double_3& world_point,
91  double error_tol,
92  double relative_diameter)
93 {
94  const auto* cam = static_cast<const vpgl_camera<double>* >(&rcam);
95  return bproj_plane(cam, image_point, plane, initial_guess, world_point, error_tol, relative_diameter);
96 }
97 
98 //: Backproject an image point onto a world plane
100  vgl_point_2d<double> const& image_point,
101  vgl_plane_3d<double> const& plane,
102  vgl_point_3d<double> const& initial_guess,
103  vgl_point_3d<double>& world_point,
104  double error_tol,
105  double relative_diameter)
106 {
107  const auto* const cam = static_cast<const vpgl_camera<double>* >(&rcam);
108  return bproj_plane(cam, image_point, plane, initial_guess, world_point, error_tol, relative_diameter);
109 }
110 
111 //Only the direction of the vector is important so it can be
112 //normalized to a unit vector. Two rays can be constructed, one through
113 //point and one through a point formed by adding the vector to the point
114 bool
116  vgl_point_2d<double> const& point,
117  vgl_vector_2d<double> const& vect,
118  vgl_plane_3d<double>& plane)
119 {
120  vgl_homg_point_2d<double> hp(point);
121  //get a second point
122  vgl_vector_2d<double> vu = vect/vect.length();
123  vgl_point_2d<double> point_plus_vect = point + vu;
124  vgl_homg_point_2d<double> hp1(point_plus_vect);
125  vgl_homg_line_2d<double> hline(hp, hp1);
126  vgl_homg_plane_3d<double> hpl = cam.backproject(hline);
127  plane = vgl_plane_3d<double>(hpl);
128  //might add checks for ideal plane later
129  return true;
130 }
131 
132 
133 //: Use backprojection to determine direction to camera from 3-d point
135  vgl_point_3d<double> const& point,
136  vgl_vector_3d<double> &to_camera,
137  double error_tol,
138  double relative_diameter)
139 {
140  // assumes that camera is above point of interest
141  // project point to image, and backproject to another z-plane, vector points to sensor
142  vgl_point_2d<double> img_pt = cam.project(point);
143  constexpr double z_off = 10.0;
144  vgl_plane_3d<double> plane_high(0,0,1,-(point.z()+z_off));
145  vgl_point_3d<double> point_high;
146  vgl_point_3d<double> guess(point.x(),point.y(),point.z() + z_off);
147  if (!bproj_plane(cam, img_pt, plane_high, guess, point_high, error_tol, relative_diameter)) {
148  return false;
149  }
150  // this assumes camera z > point.z
151  to_camera = point_high - point;
152  // normalize vector
153  normalize(to_camera);
154 
155  return true;
156 
157 }
void project(const T x, const T y, const T z, T &u, T &v) const override
The generic camera interface. u represents image column, v image row.
void set_zero_term_delta(double d)
T a() const
void set_max_iterations(int n)
void set_params(vnl_vector_fixed< double, 3 > const &xyz, vnl_vector_fixed< double, 2 > &x)
set the parameter values from the 3-d point.
double length() const
void point_3d(vnl_vector_fixed< double, 2 > const &x, vnl_vector_fixed< double, 3 > &xyz)
get the 3-d point defined by the parameters (and the plane).
Type & z()
#define v
void minimize(vnl_vector< double > &x)
T b() const
static bool bproj_point_vector(vpgl_proj_camera< double > const &cam, vgl_point_2d< double > const &point, vgl_vector_2d< double > const &vect, vgl_plane_3d< double > &plane)
Backproject a point with associated direction vector in the image to a plane in 3-d,...
virtual vgl_homg_line_3d_2_points< T > backproject(const vgl_homg_point_2d< T > &image_point) const
Find the 3d ray that goes through the camera center and the provided image point.
Type & y()
void set_relative_diameter(double r)
T d() const
virtual std::string type_name() const
class identity functions for casting.
Definition: vpgl_camera.h:39
Type & x()
virtual void project(const T x, const T y, const T z, T &u, T &v) const =0
The generic camera interface. u represents image column, v image row.
static bool direction_to_camera(vpgl_local_rational_camera< double > const &cam, vgl_point_3d< double > const &point, vgl_vector_3d< double > &to_camera, double error_tol=0.05, double relative_diameter=1.0)
Use backprojection to determine direction to camera from 3-d point.
void set(Type px, Type py, Type pz)
The generic camera.
v & normalize(v &a)
static bool bproj_plane(const vpgl_camera< double > *cam, vnl_double_2 const &image_point, vnl_double_4 const &plane, vnl_double_3 const &initial_guess, vnl_double_3 &world_point, double error_tol=0.05, double relative_diameter=1.0)
Generic camera interfaces (pointer for abstract class).
T c() const
Methods for back_projecting from cameras to 3-d geometric structures.
Type & y()
Type & x()