void upgrade_octree()

in caffe/tools/upgrade_octree_database.cpp [32:125]


void upgrade_octree(string& octree_output, const string& octree_input) {
  /// parse the octree
  const int* octi = reinterpret_cast<const int*>(octree_input.data());
  int total_node_num = octi[0];
  int final_node_num = octi[1];
  int depth = octi[2];
  int full_layer = octi[3];
  const int* node_num = octi + 4;
  const int* node_num_cum = node_num + depth + 1;
  const int* key = node_num_cum + depth + 2;
  const int* children = key + total_node_num;
  const int* data = children + total_node_num;

  vector<int> nnum_nempty(depth + 1, 0);
  for (int d = 0; d <= depth; ++d) {
    // find the last element which is not equal to -1
    const int* children_d = children + node_num_cum[d];
    for (int i = node_num[d] - 1; i >= 0; i--) {
      if (children_d[i] != -1) {
        nnum_nempty[d] = children_d[i] + 1;
        break;
      }
    }
  }

  /// set octree info
  OctreeInfo octree_info;
  octree_info.set_batch_size(1);
  octree_info.set_depth(depth);
  octree_info.set_full_layer(full_layer);
  octree_info.set_adaptive_layer(FLAGS_adp_depth);
  octree_info.set_adaptive(FLAGS_adaptive);
  octree_info.set_node_dis(FLAGS_node_dis);
  octree_info.set_key2xyz(FLAGS_key2xyz);
  octree_info.set_threshold_normal(0.0f);
  octree_info.set_threshold_dist(0.0f);

  float width = static_cast<float>(1 << depth);
  float bbmin[] = { 0.0f, 0.0f, 0.0f };
  float bbmax[] = { width, width, width };
  octree_info.set_bbox(bbmin, bbmax);

  // by default, the octree contains Key and Child
  int channel = 1;
  octree_info.set_property(OctreeInfo::kKey, channel, -1);
  octree_info.set_property(OctreeInfo::kChild, channel, -1);

  // set feature
  int data_channel = FLAGS_node_dis ? 4 : 3;
  int location = FLAGS_adaptive ? -1 : depth;
  octree_info.set_property(OctreeInfo::kFeature, data_channel, location);

  // set label
  if (FLAGS_node_label) {
    octree_info.set_property(OctreeInfo::kLabel, 1, depth);
  }

  // set split label
  octree_info.set_property(OctreeInfo::kSplit, 0, 0);
  if (FLAGS_split_label) {
    octree_info.set_property(OctreeInfo::kSplit, 1, -1);
  }

  // update node_num
  octree_info.set_nnum(node_num);
  octree_info.set_nnum_cum();
  octree_info.set_nempty(nnum_nempty.data());
  octree_info.set_ptr_dis();

  /// output octree
  octree_output.resize(octree_info.sizeof_octree());
  OctreeParser oct_parser;
  oct_parser.set_cpu(&octree_output[0], &octree_info);
  int total_nnum = octree_info.total_nnum();
  int nnum_depth = octree_info.node_num(depth);
  memcpy(oct_parser.mutable_key_cpu(0), key, total_nnum * sizeof(int));
  memcpy(oct_parser.mutable_children_cpu(0), children, total_nnum * sizeof(int));
  int data_size = FLAGS_adaptive ? total_nnum : nnum_depth;
  memcpy(oct_parser.mutable_feature_cpu(0), data, data_size * data_channel * sizeof(float));
  if (FLAGS_node_label) {
    const int* ptr = data + data_size * data_channel;
    float* des = oct_parser.mutable_label_cpu(0);
    for (int i = 0; i < nnum_depth; ++i) {
      des[i] = static_cast<float>(ptr[i]);
    }
  }
  if (FLAGS_split_label) {
    const int* ptr = data + data_size * data_channel;
    float* des = oct_parser.mutable_split_cpu(0);
    for (int i = 0; i < total_nnum; ++i) {
      des[i] = static_cast<float>(ptr[i]);
    }
  }
}