1 #include <iostream>
2 #include <algorithm>
3 #include "volm_query.h"
4 //:
5 // \file
6 #include <bpgl/bpgl_camera_utils.h>
7 #include <volm/volm_spherical_container.h>
8 #include <bsol/bsol_algs.h>
9 #include "vil/vil_image_view.h"
10 #include "vil/vil_rgb.h"
11 #include "vil/vil_save.h"
12 #include "vsl/vsl_binary_io.h"
13 #include <volm/volm_io.h>
14 #include <volm/volm_tile.h>
15 #include <volm/volm_spherical_layers.h>
16 #ifdef _MSC_VER
17 # include "vcl_msvc_warnings.h"
18 #endif
19 #include <cassert>
20 #include <volm/volm_camera_space.h>
21 #include "vsl/vsl_vector_io.h"
22 #include "vsl/vsl_set_io.h"
23
24 #define TOL -1E-8
25
volm_query(const volm_camera_space_sptr & cam_space,std::string const & label_xml_file,std::string const & category_file,volm_spherical_container_sptr const & sph,volm_spherical_shell_container_sptr const & sph_shell)26 volm_query::volm_query(const volm_camera_space_sptr& cam_space,
27 std::string const& label_xml_file,
28 std::string const& category_file,
29 volm_spherical_container_sptr const& sph,
30 volm_spherical_shell_container_sptr const& sph_shell)
31 : cam_space_(cam_space), invalid_((unsigned char)255), sph_depth_(sph), sph_(sph_shell)
32 {
33 //the discrete rays defined on the sphere as x, y, z
34 query_points_ = sph_->cart_points();
35 query_size_ = (unsigned)query_points_.size();
36
37 // load the labelme xml to define depth_map_scene and associated default value of camera parameters
38 dm_ = new depth_map_scene;
39 std::string img_category;
40 volm_io::read_labelme(label_xml_file, category_file, dm_, img_category);
41 // the dimensions of the depth image
42 ni_ = dm_->ni();
43 nj_ = dm_->nj();
44 // the image may be downsampled to provide more efficient matching
45 log_downsample_ratio_ = 0;//initial scale = 1
46 // the larger dimension of the image
47 unsigned bigger = ni_ > nj_ ? ni_ : nj_;
48 // find the scale that keeps the largest image dimension > 500
49 while ((bigger>>log_downsample_ratio_) > 500)
50 ++log_downsample_ratio_;
51 std::cout << "log_downsample_ratio_: " << log_downsample_ratio_ << std::endl; // need flush
52
53 #if NO_CAM_SPACE_CLASS
54 //
55 // set the default camera hypothesis parameters
56 // based on img_category ( "desert" and "coast")
57 //
58 if (img_category == "desert") {
59 head_ = 0.0; head_d_ = 180.0; head_inc_ = 2.0;
60 tilt_ = 90.0; tilt_d_ = 20.0; tilt_inc_ = 2.0;
61 roll_ = 0.0; roll_d_ = 3.0; roll_inc_ = 2.0; // try +2 -2
62 tfov_ = 5.0; tfov_d_ = 5.0; tfov_inc_ = 2.0;
63 }
64 else if (img_category == "coast") {
65 // temporary use desert default
66 head_ = 0.0; head_d_ = 180.0; head_inc_ = 2.0;
67 tilt_ = 90.0; tilt_d_ = 0.0; tilt_inc_ = 2.0;
68 roll_ = 0.0; roll_d_ = 1.0; roll_inc_ = 1.0;
69 tfov_ = 5.0; tfov_d_ = 30.0; tfov_inc_ = 2.0;
70 }
71 else {
72 // undefined img category, use desert default
73 head_ = 0.0; head_d_ = 180.0; head_inc_ = 2.0;
74 tilt_ = 90.0; tilt_d_ = 20.0; tilt_inc_ = 2.0;
75 roll_ = 0.0; roll_d_ = 1.0; roll_inc_ = 1.0;
76 tfov_ = 5.0; tfov_d_ = 30.0; tfov_inc_ = 2.0;
77 }
78 // read the camera file but don't use the values
79 // use the default values instead
80 if (use_default_) {
81 double lat, lon, head, head_d, tilt, tilt_d, roll, roll_d, tfov, tfov_d, altitude;
82 // load the camera kml, fetch the camera value and deviation
83 // for now we don't trust angle params read from the camera file
84 volm_io::read_camera(cam_kml_file, ni_, nj_, head, head_d, tilt, tilt_d, roll, roll_d, tfov, tfov_d, altitude, lat, lon);
85 // overwrite roll deviation for now
86 altitude_ = 3.0;
87 roll_d_ = 3.0;
88 std::cout << "In volm_query() - default values are used:\nheading: "
89 << head_ << " dev: " << head_d_
90 << "\ntilt: " << tilt_ << " dev: " << tilt_d_
91 << "\nroll: " << roll_ << " dev: " << roll_d_
92 << " (hard-coded to 3 till .kml passes meaningful values!!)\n"
93 << "top_fov: " << tfov_ << " dev: " << tfov_d_
94 << " alt: " << altitude_ << std::endl;
95 }
96 else {//overwrite the camera parameters with those in the camera file
97 double lat, lon;
98 volm_io::read_camera(cam_kml_file, ni_, nj_, head_, head_d_, tilt_, tilt_d_, roll_, roll_d_, tfov_, tfov_d_, altitude_, lat, lon);
99 std::cout << "In volm_query() - values are read:\nheading: "
100 << head_ << " dev: " << head_d_
101 << "\ntilt: " << tilt_ << " dev: " << tilt_d_
102 << "\nroll: " << roll_ << " dev: " << roll_d_
103 << "\ntop_fov: " << tfov_ << " dev: " << tfov_d_
104 << " alt: " << altitude_ << std::endl;
105 }
106 #endif
107
108 altitude_ = cam_space_->altitude();
109 // create camera hypotheses
110 this->create_cameras();
111 std::cout << " volm_query has " << this->get_cam_num() << " cameras" << std::endl;
112 // generate polygon vector based on defined order
113 this->generate_regions();
114 ground_orient_ = volm_orient_table::ori_id["horizontal"];
115 sky_orient_ = volm_orient_table::ori_id["infinite"];
116 std::cout << "volm_query generated " << this->depth_regions().size() << " regions! ingesting...\n"; std::cout.flush();
117 // start to ingest query, with min_dist and order implemented
118 this->query_ingest();
119 // create offset vector
120 this->offset_ingest();
121 // start to ingest order, store in order_index_
122 this->order_ingest();
123 // implement the weight parameters for all objects
124 }
125
126 // build a query from an existing depth map scene
volm_query(const volm_camera_space_sptr & cam_space,std::string const & depth_map_scene_file,volm_spherical_shell_container_sptr const & sph_shell,volm_spherical_container_sptr const & sph)127 volm_query::volm_query(const volm_camera_space_sptr& cam_space,
128 std::string const& depth_map_scene_file,
129 volm_spherical_shell_container_sptr const& sph_shell,
130 volm_spherical_container_sptr const& sph)
131 : cam_space_(cam_space), invalid_((unsigned char)255), sph_depth_(sph), sph_(sph_shell)
132 {
133 //the discrete rays defined on the sphere as x, y, z
134 query_points_ = sph_->cart_points();
135 query_size_ = (unsigned)query_points_.size();
136
137 // load the depth_map_scene from depth_map_scene binary
138 dm_ = new depth_map_scene;
139 vsl_b_ifstream dis(depth_map_scene_file.c_str());
140 dm_->b_read(dis);
141 dis.close();
142 // the dimensions of the depth image
143 ni_ = dm_->ni();
144 nj_ = dm_->nj();
145 // the image may be downsampled to provide more efficient matching
146 log_downsample_ratio_ = 0;//initial scale = 1
147 // the larger dimension of the image
148 unsigned bigger = ni_ > nj_ ? ni_ : nj_;
149 // find the scale that keeps the largest image dimension > 500
150 while ((bigger>>log_downsample_ratio_) > 500)
151 ++log_downsample_ratio_;
152 std::cout << "log_downsample_ratio_: " << log_downsample_ratio_ << std::endl; // need flush
153
154 altitude_ = cam_space_->altitude();
155 this->create_cameras();
156 std::cout << " volm_query has " << this->get_cam_num() << " cameras" << std::endl;
157 // generate polygon vector based on defined order
158 this->generate_regions();
159 ground_orient_ = volm_orient_table::ori_id["horizontal"];
160 sky_orient_ = volm_orient_table::ori_id["infinite"];
161 std::cout << "volm_query generated " << this->depth_regions().size() << " regions! ingesting...\n"; std::cout.flush();
162 // start to ingest query, with min_dist and order implemented
163 this->query_ingest();
164 // create offset vector
165 this->offset_ingest();
166 // start to ingest order, store in order_index_
167 this->order_ingest();
168 // implement the weight parameters for all objects
169 //this->weight_ingest();
170 }
171
volm_query(std::string const & query_file,const volm_camera_space_sptr & cam_space,std::string const & depth_map_scene_file,volm_spherical_shell_container_sptr const & sph_shell,volm_spherical_container_sptr const & sph)172 volm_query::volm_query(std::string const& query_file, const volm_camera_space_sptr& cam_space,
173 std::string const& depth_map_scene_file,
174 volm_spherical_shell_container_sptr const& sph_shell,
175 volm_spherical_container_sptr const& sph)
176 : cam_space_(cam_space), invalid_((unsigned char)255), sph_depth_(sph), sph_(sph_shell)
177 {
178
179 //the discrete rays defined on the sphere as x, y, z
180 std::cout << "depth_map_scene_file = " << depth_map_scene_file << std::endl;
181
182 query_points_ = sph_->cart_points();
183 query_size_ = (unsigned)query_points_.size();
184
185 // load the depth_map_scene from depth_map_scene binary
186 dm_ = new depth_map_scene;
187 vsl_b_ifstream dis(depth_map_scene_file.c_str());
188
189 dm_->b_read(dis);
190 dis.close();
191 // the dimensions of the depth image
192 ni_ = dm_->ni();
193 nj_ = dm_->nj();
194 // the image may be downsampled to provide more efficient matching
195 log_downsample_ratio_ = 0;//initial scale = 1
196 // the larger dimension of the image
197 unsigned bigger = ni_ > nj_ ? ni_ : nj_;
198 // find the scale that keeps the largest image dimension > 500
199 while ((bigger>>log_downsample_ratio_) > 500)
200 ++log_downsample_ratio_;
201 //std::cout << "log_downsample_ratio_: " << log_downsample_ratio_ << std::endl; // need flush
202
203 depth_regions_ = dm_->scene_regions();
204 // sort the regions on depth order
205 std::sort(depth_regions_.begin(), depth_regions_.end(), compare_order());
206
207 altitude_ = cam_space_->altitude();
208
209 // read the rest from the binary file
210 vsl_b_ifstream dis_self(query_file.c_str());
211 this->read_data(dis_self);
212 dis_self.close();
213 std::cout << " volm_query has " << this->get_cam_num() << " cameras" << std::endl;
214 }
215
216
217 #if NO_CAM_SPACE_CLASS
218 // generate the set of camera hypotheses
219 // the camera space includes multiple
220 // choices for focal length, heading, tilt and roll
create_cameras()221 void volm_query::create_cameras()
222 {
223 // set up the camera parameter arrays and construct vector of cameras
224 if (use_default_)//define focal length search space
225 {
226 if (img_category == "desert") {
227 //field of view angle choices (degrees)
228 double stock[] = {18.0, 19.0,
229 20.0, 24.0, 26.0,
230 28.0, 30.0, 32.0};
231 //store in vector
232 if (ni_ >= nj_) { // landscape
233 top_fov_.insert(top_fov_.end(), stock, stock + 8);
234 }
235 else { // protrait, so take into account aspect ratio
236 double dtor = vnl_math::pi_over_180;
237 for (unsigned i = 0; i < 8; ++i) {
238 double tr = std::tan(stock[i]*dtor);
239 double top = std::atan(nj_*tr/ni_)/dtor;
240 top_fov_.push_back(top);
241 }
242 }
243 std::cout << " NOTE: default top field of view is used:\n\t[ ";
244 for (unsigned i = 0; i < 8; ++i)
245 std::cout << top_fov_[i] << ' ';
246 std::cout << ']' << std::endl;
247 }
248 else if (img_category == "coast") {
249 double stock[] = {3.0, 4.0, 5.0, 9.0,
250 15.0, 16.0,
251 20.0, 21.0, 22.0, 23.0, 24.0};
252 if (ni_ >= nj_) { // landscape
253 top_fov_.insert(top_fov_.end(), stock, stock + 11);
254 }
255 else { // protrait
256 double dtor = vnl_math::pi_over_180;
257 for (unsigned i = 0; i < 11; ++i) {
258 double tr = std::tan(stock[i]*dtor);
259 double top = std::atan(nj_*tr/ni_)/dtor;
260 top_fov_.push_back(top);
261 }
262 }
263 std::cout << " NOTE: default top field of view is used:\n\t[ ";
264 for (unsigned i = 0; i < 11; ++i)
265 std::cout << top_fov_[i] << ' ';
266 std::cout << ']' << std::endl;
267 }
268 else {
269 double stock[] = {3.0, 4.0, 5.0,
270 12.0, 17.0, 18.0,19.0,
271 20.0, 24.0};
272 top_fov_.insert(top_fov_.end(), stock, stock + 9);
273 std::cout << " NOTE: default top field of view is used:\n\t[ ";
274 for (unsigned i = 0; i < 9; ++i)
275 std::cout << top_fov_[i] << ' ';
276 std::cout << ']' << std::endl;
277 }
278 }// end use_default == true
279 else {
280 tfov_inc_ = 2.0;
281 #if 0
282 if (tfov_ < 10) tfov_inc_ = 1.0;
283 else if (tfov_ > 20) tfov_inc_ = 4.0;
284 else tfov_inc_ = 2.0;
285 #endif
286 top_fov_.push_back(tfov_); // top viewing ranges from 1 to 89
287 std::cout << "\t top_fov:\n\t " << tfov_ << ' ';
288 for (double i = tfov_inc_; i <= tfov_d_; i+=tfov_inc_) {
289 double right_fov = tfov_ + i, left_fov = tfov_ - i;
290 if (right_fov > 89) right_fov = 89;
291 if (left_fov < 1) left_fov = 1;
292 top_fov_.push_back(right_fov);
293 if (left_fov != right_fov) {
294 top_fov_.push_back(left_fov);
295 std::cout << right_fov << ' ' << left_fov << ' ';
296 }
297 else
298 std::cout << right_fov << ' ';
299 }
300 }
301 // store heading hypotheses
302 headings_.push_back(head_);
303 std::cout << "\n\t headings:\n\t " << head_ << ' ';
304 for (double i = head_inc_; i <= head_d_; i+= head_inc_) { // heading ranges from 0 to 360
305 double right_hd = head_ + i, left_hd = head_ - i;
306 if (right_hd > 360) right_hd = right_hd - 360;
307 if (left_hd < 0) left_hd = left_hd + 360;
308 headings_.push_back(right_hd);
309 if (left_hd != right_hd) {
310 headings_.push_back(left_hd); std::cout << right_hd << ' ' << left_hd << ' ';
311 }
312 else
313 std::cout << right_hd << ' ';
314 }
315 // store tilt hypotheses
316 std::cout << "\n\t tilts:\n\t " << tilt_ << ' ';
317 tilts_.push_back(tilt_); // tilt ranges from 0 to 180
318 for (double i = tilt_inc_; i <= tilt_d_; i+= tilt_inc_) {
319 double right_tlt = tilt_ + i, left_tlt = tilt_ - i;
320 if (right_tlt > 180) right_tlt = 180;
321 if (left_tlt < 0) left_tlt = 0;
322 tilts_.push_back(right_tlt); tilts_.push_back(left_tlt);
323 std::cout << right_tlt << ' ' << left_tlt << ' ';
324 }
325 // store roll hypotheses
326 std::cout << "\n\t rolls:\n\t " << roll_ << ' ';
327 rolls_.push_back(roll_); // roll ranges from -180 to 180 in kml, how about in camera_from_kml ?? (need to check...)
328 for (double i = roll_inc_; i <= roll_d_; i+=roll_inc_) {
329 double right_rol = roll_ + i , left_rol = roll_ - i;
330 if (right_rol > 180) right_rol = right_rol - 360;
331 if (left_rol < -180) left_rol = left_rol + 360;
332 rolls_.push_back(roll_ + i); rolls_.push_back(roll_ - i);
333 std::cout << right_rol << ' ' << left_rol << ' ';
334 }
335 std::cout << '\n';
336 std::cout.flush();
337
338 // construct the camera hypotheses
339 for (unsigned i = 0; i < tilts_.size(); ++i)
340 for (unsigned j = 0; j < rolls_.size(); ++j)
341 for (unsigned k = 0; k < top_fov_.size(); ++k)
342 for (unsigned h = 0; h < headings_.size(); ++h)
343 {
344 double tilt = tilts_[i], roll = rolls_[j], top_f = top_fov_[k], head = headings_[h];
345 double dtor = vnl_math::pi_over_180;
346 double ttr = std::tan(top_f*dtor);
347 double right_f = std::atan(ni_*ttr/nj_)/dtor;
348 vpgl_perspective_camera<double> cam = bpgl_camera_utils::camera_from_kml((double)ni_, (double)nj_, right_f, top_f, altitude_, head, tilt, roll);
349 // check whether current camera is consistent with defined ground plane
350 // that is, if the 2-d ground plane region actually projects onto the 3-d ground plane
351 bool success = true;
352 if (dm_->ground_plane().size()) {
353 for (unsigned i = 0; (success && i < dm_->ground_plane().size()); ++i) {
354 success = dm_->ground_plane()[i]->region_ground_2d_to_3d(cam);
355 #if 0
356 std::cout << "checking ground plane consistency for: " << dm_->ground_plane()[i]->name() << " min depth is: " << dm_->ground_plane()[i]->min_depth()
357 << ' ' << (success ? "" : "not_") << "consistent!\n"
358 #endif
359 }
360 if (success) {
361 cameras_.push_back(cam);
362 camera_strings_.push_back(bpgl_camera_utils::get_string((double)ni_, (double)nj_, right_f, top_f, altitude_, head, tilt, roll));
363 }
364 else
365 {
366 #if 0
367 std::cout << "WARNING: following camera hypothesis is NOT consistent with defined ground plane in the query image and ignored\n"
368 << " \t heading = " << head << ", tilt = " << tilt << ", roll = " << roll << ", top_fov = " << top_f << ", right_fov = " << right_f << std::endl;
369 #endif
370 }
371 }
372 else
373 {
374 cameras_.push_back(cam);
375 camera_strings_.push_back(bpgl_camera_utils::get_string((double)ni_, (double)nj_, right_f, top_f, altitude_, head, tilt, roll));
376 }
377 }
378 }
379 #endif
380
create_cameras()381 void volm_query::create_cameras()
382 {
383 // iterate over valid cameras in the camera space
384 std::vector<unsigned int> const& valid_cams = cam_space_->valid_indices();
385 for (unsigned int valid_cam : valid_cams) {
386 vpgl_perspective_camera<double> cam = cam_space_->camera(valid_cam);
387 cameras_.push_back(cam);
388 std::string cam_str = cam_space_->get_string(valid_cam);
389 camera_strings_.push_back(cam_str);
390 }
391 }
392
393 // convert min and max distances from scene depth regions to voxel indices
394 // insure consistent order indices
395 // obtain the maximum distance bound (meters)
generate_regions()396 void volm_query::generate_regions()
397 {
398 // generate the map of the depth_map_region based on their order
399 // a vector of regions not including sky or ground plane
400 depth_regions_ = dm_->scene_regions();
401 auto size = (unsigned)depth_regions_.size();
402 // sort the regions on depth order
403 std::sort(depth_regions_.begin(), depth_regions_.end(), compare_order());
404 // obtain the min and max dist for different non-ground, non-sky objects
405 // distances are in terms of voxel indices
406 for (unsigned i = 0; i < size; ++i) {
407 min_obj_dist_.push_back(sph_depth_->get_depth_interval(depth_regions_[i]->min_depth()));
408 max_obj_dist_.push_back(sph_depth_->get_depth_interval(depth_regions_[i]->max_depth()));
409 order_obj_.push_back((unsigned char)depth_regions_[i]->order());
410 obj_orient_.push_back((unsigned char)depth_regions_[i]->orient_type());
411
412 auto land_id = (unsigned char)depth_regions_[i]->land_id();
413 std::vector<unsigned char> land_fallback_id = volm_fallback_label::fallback_id[land_id];
414 obj_land_id_.push_back(land_fallback_id);
415 std::vector<float> land_fallback_wgt = volm_fallback_label::fallback_weight[land_id];
416 obj_land_wgt_.push_back(land_fallback_wgt);
417 }
418 d_threshold_ = 20000.0; //upper depth bound
419 for (unsigned i = 0; i < size; ++i) {
420 //depth_regions_[(dm_->scene_regions())[i]->order()] = (dm_->scene_regions())[i];
421 if (d_threshold_ < (dm_->scene_regions())[i]->max_depth())
422 d_threshold_ = (dm_->scene_regions())[i]->max_depth();
423 }
424 if (dm_->ground_plane().size()) {
425 for (unsigned i = 0; i < dm_->ground_plane().size(); ++i) {
426 if (d_threshold_ < dm_->ground_plane()[i]->max_depth())
427 d_threshold_ = dm_->ground_plane()[i]->max_depth();
428 }
429 }
430 // set a constant value for sky objects, which is equal to minimum order for all sky objects
431 // actually, order for sky shouldn't matter - JLM
432 if (dm_->sky().size()) {
433 order_sky_ = dm_->sky()[0]->order();
434 for (unsigned i = 1; i < dm_->sky().size(); ++i) {
435 if ( order_sky_ > dm_->sky()[i]->order() )
436 order_sky_ = dm_->sky()[i]->order();
437 }
438 }
439 // create the order_set for all non-ground region
440 // std::set<unsigned>
441 if (depth_regions_.size())
442 for (auto & depth_region : depth_regions_)
443 order_set_.insert(depth_region->order());
444 if (dm_->sky().size())
445 order_set_.insert(order_sky_);
446 }
447
order_ingest()448 bool volm_query::order_ingest()
449 {
450 // loop over camera hypotheses
451 auto cam_num = (unsigned)cameras_.size();
452 for (unsigned cam_id = 0; cam_id < cam_num; ++cam_id) {
453 // create a vector to store all objects and fetch the order for current layer
454 std::vector<std::vector<unsigned> > order_cam(order_set_.size());
455 std::vector<unsigned char> order_layer = order_[cam_id];
456 #if 0
457 std::cout << " --------------------- camera " << cam_id << " --------------------" << std::endl;
458 #endif
459 // loop over rays on query sphere
460 for (unsigned idx = 0; idx < query_size_; ++idx) {
461 unsigned count = 0;
462 //std::cout << " cam " << cam_id << ", order_layer[" << idx << "] = " << (int)order_layer[idx] << std::endl;
463 auto iter = this->order_set_.begin();
464 for ( ; iter != order_set_.end(); ++iter) {
465 if ( (int)order_layer[idx] == *iter) {
466 order_cam[count].push_back(idx);
467 break;
468 }
469 else {
470 ++count;
471 }
472 }
473 }
474 order_index_.push_back(order_cam);
475 } // loop over camera
476 return true;
477 }
478
479 // computes a set of spherical shell layers for each camera hypothesis
480 // the layer contents are indexed by the camera ray, p_idx
query_ingest()481 bool volm_query::query_ingest()
482 {
483 // loop over the set of camera hypotheses
484 for (const auto& cam : cameras_)
485 {
486 // the layers for camera hypothesis i
487 // the minimum distance for each ray
488 std::vector<unsigned char> min_dist_layer;
489 // the maximum distance for each ray
490 std::vector<unsigned char> max_dist_layer;
491 // the region order for each ray
492 std::vector<unsigned char> order_layer;
493 // the set of rays intersecting the ground plane
494 std::vector<unsigned> ground_id_layer;
495 // the ground plane distance for the ray
496 std::vector<unsigned char> ground_dist_layer;
497 // the ground plane land fallback class for the ray
498 std::vector<std::vector<unsigned char> > ground_land_layer;
499 // the ground pland land fallback class weight
500 std::vector<std::vector<float> > ground_land_wgt_layer;
501 // the set of rays intersecting sky
502 std::vector<unsigned> sky_id_layer;
503 // the set of rays for each non-gp, non-sky region
504 std::vector<std::vector<unsigned> > dist_id_layer(depth_regions_.size());
505 // put current camera into depth_map_scene
506 dm_->set_camera(cam);
507 // create an depth image for current camera if there is ground plane
508 vil_image_view<float> depth_img;
509 if (dm_->ground_plane().size()) {
510 depth_img = dm_->depth_map("ground_plane", log_downsample_ratio_, d_threshold_);
511 }
512
513 // loop over rays on sphere
514 unsigned count = 0;
515 for (unsigned p_idx = 0; p_idx < query_size_; ++p_idx)
516 {
517 vgl_point_3d<double> qp(query_points_[p_idx].x(), query_points_[p_idx].y(), query_points_[p_idx].z()+altitude_);
518 unsigned char min_dist, order, max_dist;
519 // check whether the point is behind the camera
520 if (cam.is_behind_camera(vgl_homg_point_3d<double>(qp))) {
521 min_dist_layer.push_back((unsigned char)255);
522 max_dist_layer.push_back((unsigned char)255);
523 order_layer.push_back((unsigned char)255);
524 }
525 else {
526 double u, v;
527 cam.project(qp.x(), qp.y(), qp.z(), u, v);
528 // compare (u, v) with depth_map_scene, return min_dist
529 if ( u > (double)ni_ || v > (double)nj_ || u < TOL || v < TOL) { // container point qp is outside camera viewing volume
530 min_dist_layer.push_back((unsigned char)255);
531 max_dist_layer.push_back((unsigned char)255);
532 order_layer.push_back((unsigned char)255);
533 }
534 else {
535 bool is_ground = false, is_sky = false, is_object = false;
536 unsigned obj_id;
537 std::vector<unsigned char> grd_fallback_id;
538 std::vector<float> grd_fallback_wgt;
539 min_dist = this->fetch_depth(u, v, order, max_dist, obj_id, grd_fallback_id, grd_fallback_wgt, is_ground, is_sky, is_object, depth_img);
540 min_dist_layer.push_back(min_dist);
541 max_dist_layer.push_back(max_dist);
542 order_layer.push_back(order);
543 if (is_ground) {
544 ground_id_layer.push_back(p_idx);
545 ground_dist_layer.push_back(min_dist);
546 ground_land_layer.push_back(grd_fallback_id);
547 ground_land_wgt_layer.push_back(grd_fallback_wgt);
548 }
549 else if (is_sky) {
550 sky_id_layer.push_back(p_idx);
551 }
552 else if (is_object) {
553 if (obj_id < depth_regions_.size()) {
554 dist_id_layer[obj_id].push_back(p_idx);
555 }
556 else {
557 std::cerr << "ERROR in query creation: object id exceeds the size of non-ground, non-sky objects\n";
558 return false;
559 }
560 }
561 if ((unsigned)min_dist != 255)
562 ++count;
563 }
564 }
565 } // loop over rays for current camera
566 min_dist_.push_back(min_dist_layer);
567 max_dist_.push_back(max_dist_layer);
568 order_.push_back(order_layer);
569 ground_id_.push_back(ground_id_layer);
570 ground_dist_.push_back(ground_dist_layer);
571 ground_land_id_.push_back(ground_land_layer);
572 ground_land_wgt_.push_back(ground_land_wgt_layer);
573 sky_id_.push_back(sky_id_layer);
574 dist_id_.push_back(dist_id_layer);
575 } // loop over cameras
576 return true;
577 }
578
579 // u, v defines the pixel location in a depth image
580 // depth image is the ground plane depth map
581 // returns min distance to depth region that contains
582 // u, v
offset_ingest()583 bool volm_query::offset_ingest()
584 {
585 auto n_cam = (unsigned)cameras_.size();
586 // create ground offset
587 unsigned count = 0;
588 ground_offset_.push_back(count);
589 for (unsigned cam_id = 0; cam_id < n_cam; ++cam_id) {
590 count += (unsigned)ground_id_[cam_id].size();
591 ground_offset_.push_back(count);
592 }
593
594 // create sky offset
595 count = 0;
596 sky_offset_.push_back(count);
597 for (unsigned cam_id = 0; cam_id < n_cam; ++cam_id) {
598 count += (unsigned)sky_id_[cam_id].size();
599 sky_offset_.push_back(count);
600 }
601
602 // create object offset
603 count = 0;
604 auto n_obj = (unsigned)depth_regions_.size();
605 dist_offset_.push_back(count);
606 for (unsigned cam_id = 0; cam_id < n_cam; ++cam_id)
607 for (unsigned obj_id = 0; obj_id < n_obj; ++obj_id) {
608 count += (unsigned)dist_id_[cam_id][obj_id].size();
609 dist_offset_.push_back(count);
610 }
611
612 return true;
613 }
614
fetch_depth(double const & u,double const & v,unsigned char & order,unsigned char & max_dist,unsigned & object_id,std::vector<unsigned char> & grd_fallback_id,std::vector<float> & grd_fallback_wgt,bool & is_ground,bool & is_sky,bool & is_object,vil_image_view<float> const & depth_img)615 unsigned char volm_query::fetch_depth(double const& u,
616 double const& v,
617 unsigned char& order,
618 unsigned char& max_dist,
619 unsigned& object_id,
620 std::vector<unsigned char>& grd_fallback_id,
621 std::vector<float>& grd_fallback_wgt,
622 bool& is_ground,
623 bool& is_sky,
624 bool& is_object,
625 vil_image_view<float> const& depth_img)
626 {
627 unsigned char min_dist;
628 // check other objects before ground,
629 // e.g., for overlap region of a building and ground, building is on the ground and it is must closer than the ground
630 // find if (u, v) is contained in non-ground, non-sky region
631 if (depth_regions_.size()) {
632 for (unsigned i = 0; i < depth_regions_.size(); ++i) {
633 vgl_polygon<double> poly = bsol_algs::vgl_from_poly(depth_regions_[i]->region_2d());
634 if (poly.contains(u,v)) {
635 is_object = true;
636 object_id = i;
637 double min_depth = depth_regions_[i]->min_depth();
638 if (min_depth < 0)
639 min_dist = (unsigned char)255;
640 else
641 min_dist = sph_depth_->get_depth_interval(min_depth);
642 double max_depth = depth_regions_[i]->max_depth();
643 if (max_depth < sph_depth_->min_voxel_res())
644 max_dist = (unsigned char)255;
645 else
646 max_dist = sph_depth_->get_depth_interval(max_depth);
647 order = (unsigned char)depth_regions_[i]->order();
648 return min_dist;
649 }
650 }
651 }
652 // not contained in a non-ground non_sky region, check ground_plane
653 if (dm_->ground_plane().size()) {
654 for (unsigned i = 0; i < dm_->ground_plane().size(); ++i) {
655 vgl_polygon<double> vgl_ground = bsol_algs::vgl_from_poly((dm_->ground_plane()[i])->region_2d());
656 if (vgl_ground.contains(u,v)) {
657 is_ground = true;
658 // get the depth of the pixel
659 // maybe better to do bilinear interpolation instead of casting to nearest pixel
660 int uu = (int)std::floor(u/(1<<log_downsample_ratio_)+0.5);
661 uu = uu < 0 ? 0 : uu;
662 uu = uu >= (int)depth_img.ni() ? depth_img.ni()-1 : uu;
663 int vv = (int)std::floor(v/(1<<log_downsample_ratio_)+0.5);
664 vv = vv < 0 ? 0 : vv;
665 vv = vv >= (int)depth_img.nj() ? depth_img.nj()-1 : vv;
666 float depth_uv = depth_img(uu,vv);
667 // handle the case where the voxel/ray is too close to ground_plane boundary
668 if (depth_uv < 0) {
669 #ifdef DEBUG
670 std::cout << " WARNING: point (" << (int)u << ',' << (int)v
671 << ") is too close to the ground boundary, disregarded." << std::endl;
672 #endif
673 is_ground = false;
674 max_dist = (unsigned char)255;
675 order = (unsigned char)255;
676 return (unsigned char)253; // invalid depth value
677 }
678 min_dist = sph_depth_->get_depth_interval(depth_uv);
679 max_dist = (unsigned char)255;
680 order = (unsigned char)(dm_->ground_plane()[i])->order();
681 unsigned char grd_land = dm_->ground_plane()[i]->land_id();
682 grd_fallback_id = volm_fallback_label::fallback_id[grd_land];
683 grd_fallback_wgt = volm_fallback_label::fallback_weight[grd_land];
684 return min_dist;
685 }
686 }
687 }
688 // check if (u, v) is contained in sky
689 // considered last since all objects should be closer than sky
690 if (dm_->sky().size()) {
691 for (unsigned i = 0; i < dm_->sky().size(); ++i) {
692 vgl_polygon<double> vgl_sky = bsol_algs::vgl_from_poly((dm_->sky()[i])->region_2d());
693 if (vgl_sky.contains(u,v)) {
694 is_sky = true;
695 max_dist = (unsigned char)254;
696 order = order_sky_;
697 return (unsigned char)254;
698 }
699 }
700 }
701 // the image points (u,v) is not inside any defined objectes
702 max_dist = (unsigned char)255;
703 order = (unsigned char)255;
704 return (unsigned char)255;
705 }
706
draw_template(std::string const & vrml_fname)707 void volm_query::draw_template(std::string const& vrml_fname)
708 {
709 // write the header and shell container first
710 sph_->draw_template(vrml_fname);
711 // write rays
712 //this->draw_rays(vrml_fname);
713 // write the camera
714 unsigned cam_num = this->get_cam_num();
715 for (unsigned i = 0; i < cam_num; ++i) {
716 float r = 0.0f;
717 float g = 0.0f;
718 float b = 0.0f;
719 if (i%2 == 0)
720 g = 1.0f;
721 else if (i%2 == 1) {
722 b = 1.0f; g = 0.0f;
723 }
724 else {
725 r = 0.0f; g = 1.0f;
726 }
727 this->draw_viewing_volume(vrml_fname, cameras_[i], r, g, b);
728 }
729 }
730
draw_rays(std::string const & fname)731 void volm_query::draw_rays(std::string const& fname)
732 {
733 std::ofstream ofs(fname.c_str(), std::ios::app);
734 double len = 800.0;
735 vgl_point_3d<double> ori(0.0,0.0,0.0);
736 for (unsigned i=0; i<query_size_; ++i) {
737 vgl_ray_3d<double> ray(ori, query_points_[i]);
738 bvrml_write::write_vrml_cylinder(ofs, ori, ray.direction(), (float)3.0, (float)len, 0.0f, 0.0f, 0.0f, 1);
739 }
740 }
741
draw_viewing_volume(std::string const & fname,vpgl_perspective_camera<double> cam,float r,float g,float b)742 void volm_query::draw_viewing_volume(std::string const& fname, vpgl_perspective_camera<double> cam, float r, float g, float b)
743 {
744 std::ofstream ofs(fname.c_str(), std::ios::app);
745 // reset the center back to zero
746 cam.set_camera_center(vgl_point_3d<double>(0.0,0.0,0.0) );
747 //bvrml_write::write_vrml_cylinder(ofs, cam.get_camera_center(), cam.principal_axis(),0.2f, (double)(conf_focal_ + init_focal_),r,g,b);
748
749 // create the viewing volume by rays
750 vgl_ray_3d<double> rtl = cam.backproject_ray(vgl_point_2d<double>(0.0, 0.0));
751 vgl_ray_3d<double> rtr = cam.backproject_ray(vgl_point_2d<double>((double)ni_, 0.0));
752 vgl_ray_3d<double> rll = cam.backproject_ray(vgl_point_2d<double>(0.0, (double)nj_));
753 vgl_ray_3d<double> rlr = cam.backproject_ray(vgl_point_2d<double>((double)ni_, (double)nj_));
754 // calculate a scaling factor
755 double scale = 0.5;
756 double focal = (cam.get_calibration()).focal_length();
757 double depth = focal * scale;
758 double dist = depth / focal * 0.5 * std::sqrt(4*focal*focal + ni_*ni_ + nj_*nj_);
759 // get image corner point
760 vgl_point_3d<double> ptl = cam.get_camera_center() + dist*rtl.direction();
761 vgl_point_3d<double> ptr = cam.get_camera_center() + dist*rtr.direction();
762 vgl_point_3d<double> pll = cam.get_camera_center() + dist*rll.direction();
763 vgl_point_3d<double> plr = cam.get_camera_center() + dist*rlr.direction();
764 // draw the boundary face
765 ofs << "Shape {\n"
766 << " appearance Appearance {\n"
767 << " material Material\n"
768 << " {\n"
769 << " diffuseColor " << r << ' ' << g << ' ' << b << '\n'
770 << " transparency " << 0 << '\n'
771 << " }\n"
772 << " }\n"
773 << " geometry IndexedFaceSet {\n"
774 << " coord Coordinate {\n"
775 << " point [\n"
776 << " " << cam.get_camera_center().x() << ' '
777 << " " << cam.get_camera_center().y() << ' '
778 << " " << cam.get_camera_center().z() << ",\n"
779 << " " << ptl.x() << ' ' << ptl.y() << ' ' << ptl.z() << ",\n"
780 << " " << ptr.x() << ' ' << ptr.y() << ' ' << ptr.z() << ",\n"
781 << " " << pll.x() << ' ' << pll.y() << ' ' << pll.z() << ",\n"
782 << " " << plr.x() << ' ' << plr.y() << ' ' << plr.z() << '\n'
783 << " ]\n"
784 << " }\n"
785 << " coordIndex [\n"
786 << " 0, 1, 2, -1,\n"
787 << " 0, 2, 4, -1,\n"
788 << " 0, 3, 4, -1,\n"
789 << " 0, 1, 3, -1,\n"
790 << " ]\n"
791 << " }\n"
792 << "}\n";
793 ofs.close();
794 }
795
draw_polygon(vil_image_view<vil_rgb<vxl_byte>> & img,vgl_polygon<double> const & poly,unsigned char const & depth)796 void volm_query::draw_polygon(vil_image_view<vil_rgb<vxl_byte> >& img, vgl_polygon<double> const& poly, unsigned char const& depth)
797 {
798 for (unsigned pi = 0; pi < poly.num_sheets(); ++pi)
799 {
800 for (unsigned vi = 0; vi < poly[pi].size(); ++vi)
801 {
802 vgl_point_2d<double> s = poly[pi][vi];
803 vgl_point_2d<double> e;
804 if (vi < poly[pi].size()-1) e = poly[pi][vi+1];
805 else e = poly[pi][0];
806 double k;
807 if (e.x() == s.x()) k = 10000;
808 else k = (e.y()-s.y())/(e.x()-s.x());
809 double b = s.y() - k * s.x();
810 if (std::sqrt(k*k) < 1) {// loop x
811 if (s.x() <= e.x()) {
812 for (auto xi = (unsigned)s.x(); xi <= (unsigned)e.x(); ++xi) {
813 auto xj = (unsigned)(k*xi+b);
814 if (xi < img.ni() && xj < img.nj()) {
815 img(xi,xj).r = bvrml_color::heatmap_classic[(int)depth][0];
816 img(xi,xj).g = bvrml_color::heatmap_classic[(int)depth][1];
817 img(xi,xj).b = bvrml_color::heatmap_classic[(int)depth][2];
818 }
819 }
820 }
821 else {
822 for (auto xi = (unsigned)e.x(); xi <= (unsigned)s.x(); ++xi) {
823 auto xj = (unsigned)(k*xi+b);
824 if (xi < img.ni() && xj < img.nj()) {
825 img(xi,xj).r = bvrml_color::heatmap_classic[(int)depth][0];
826 img(xi,xj).g = bvrml_color::heatmap_classic[(int)depth][1];
827 img(xi,xj).b = bvrml_color::heatmap_classic[(int)depth][2];
828 }
829 }
830 }
831 }
832 else {
833 if (s.y() <= e.y()) {
834 for (auto xj = (unsigned)s.y(); xj <= (unsigned)e.y(); ++xj) {
835 auto xi = (unsigned)((xj-b)/k);
836 if (xi < img.ni() && xj < img.nj()) {
837 img(xi,xj).r = bvrml_color::heatmap_classic[(int)depth][0];
838 img(xi,xj).g = bvrml_color::heatmap_classic[(int)depth][1];
839 img(xi,xj).b = bvrml_color::heatmap_classic[(int)depth][2];
840 }
841 }
842 }
843 else {
844 for (auto xj = (unsigned)e.y(); xj <= (unsigned)s.y(); ++xj) {
845 auto xi = (unsigned)((xj-b)/k);
846 if (xi < img.ni() && xj < img.nj()) {
847 img(xi,xj).r = bvrml_color::heatmap_classic[(int)depth][0];
848 img(xi,xj).g = bvrml_color::heatmap_classic[(int)depth][1];
849 img(xi,xj).b = bvrml_color::heatmap_classic[(int)depth][2];
850 }
851 }
852 }
853 }
854 }
855 }
856 }
857
draw_dot(vil_image_view<vil_rgb<vxl_byte>> & img,vgl_point_3d<double> const & world_point,vil_rgb<vxl_byte> color,vpgl_perspective_camera<double> const & cam)858 void volm_query::draw_dot(vil_image_view<vil_rgb<vxl_byte> >& img,
859 vgl_point_3d<double> const& world_point,
860 vil_rgb<vxl_byte> color,
861 vpgl_perspective_camera<double> const& cam)
862 {
863 int dot_size = ( img.ni() < img.nj() ) ? (int)(0.01*ni_) : (int)(0.01*nj_);
864 double u, v;
865 vgl_homg_point_3d<double> current_p(world_point.x(), world_point.y(), world_point.z()+altitude_);
866 if (!(cam.is_behind_camera(current_p))) {
867 cam.project(world_point.x(), world_point.y(), world_point.z()+altitude_, u, v);
868 int cx = (int)u;
869 int cy = (int)v;
870 for (int i = -dot_size; i < dot_size; ++i)
871 for (int j = -dot_size; j < dot_size; ++j) {
872 int x = cx + i ; int y = cy + j;
873 if ( !(x < 0 || y < 0 || x >= (int)img.ni() || y >= (int)img.nj()) ) {
874 img((unsigned)x, (unsigned)y) = color;
875 }
876 }
877 }
878 }
879
draw_depth_map_regions(vil_image_view<vil_rgb<vxl_byte>> & out_img)880 void volm_query::draw_depth_map_regions(vil_image_view<vil_rgb<vxl_byte> >& out_img)
881 {
882 // draw depth_map polygons on the depth images
883 if (dm_->sky().size()) {
884 for (unsigned i = 0; i < dm_->sky().size(); ++i) {
885 vgl_polygon<double> poly = bsol_algs::vgl_from_poly((dm_->sky()[i])->region_2d());
886 this->draw_polygon(out_img, poly, (unsigned char)254);
887 }
888 }
889 if (dm_->ground_plane().size()) {
890 unsigned ground_size = (unsigned)dm_->ground_plane().size();
891 for (unsigned i = 0; i < ground_size; ++i) {
892 vgl_polygon<double> poly = bsol_algs::vgl_from_poly((dm_->ground_plane()[i])->region_2d());
893 this->draw_polygon(out_img, poly, (unsigned char)1);
894 }
895 }
896 if (dm_->scene_regions().size()) {
897 unsigned region_size = (unsigned)dm_->scene_regions().size();
898 for ( unsigned i = 0; i < region_size; ++i) {
899 vgl_polygon<double> poly = bsol_algs::vgl_from_poly((dm_->scene_regions())[i]->region_2d());
900 double value = (dm_->scene_regions())[i]->min_depth();
901 unsigned char depth = sph_depth_->get_depth_interval(value);
902 this->draw_polygon(out_img, poly, depth);
903 }
904 }
905 }
906
depth_rgb_image(std::vector<unsigned char> const & values,unsigned const & cam_id,vil_image_view<vil_rgb<vxl_byte>> & out_img,const std::string & value_type)907 void volm_query::depth_rgb_image(std::vector<unsigned char> const& values,
908 unsigned const& cam_id,
909 vil_image_view<vil_rgb<vxl_byte> >& out_img,
910 const std::string& value_type)
911 {
912 this->draw_depth_map_regions(out_img);
913
914 vpgl_perspective_camera<double> cam = cam_space_->camera(cam_id);
915
916 if (value_type == "orientation") {
917 for (unsigned pidx = 0; pidx < query_size_; ++pidx) {
918 vil_rgb<vxl_byte> color_id;
919 if (values[pidx] == 0 || values[pidx] == 100) // invalid --> black
920 color_id = vil_rgb<vxl_byte>(0,0,0);
921 else if (values[pidx] == 1) // horizontal --> red
922 color_id = vil_rgb<vxl_byte>(255,0,0);
923 else if (values[pidx] > 1 && values[pidx] < 10) // vertical --> green
924 color_id = vil_rgb<vxl_byte>(0,180,60);
925 else if (values[pidx] == 254) // sky --> blue
926 color_id = vil_rgb<vxl_byte>(51,102,255);
927 else
928 color_id = vil_rgb<vxl_byte>(49,50,62);
929 this->draw_dot(out_img, query_points_[pidx], color_id, cam);
930 }
931 }
932 else if (value_type == "land") {
933 for (unsigned pidx = 0; pidx < query_size_; ++pidx) {
934 vil_rgb<vxl_byte> color_id;
935 if (values[pidx] == 0) // invalid --> black
936 color_id = vil_rgb<vxl_byte>(255,0,0);
937 else if (values[pidx] == 254) // sky --> blue
938 color_id = vil_rgb<vxl_byte>(51,102,255);
939 else
940 color_id = volm_osm_category_io::volm_land_table[values[pidx]].color_;
941 //color_id = volm_label_table::get_color(values[pidx]);
942 this->draw_dot(out_img, query_points_[pidx], color_id, cam);
943 }
944 }
945 else if (value_type == "depth") {
946 for (unsigned pidx = 0; pidx < query_size_; ++pidx) {
947 vil_rgb<vxl_byte> color_id;
948 if (values[pidx] == 254)
949 color_id = vil_rgb<vxl_byte>(51,102,255);
950 else if (values[pidx] == 253)
951 color_id = vil_rgb<vxl_byte>(0,0,0);
952 else
953 color_id = vil_rgb<vxl_byte>(bvrml_color::heatmap_classic[(int)values[pidx]][0],
954 bvrml_color::heatmap_classic[(int)values[pidx]][1],
955 bvrml_color::heatmap_classic[(int)values[pidx]][2]);
956 this->draw_dot(out_img, query_points_[pidx], color_id, cam);
957 }
958 }
959 else {
960 std::cerr << "WARNING: given image type " << value_type << " is not found in volm_query::depth_rgb_image, generate depth image instead\n";
961 for (unsigned pidx = 0; pidx < query_size_; ++pidx)
962 if (values[pidx] < 255)
963 this->draw_dot(out_img, query_points_[pidx], values[pidx], cam);
964 }
965 }
966
draw_query_image(unsigned cam_i,std::string const & out_name)967 void volm_query::draw_query_image(unsigned cam_i, std::string const& out_name)
968 {
969 // create an rgb image instance
970 vil_image_view<vil_rgb<vxl_byte> > img(ni_, nj_);
971 // initialize the image
972 for (unsigned i = 0; i < ni_; ++i)
973 for (unsigned j = 0; j < nj_; ++j) {
974 img(i,j).r = (unsigned char)120;
975 img(i,j).g = (unsigned char)120;
976 img(i,j).b = (unsigned char)120;
977 }
978 std::vector<unsigned char> current_query = min_dist_[cam_i];
979 this->depth_rgb_image(current_query, cam_i, img);
980 // save the images
981 vil_save(img,out_name.c_str());
982 }
983
draw_query_regions(std::string const & out_name)984 void volm_query::draw_query_regions(std::string const& out_name)
985 {
986 // create an rgb image instance
987 vil_image_view<vil_rgb<vxl_byte> > img(ni_, nj_);
988 // initialize the image
989 for (unsigned i = 0; i < ni_; ++i)
990 for (unsigned j = 0; j < nj_; ++j) {
991 img(i,j).r = (unsigned char)120;
992 img(i,j).g = (unsigned char)120;
993 img(i,j).b = (unsigned char)120;
994 }
995 this->draw_depth_map_regions(img);
996 // save the images
997 vil_save(img,out_name.c_str());
998 }
999
draw_query_images(std::string const & out_dir)1000 void volm_query::draw_query_images(std::string const& out_dir)
1001 {
1002 // create a png img associated with each camera hypothesis, containing the geometry defined
1003 // in depth_map_scene and the img points corresponding to points inside the container
1004 // loop over fist 100 camera
1005 unsigned img_num = (this->get_cam_num() > 20) ? 20 : (unsigned)cameras_.size();
1006 for (unsigned i = 0; i < img_num; ++i) {
1007 std::stringstream s_idx;
1008 s_idx << i;
1009 std::string fs = out_dir + "query_img_" + this->get_cam_string(i) + ".png";
1010 this->draw_query_image(i, fs);
1011 }
1012 }
1013
visualize_query(std::string const & prefix)1014 void volm_query::visualize_query(std::string const& prefix)
1015 {
1016 // visualize the spherical shell by the query depth value -- used to compare with the generated index spherical shell
1017 // loop over all camera
1018 for (unsigned i = 0; i < this->get_cam_num(); ++i) {
1019 std::vector<unsigned char> single_layer = min_dist_[i];
1020 std::stringstream str;
1021 str << prefix << "_query_" << i << ".vrml";
1022 sph_->draw_template(str.str(), single_layer, 254);
1023 }
1024 }
1025
get_num_top_fov(double const & top_fov) const1026 unsigned volm_query::get_num_top_fov(double const& top_fov) const
1027 {
1028 unsigned count = 0;
1029 for (unsigned i = 0; i < this->get_cam_num(); ++i) {
1030 std::string cam_string = this->get_cam_string(i);
1031 auto sindx = (unsigned)cam_string.find("top_fov");
1032 sindx += 8;
1033 std::stringstream ss( cam_string.substr(sindx, cam_string.size()-1) );
1034 double top;
1035 ss >> top;
1036 if ((unsigned)top == (unsigned)top_fov) {
1037 ++count;
1038 }
1039 }
1040 return count;
1041 }
1042
get_top_fov(unsigned const & id) const1043 double volm_query::get_top_fov(unsigned const& id) const
1044 {
1045 std::string cam_string = this->get_cam_string(id);
1046 auto sindx = (unsigned)cam_string.find("top_fov");
1047 sindx += 8;
1048 std::stringstream ss( cam_string.substr(sindx, cam_string.size()-1) );
1049 double top;
1050 ss >> top;
1051 return top;
1052 }
1053
get_valid_top_fov() const1054 std::vector<double> volm_query::get_valid_top_fov() const
1055 {
1056 std::set<double> top_fov_set;
1057 for (unsigned i = 0; i < this->get_cam_num(); ++i) {
1058 top_fov_set.insert(this->get_top_fov(i));
1059 }
1060 std::vector<double> valid_top_fov;
1061 valid_top_fov.reserve(top_fov_set.size());
1062 for (const auto & it : top_fov_set)
1063 valid_top_fov.push_back(it);
1064 return valid_top_fov;
1065 }
1066
get_order_size() const1067 unsigned volm_query::get_order_size() const
1068 {
1069 unsigned count = 0;
1070 unsigned cam_num = this->get_cam_num();
1071 unsigned obj_num = this->get_obj_order_num();
1072 for (unsigned i = 0; i < cam_num; ++i)
1073 for (unsigned j = 0; j < obj_num; ++j)
1074 count += (unsigned)order_index_[i][j].size();
1075 return count;
1076 }
1077
obj_based_query_size_byte() const1078 unsigned volm_query::obj_based_query_size_byte() const
1079 {
1080 unsigned size_byte = 0;
1081 // ground voxel size
1082 size_byte += this->get_ground_id_size()*4; // unsigned id
1083 size_byte += this->get_ground_dist_size(); // unsigned char distance
1084 size_byte += this->get_ground_id_size()*4; // unsigned char land classfication
1085 size_byte += this->get_ground_id_size()*4*4; // float land fallback category weight
1086 size_byte += 1; // unsigned char orientation
1087 size_byte += (unsigned)ground_offset_.size()*4; // unsinged ground offset
1088
1089 // sky voxel size
1090 size_byte += this->get_sky_id_size()*4; // unsigned id
1091 size_byte += (unsigned)sky_offset_.size()*4; // unsigned sky offset
1092 //size_byte += 4; // float weight
1093
1094 // non-sky, non-ground object
1095 size_byte += this->get_dist_id_size()*4; // unsigned id
1096 size_byte += (unsigned)dist_offset_.size()*4; // unsigned offset
1097 size_byte += (unsigned)min_obj_dist_.size(); // unsigned char distance
1098 size_byte += (unsigned)max_obj_dist_.size(); // unsigned char distance
1099 size_byte += (unsigned)obj_orient_.size(); // unsigned char orientation
1100 size_byte += (unsigned)obj_land_id_.size()*4; // unsigned char land clarification
1101 size_byte += (unsigned)obj_land_wgt_.size()*4*4; // float land fallback category weight
1102 size_byte += (unsigned)order_obj_.size(); // unsigned char order
1103 //size_byte += (unsigned)weight_obj_.size()*4; // float weight
1104 return size_byte;
1105 }
1106
1107 //: binary IO write
write_data(vsl_b_ostream & os)1108 void volm_query::write_data(vsl_b_ostream& os)
1109 {
1110 unsigned ver = this->version();
1111 vsl_b_write(os, ver);
1112 vsl_b_write(os, invalid_);
1113 vsl_b_write(os, d_threshold_);
1114 vsl_b_write(os, camera_strings_);
1115 vsl_b_write(os, order_set_); // store the non-ground order, using set to ensure objects having same order are put together
1116
1117 vsl_b_write(os, (unsigned)(order_index_.size()));
1118 for (const auto & i : order_index_)
1119 vsl_b_write(os, i);
1120
1121 vsl_b_write(os, ground_id_);
1122 vsl_b_write(os, ground_dist_);
1123
1124 //vsl_b_write(os, ground_land_id_);
1125 vsl_b_write(os, (unsigned)(ground_land_id_.size()));
1126 for (const auto & i : ground_land_id_)
1127 vsl_b_write(os, i);
1128
1129 vsl_b_write(os, (unsigned)(ground_land_wgt_.size()));
1130 for (const auto & i : ground_land_wgt_)
1131 vsl_b_write(os, i);
1132
1133 vsl_b_write(os, ground_offset_);
1134 vsl_b_write(os, ground_orient_);
1135 vsl_b_write(os, sky_id_);
1136 vsl_b_write(os, sky_offset_);
1137 vsl_b_write(os, sky_orient_);
1138
1139 vsl_b_write(os, (unsigned)(dist_id_.size()));
1140 for (const auto & i : dist_id_)
1141 vsl_b_write(os, i);
1142
1143 vsl_b_write(os, dist_offset_);
1144 vsl_b_write(os, min_obj_dist_);
1145 vsl_b_write(os, max_obj_dist_);
1146 vsl_b_write(os, order_obj_);
1147 vsl_b_write(os, obj_orient_);
1148 vsl_b_write(os, obj_land_id_);
1149 vsl_b_write(os, obj_land_wgt_);
1150 }
1151
1152 //: binary IO read
read_data(vsl_b_istream & is)1153 void volm_query::read_data(vsl_b_istream& is)
1154 {
1155 unsigned ver;
1156 vsl_b_read(is, ver);
1157 if (ver ==1) {
1158 vsl_b_read(is, invalid_);
1159 vsl_b_read(is, d_threshold_);
1160 vsl_b_read(is, camera_strings_);
1161 vsl_b_read(is, order_set_); // store the non-ground order, using set to ensure objects having same order are put together
1162 unsigned size;
1163 vsl_b_read(is, size);
1164 for (unsigned i = 0; i < size; i++) {
1165 std::vector<std::vector<unsigned> > o;
1166 vsl_b_read(is, o);
1167 order_index_.push_back(o);
1168 }
1169
1170 vsl_b_read(is, ground_id_);
1171 vsl_b_read(is, ground_dist_);
1172
1173 // vsl_b_read(is, ground_land_id_);
1174 vsl_b_read(is, size);
1175 for (unsigned i = 0; i < size; i++) {
1176 std::vector<std::vector<unsigned char> > temp;
1177 vsl_b_read(is, temp);
1178 ground_land_id_.push_back(temp);
1179 }
1180
1181 vsl_b_read(is, size);
1182 for (unsigned i = 0; i < size; i++) {
1183 std::vector<std::vector<float> > temp;
1184 vsl_b_read(is, temp);
1185 ground_land_wgt_.push_back(temp);
1186 }
1187
1188 vsl_b_read(is, ground_offset_);
1189 vsl_b_read(is, ground_orient_);
1190 vsl_b_read(is, sky_id_);
1191 vsl_b_read(is, sky_offset_);
1192 vsl_b_read(is, sky_orient_);
1193
1194 vsl_b_read(is, size);
1195 for (unsigned i = 0; i < size; i++) {
1196 std::vector<std::vector<unsigned> > o;
1197 vsl_b_read(is, o);
1198 dist_id_.push_back(o);
1199 }
1200
1201 vsl_b_read(is, dist_offset_);
1202 vsl_b_read(is, min_obj_dist_);
1203 vsl_b_read(is, max_obj_dist_);
1204 vsl_b_read(is, order_obj_);
1205 vsl_b_read(is, obj_orient_);
1206 vsl_b_read(is, obj_land_id_);
1207 vsl_b_read(is, obj_land_wgt_);
1208 }
1209 else {
1210 std::cerr << "volm_spherical_shell_container - unknown binary io version " << ver <<'\n';
1211 return;
1212 }
1213 }
1214
operator ==(const volm_query & other) const1215 bool volm_query::operator== (const volm_query &other) const
1216 {
1217 return this->get_cam_num() == other.get_cam_num() &&
1218 ni_ == other.ni_ && nj_ == other.nj_ &&
1219 log_downsample_ratio_ == other.log_downsample_ratio_ &&
1220 d_threshold_ == other.d_threshold_ &&
1221 depth_regions_.size() == other.depth_regions_.size() &&
1222 camera_strings_ == other.camera_strings_ &&
1223 order_set_ == other.order_set_ &&
1224 order_index_ == other.order_index_ &&
1225 ground_id_ == other.ground_id_ &&
1226 ground_dist_ == other.ground_dist_ &&
1227 ground_land_id_ == other.ground_land_id_ &&
1228 ground_offset_ == other.ground_offset_ &&
1229 ground_orient_ == other.ground_orient_ &&
1230 sky_id_ == other.sky_id_ &&
1231 sky_offset_ == other.sky_offset_ &&
1232 sky_orient_ == other.sky_orient_ &&
1233 dist_id_ == other.dist_id_ &&
1234 dist_offset_ == other.dist_offset_ &&
1235 min_obj_dist_ == other.min_obj_dist_ &&
1236 max_obj_dist_ == other.max_obj_dist_ &&
1237 order_obj_ == other.order_obj_ &&
1238 obj_orient_ == other.obj_orient_ &&
1239 obj_land_id_ == other.obj_land_id_;
1240 }
1241