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