1 // This is brl/bseg/bstm/cpp/pro/processes/bstm_cpp_change_btw_frames_process.cxx
2 #include <iostream>
3 #include <fstream>
4 #include <bprb/bprb_func_process.h>
5 //:
6 // \file
7 // \brief  A process for analyzing the temporal coherency of a region (bounding box) over a specified time interval.
8 //
9 // \author Ali Osman Ulusoy
10 // \date Mar 18, 2013
11 
12 #ifdef _MSC_VER
13 #  include "vcl_msvc_warnings.h"
14 #endif
15 #include <bstm/io/bstm_cache.h>
16 #include <bstm/io/bstm_lru_cache.h>
17 #include <bstm/bstm_scene.h>
18 #include <bstm/bstm_block.h>
19 #include <bstm/bstm_data_base.h>
20 //brdb stuff
21 #include <brdb/brdb_value.h>
22 
23 #include "vgl/vgl_box_3d.h"
24 #include "vgl/vgl_intersection.h"
25 
26 #include <bstm/bstm_util.h>
27 #include <bstm/cpp/algo/bstm_analyze_coherency_function.h>
28 
29 namespace bstm_cpp_change_btw_frames_process_globals
30 {
31   constexpr unsigned n_inputs_ = 4;
32   constexpr unsigned n_outputs_ = 0;
33 
34   typedef unsigned char uchar;
35   typedef unsigned short ushort;
36   typedef vnl_vector_fixed<uchar, 16> uchar16;
37   typedef vnl_vector_fixed<uchar, 8> uchar8;
38   typedef vnl_vector_fixed<ushort, 4> ushort4;
39 
40 
41 }
42 
bstm_cpp_change_btw_frames_process_cons(bprb_func_process & pro)43 bool bstm_cpp_change_btw_frames_process_cons(bprb_func_process& pro)
44 {
45   using namespace bstm_cpp_change_btw_frames_process_globals;
46 
47   //process takes 1 input
48   std::vector<std::string> input_types_(n_inputs_);
49 
50   input_types_[0] = "bstm_scene_sptr";
51   input_types_[1] = "bstm_cache_sptr";
52   input_types_[2] = "float"; //time 0
53   input_types_[3] = "float"; //time 1
54 
55   // process has 1 output:
56   // output[0]: scene sptr
57   std::vector<std::string>  output_types_(n_outputs_);
58 
59   bool good = pro.set_input_types(input_types_) && pro.set_output_types(output_types_);
60   return good;
61 }
62 
bstm_cpp_change_btw_frames_process(bprb_func_process & pro)63 bool bstm_cpp_change_btw_frames_process(bprb_func_process& pro)
64 {
65   using namespace bstm_cpp_change_btw_frames_process_globals;
66 
67   if ( pro.n_inputs() < n_inputs_ ) {
68     std::cout << pro.name() << ": The input number should be " << n_inputs_<< std::endl;
69     return false;
70   }
71 
72   //get the inputs
73   unsigned i = 0;
74   bstm_scene_sptr scene =pro.get_input<bstm_scene_sptr>(i++);
75   bstm_cache_sptr cache= pro.get_input<bstm_cache_sptr>(i++);
76   auto time_0 = pro.get_input<float>(i++);
77   auto time_1 = pro.get_input<float>(i++);
78 
79 
80 
81   //iterate over each block/metadata to check if bbox intersects the input bbox
82   std::map<bstm_block_id, bstm_block_metadata> blocks = scene->blocks();
83   std::map<bstm_block_id, bstm_block_metadata> ::const_iterator bstm_iter = blocks.begin();
84   for(; bstm_iter != blocks.end() ; bstm_iter++)
85   {
86     bstm_block_id bstm_id = bstm_iter->first;
87     bstm_block_metadata bstm_metadata = bstm_iter->second;
88 
89     double local_time_0, local_time_1;
90     if(bstm_metadata.contains_t (time_0, local_time_0) && bstm_metadata.contains_t (time_1, local_time_1)) //if the block box contains the given times
91     {
92       std::cout << "Found intersecting bbox at block " << bstm_id << "..." << std::endl;
93 
94       bstm_block* blk = cache->get_block(bstm_metadata.id_);
95       bstm_time_block* blk_t = cache->get_time_block(bstm_metadata.id_);
96       bstm_data_base * alph = cache->get_data_base(bstm_metadata.id_, bstm_data_traits<BSTM_ALPHA>::prefix());
97       auto * alpha_data = (bstm_data_traits<BSTM_ALPHA>::datatype*) alph->data_buffer();
98       bstm_data_base *change_buffer = cache->get_data_base_new(bstm_metadata.id_,
99                                                         bstm_data_traits<BSTM_CHANGE>::prefix(),
100                                                         blk_t->tree_buff_length() * bstm_data_traits<BSTM_CHANGE>::datasize()  );
101       auto* change_array = (bstm_data_traits<BSTM_CHANGE>::datatype*) change_buffer->data_buffer();
102 
103       //iterate through each tree
104       boxm2_array_3d<uchar16>&  trees = blk->trees();
105       for (unsigned int x = 0; x < trees.get_row1_count(); ++x) {
106         for (unsigned int y = 0; y < trees.get_row2_count(); ++y) {
107          for (unsigned int z = 0; z < trees.get_row3_count(); ++z) {
108            //load current block/tree
109            uchar16 tree = trees(x, y, z);
110            boct_bit_tree bit_tree((unsigned char*) tree.data_block());
111 
112            //iterate through leaves of the tree
113            std::vector<int> leafBits = bit_tree.get_leaf_bits();
114            std::vector<int>::iterator iter;
115            for (iter = leafBits.begin(); iter != leafBits.end(); ++iter) {
116              int curr_depth = bit_tree.depth_at((*iter));
117              double side_len = 1.0 / (double) (1<<curr_depth);
118              int data_offset = bit_tree.get_data_index(*iter);
119 
120              float prob_0, prob_1;
121              {
122                vnl_vector_fixed<unsigned char,8> time_treebits = blk_t->get_cell_tt(data_offset,local_time_0);
123                bstm_time_tree time_tree(time_treebits.data_block());
124                int bit_index_t = time_tree.traverse(local_time_0 - blk_t->tree_index(local_time_0) );
125                int data_offset_t = time_tree.get_data_index(bit_index_t);
126                prob_0 = 1.0f - (float)std::exp(-alpha_data[data_offset_t] * side_len * bstm_metadata.sub_block_dim_.x());
127              }
128              {
129                vnl_vector_fixed<unsigned char,8> time_treebits = blk_t->get_cell_tt(data_offset,local_time_1);
130                bstm_time_tree time_tree(time_treebits.data_block());
131                int bit_index_t = time_tree.traverse(local_time_1 - blk_t->tree_index(local_time_1) );
132                int data_offset_t = time_tree.get_data_index(bit_index_t);
133                prob_1 = 1.0f - (float)std::exp(-alpha_data[data_offset_t] * side_len * bstm_metadata.sub_block_dim_.x());
134              }
135              change_array[data_offset] = std::fabs(prob_0 - prob_1);
136            }
137 
138          }
139         }
140       }
141 
142 
143 
144     }
145   }
146 
147   return true;
148 
149 }
150