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