Caffe2 - C++ API
A deep learning, cross platform ML framework
rmac_regions_op.cc
1 #include "caffe2/operators/rmac_regions_op.h"
2 
3 #include <float.h>
4 
5 namespace caffe2 {
6 
7 template <>
8 bool RMACRegionsOp<CPUContext>::RunOnDevice() {
9  const auto& X = Input(0); // Input tensor
10  auto* output = Output(0); // RoIs
11  output->Resize(0, 5); // [batch_id x1 y1 x2 y2] format of ROIPoolOp
12 
13  if (X.size() == 0) {
14  return true;
15  }
16 
17  int batch_size = X.dim32(0);
18  int H = X.dim32(2);
19  int W = X.dim32(3);
20  int minW = std::min(H, W);
21 
22  // steps(idx) regions for long dimension
23  int step = 0;
24  if (W != H) {
25  int min_step = 1;
26  int max_step = 6;
27  float cur_min = FLT_MAX;
28  for (int idx = min_step; idx <= max_step; ++idx) {
29  float b = (std::max(H, W) - minW) / (1.0 * idx);
30  float val = std::abs((minW * minW - minW * b) / (minW * minW) - overlap_);
31  if (val < cur_min) {
32  step = idx;
33  cur_min = val;
34  }
35  }
36  }
37 
38  // Region overplus per dimension
39  int Wd = (W > H) ? step : 0;
40  int Hd = (H > W) ? step : 0;
41 
42  // Regions at each scale
43  for (int l = 1; l <= scales_; ++l) {
44  int region_size = 2 * minW / (l + 1);
45  if (region_size == 0) {
46  // Empty region.
47  // Break early as further scales will also result in empty regions.
48  break;
49  }
50 
51  // Region coordinates
52  float bw =
53  (l + Wd - 1 > 0) ? ((W - region_size) / (1.0 * (l + Wd - 1))) : 0;
54  float bh =
55  (l + Hd - 1 > 0) ? ((H - region_size) / (1.0 * (l + Hd - 1))) : 0;
56 
57  int cur_rows = output->dim32(0);
58  output->Extend((l + Wd) * (l + Hd), 50, &context_);
59  auto* outputData = output->mutable_data<float>() + cur_rows * 5;
60 
61  for (int i = 0; i < l + Wd; ++i) {
62  for (int j = 0; j < l + Hd; ++j) {
63  int x1 = bw * i;
64  int y1 = bh * j;
65  // Careful with the borders
66  if (x1 + region_size > W) {
67  x1 -= (x1 + region_size - W);
68  }
69  if (y1 + region_size > H) {
70  y1 -= (y1 + region_size - H);
71  }
72  int x2 = x1 + region_size - 1;
73  int y2 = y1 + region_size - 1;
74 
75  // Write region coordinates for batch 0
76  *outputData++ = 0;
77  *outputData++ = x1;
78  *outputData++ = y1;
79  *outputData++ = x2;
80  *outputData++ = y2;
81  }
82  }
83  }
84 
85  // Replicate regions for all items in batch
86  int num_rois = output->dim32(0);
87  output->Extend((batch_size - 1) * num_rois, 50, &context_);
88  auto* outputData = output->mutable_data<float>();
89  for (int b = 1; b < batch_size; ++b) {
90  // Copy all rois
91  std::copy_n(outputData, num_rois * 5, outputData + b * num_rois * 5);
92  // Override batch index
93  for (int r = 0; r < num_rois; ++r) {
94  outputData[(b * num_rois + r) * 5] = b;
95  }
96  }
97 
98  return true;
99 }
100 
101 REGISTER_CPU_OPERATOR(RMACRegions, RMACRegionsOp<CPUContext>);
102 
103 OPERATOR_SCHEMA(RMACRegions)
104  .NumInputs(1)
105  .NumOutputs(1)
106  .SetDoc(R"DOC(
107 Computes a fixed-grid of RMAC region coordinates at various levels
108 as described in https://arxiv.org/abs/1511.05879.
109 )DOC")
110  .Arg("scales", "Number of scales to sample regions at.")
111  .Arg("overlap", "Overlap between consecutive regions.")
112  .Input(0, "X", "The input 4D tensor of shape NCHW.")
113  .Output(
114  0,
115  "RMAC_REGIONS",
116  "The output RMAC regions for all items in the batch. Tensor of shape "
117  "(N x 5) following the ROIPoolOp format - each row is of the format "
118  "(batch_index x1 y1 x2 y2) where x1, y1, x2, y2 are the region "
119  "co-ordinates. Each region is repeated N times corresponding to each "
120  "item in the batch.");
121 
122 SHOULD_NOT_DO_GRADIENT(RMACRegions);
123 
124 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...