1 #include "icam_view_sphere.h"
2 //:
3 // \file
4 #include "vpgl/vpgl_perspective_camera.h"
5 #include <vsph/vsph_camera_bounds.h>
6 
icam_view_sphere(vgl_box_3d<double> bb,double radius)7 icam_view_sphere::icam_view_sphere(vgl_box_3d<double> bb, double radius)
8 : view_sphere_(nullptr), ICAM_LOCAL_MIN_THRESH_(100)
9 {
10   // create the view sphere
11   view_sphere_ = new vsph_view_sphere<vsph_view_point<icam_view_metadata> > (bb, radius);
12 }
13 
create_view_points(double cap_angle,double view_angle,unsigned ni,unsigned nj)14 void icam_view_sphere::create_view_points(double cap_angle, double view_angle, unsigned ni, unsigned nj)
15 {
16   // create the view points
17   view_sphere_->add_uniform_views(cap_angle, view_angle,ni,nj);
18 }
19 
20 //: returns the cameras of the view points, associated with the view point id
cameras(std::map<unsigned,vpgl_camera_double_sptr> & cameras)21 void icam_view_sphere::cameras(std::map<unsigned, vpgl_camera_double_sptr> &cameras)
22 {
23   auto it=view_sphere_->begin();
24   while (it != view_sphere_->end()) {
25     vsph_view_point<icam_view_metadata> vp = it->second;
26     unsigned id = it->first;
27     cameras[id] = vp.camera();
28     it++;
29   }
30 }
31 
set_cameras(std::map<unsigned,vpgl_camera_double_sptr> const & cameras)32 void icam_view_sphere::set_cameras(std::map<unsigned, vpgl_camera_double_sptr> const &cameras)
33 {
34   auto it=view_sphere_->begin();
35   auto cam_it=cameras.begin();
36   while (it != view_sphere_->end() && cam_it != cameras.end()) {
37     vpgl_camera_double_sptr cam = cam_it->second;
38     it->second.set_camera(cam);
39     auto* pers_cam = static_cast<vpgl_perspective_camera<double>*>(cam.as_pointer());
40     vgl_homg_point_3d<double> center = pers_cam->camera_center();
41     vsph_spherical_coord coord;
42     vsph_sph_point_3d sp;
43     coord.spherical_coord(center, sp);
44     it->second.set_view_point(sp);
45     it++;
46     cam_it++;
47   }
48 }
49 
50 //: sets the images and depth images, associated with the view point id
set_images(std::map<unsigned,std::string> & images,std::map<unsigned,std::string> & depth_images)51 void icam_view_sphere::set_images(std::map<unsigned, std::string>& images,
52                                   std::map<unsigned, std::string>& depth_images)
53 {
54   auto it_imgs=images.begin();
55   while (it_imgs != images.end()) {
56     unsigned uid = it_imgs->first;
57     if (images[uid].size()>0) {
58       // make sure that there is a corresponding depth image
59       if (depth_images.find(uid) != depth_images.end()) {
60         vsph_view_point<icam_view_metadata>* vp;
61         if (view_sphere_->view_point(uid, vp)) {
62           // get the camera
63           vpgl_camera_double_sptr camera=vp->camera();
64           auto* cam = dynamic_cast<vpgl_perspective_camera<double>*> (camera.as_pointer());
65           if (cam) {
66             icam_view_metadata* data = new icam_view_metadata(images[uid],depth_images[uid]);
67             vp->set_metadata(data);
68           }
69         }
70       }
71       else
72         std::cout << "icam_view_sphere::set_images -- ERROR! There is a missing depth image for image id=" << uid << std::endl;
73     }
74     it_imgs++;
75   }
76 }
77 
register_image(vil_image_view<float> const & dest_img,icam_minimizer_params const & params)78 void icam_view_sphere::register_image(vil_image_view<float> const& dest_img,
79                                       icam_minimizer_params const& params)
80 {
81   // try to find the best camera at each view point and at the end we will
82   // have errors to compare on the view sphere
83   auto it=view_sphere_->begin();
84   unsigned index = 0;
85   while (it != view_sphere_->end()) {
86     vsph_view_point<icam_view_metadata> vp = it->second;
87     icam_view_metadata* data=vp.metadata();
88     if (data) {
89       vpgl_camera_double_sptr camera=vp.camera();
90       std::cout << "Evaluating viewpoint " << index << '\n';
91       data->register_image(dest_img, camera, params);
92     }
93     it++; index++;
94   }
95 
96   std::vector<vsph_view_point<icam_view_metadata> > local_min;
97   find_local_minima(local_min);
98 #if 0
99   std::vector<vsph_view_point<icam_view_metadata> > local_min;
100   vsph_view_point<icam_view_metadata>* vp;
101   view_sphere_->view_point(85,vp);
102   vpgl_perspective_camera<double>* cam = (vpgl_perspective_camera<double>*)vp->camera().as_pointer();
103   std::cout << *cam;
104   local_min.push_back(*vp);
105   //vsph_view_point<icam_view_metadata>* vp;
106   view_sphere_->view_point(87,vp);
107   cam = (vpgl_perspective_camera<double>*)vp->camera().as_pointer();
108   std::cout << *cam;
109   local_min.push_back(*vp);
110   //vsph_view_point<icam_view_metadata>* vp;
111   view_sphere_->view_point(88,vp);
112   cam = (vpgl_perspective_camera<double>*)vp->camera().as_pointer();
113   std::cout << *cam;
114   local_min.push_back(*vp);
115 #endif
116   double cam_cost=1e99; // will become min cost, so initialise with high value
117   for (unsigned i=0; i<local_min.size(); i++) {
118     std::cout << "Local MINIMA " << i << "--" << local_min[i].view_point() << std::endl;
119     auto* gt_cam =
120       dynamic_cast<vpgl_perspective_camera<double>* >(ground_truth_cam_.as_pointer());
121     if (gt_cam) {
122       vpgl_perspective_camera<double>* cam = (vpgl_perspective_camera<double>*)local_min[i].camera().as_pointer();
123       vgl_rotation_3d<double> rel_rot;
124       vgl_vector_3d<double> rel_trans;
125       vsph_camera_bounds::relative_transf(*gt_cam, *cam,rel_rot,rel_trans);
126       std::cout <<"***************************************\n"
127                << "Rel Rot=" << rel_rot << '\n'
128                << "Rel trans=" << rel_trans << '\n'
129                <<"***************************************" << std::endl;
130     }
131     icam_view_metadata* md = local_min[i].metadata();
132     md->refine_camera(dest_img, local_min[i].camera(),params);
133     if (md->cost() < cam_cost) {
134       cam_cost = md->cost();
135     }
136   }
137 }
138 
find_local_minima(std::vector<vsph_view_point<icam_view_metadata>> & local_minima)139 void icam_view_sphere::find_local_minima(std::vector<vsph_view_point<icam_view_metadata> >& local_minima)
140 {
141   // go through all the viewpoints to see if it is a local maxima
142   auto it=view_sphere_->begin();
143   while (it != view_sphere_->end()) {
144     vsph_view_point<icam_view_metadata> vp = it->second;
145     unsigned vp_uid = it->first;
146     if (!vp.metadata()) {
147       it++;
148       continue;
149     }
150     double cost=vp.metadata()->cost();
151 
152     // find the closest neighbors' errors
153     std::vector<vsph_view_point<icam_view_metadata> > neighbors;
154     view_sphere_->find_neighbors(vp_uid, neighbors);
155     // compare the errors with the neighbors
156     bool smallest=true;
157     double smallest_diff=1e308;
158     for (auto vp : neighbors) {
159       icam_view_metadata* data = vp.metadata();
160       if (data) {
161         if (data->cost() < cost) {
162           smallest=false;
163         }
164         else {
165           double diff = data->cost()-cost;
166           if (smallest_diff > diff)
167             smallest_diff = diff;
168         }
169       }
170     }
171     if (smallest) { // && smallest_diff > ICAM_LOCAL_MIN_THRESH_
172       // the smallest should be really different, and much smaller than the neighborhood
173       std::cout << " Selected-->" << vp_uid << " how far?=" << smallest_diff << std::endl;
174       local_minima.push_back(vp);
175     }
176     it++;
177   }
178 }
179 
camera_transf(vpgl_perspective_camera<double> const & cam)180 void icam_view_sphere::camera_transf(vpgl_perspective_camera<double> const& cam)
181 {
182   auto it=view_sphere_->begin();
183   while (it != view_sphere_->end()) {
184     vsph_view_point<icam_view_metadata> vp = it->second;
185     if (!vp.metadata()) {
186       it++;
187       continue;
188     }
189     unsigned vp_uid = it->first;
190     vpgl_perspective_camera<double>* vp_cam = static_cast<vpgl_perspective_camera<double>*>(vp.camera().as_pointer());
191     vgl_rotation_3d<double> rel_rot;
192     vgl_vector_3d<double> rel_trans;
193     vsph_camera_bounds::relative_transf(cam, *vp_cam,rel_rot,rel_trans);
194     std::cout <<"***************************************\n"
195              << "VIEW POINT " << vp_uid << '\n'
196              << "Rel Rot=" << rel_rot << '\n'
197              << "Rel trans=" << rel_trans << '\n'
198              <<"***************************************" << std::endl;
199   }
200 }
201 
202 //: the mapped source image and actual destination image at a level
mapped_image(unsigned viewpoint_id,vil_image_view<float> const & source_img,vgl_rotation_3d<double> & rot,vgl_vector_3d<double> & trans,unsigned level,vil_image_view<float> & act_dest,vil_image_view<float> & mapped_dest,icam_minimizer_params const & params)203 void icam_view_sphere::mapped_image(unsigned viewpoint_id,
204                                     vil_image_view<float> const& source_img,
205                                     vgl_rotation_3d<double>& rot,
206                                     vgl_vector_3d<double>& trans,
207                                     unsigned level,
208                                     vil_image_view<float>& act_dest,
209                                     vil_image_view<float>& mapped_dest,
210                                     icam_minimizer_params const& params)
211 {
212   vsph_view_point<icam_view_metadata>* vp;
213   if (view_sphere_->view_point(viewpoint_id, vp)) {
214     icam_view_metadata* data=vp->metadata();
215     if (data) {
216       vpgl_perspective_camera<double>* vp_cam = static_cast<vpgl_perspective_camera<double>*>(vp->camera().as_pointer());
217       data->mapped_image(source_img, vp_cam, rot, trans, level, params, act_dest, mapped_dest);
218     }
219   }
220 }
221 
b_read(vsl_b_istream & is)222 void icam_view_sphere::b_read(vsl_b_istream &is)
223 {
224   if (!is)
225     return;
226   short version;
227   vsl_b_read(is, version);
228   switch (version)
229   {
230     case 1:
231     {
232       vsph_view_sphere<vsph_view_point<icam_view_metadata> > view_sphere;
233       vsl_b_read(is, view_sphere);
234       if (view_sphere_)
235         *view_sphere_ = view_sphere;
236       else
237         view_sphere_=new vsph_view_sphere<vsph_view_point<icam_view_metadata> >(view_sphere);
238     }
239     default:
240       std::cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&, icam_view_sphere&)\n"
241                << "           Unknown version number "<< version << '\n';
242       is.is().clear(std::ios::badbit); // Set an unrecoverable IO error on stream
243       break;
244   }
245 }
246 
b_write(vsl_b_ostream & os) const247 void icam_view_sphere::b_write(vsl_b_ostream &os) const
248 {
249   vsl_b_write(os, version());
250   vsl_b_write(os, *view_sphere_);
251 }
252 
vsl_b_read(vsl_b_istream & is,icam_view_sphere & sp)253 void vsl_b_read(vsl_b_istream &is, icam_view_sphere &sp)
254 {
255   sp.b_read(is);
256 }
257 
vsl_b_write(vsl_b_ostream & os,icam_view_sphere const & sp)258 void vsl_b_write(vsl_b_ostream &os, icam_view_sphere const& sp)
259 {
260   sp.b_write(os);
261 }
262 
vsl_b_read(vsl_b_istream & is,icam_view_sphere * sp)263 void vsl_b_read(vsl_b_istream &is, icam_view_sphere* sp)
264 {
265   sp->b_read(is);
266 }
267 
vsl_b_write(vsl_b_ostream & os,const icam_view_sphere * sp)268 void vsl_b_write(vsl_b_ostream &os, const icam_view_sphere* sp)
269 {
270   sp->b_write(os);
271 }
272