File: rmac_regions_op.cc

package info (click to toggle)
pytorch 1.7.1-7
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 80,340 kB
  • sloc: cpp: 670,830; python: 343,991; ansic: 67,845; asm: 5,503; sh: 2,924; java: 2,888; xml: 266; makefile: 244; ruby: 148; yacc: 144; objc: 51; lex: 44
file content (127 lines) | stat: -rw-r--r-- 3,643 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "caffe2/operators/rmac_regions_op.h"

#include <float.h>

namespace caffe2 {

template <>
bool RMACRegionsOp<CPUContext>::RunOnDevice() {
  const auto& X = Input(0); // Input tensor
                            // RoIs
  auto* output = Output(
      0,
      {0, 5},
      at::dtype<float>()); // [batch_id x1 y1 x2 y2] format of ROIPoolOp

  if (X.numel() == 0) {
    return true;
  }

  int batch_size = X.dim32(0);
  int H = X.dim32(2);
  int W = X.dim32(3);
  int minW = std::min(H, W);

  // steps(idx) regions for long dimension
  int step = 0;
  if (W != H) {
    int min_step = 1;
    int max_step = 6;
    float cur_min = FLT_MAX;
    for (int idx = min_step; idx <= max_step; ++idx) {
      float b = (std::max(H, W) - minW) / (1.0 * idx);
      float val = std::abs((minW * minW - minW * b) / (minW * minW) - overlap_);
      if (val < cur_min) {
        step = idx;
        cur_min = val;
      }
    }
  }

  // Region overplus per dimension
  int Wd = (W > H) ? step : 0;
  int Hd = (H > W) ? step : 0;

  // Regions at each scale
  for (int l = 1; l <= scales_; ++l) {
    int region_size = 2 * minW / (l + 1);
    if (region_size == 0) {
      // Empty region.
      // Break early as further scales will also result in empty regions.
      break;
    }

    // Region coordinates
    float bw =
        (l + Wd - 1 > 0) ? ((W - region_size) / (1.0 * (l + Wd - 1))) : 0;
    float bh =
        (l + Hd - 1 > 0) ? ((H - region_size) / (1.0 * (l + Hd - 1))) : 0;

    int cur_rows = output->dim32(0);
    output->Extend((l + Wd) * (l + Hd), 50);
    auto* outputData = output->template mutable_data<float>() + cur_rows * 5;

    for (int i = 0; i < l + Wd; ++i) {
      for (int j = 0; j < l + Hd; ++j) {
        int x1 = bw * i;
        int y1 = bh * j;
        // Careful with the borders
        if (x1 + region_size > W) {
          x1 -= (x1 + region_size - W);
        }
        if (y1 + region_size > H) {
          y1 -= (y1 + region_size - H);
        }
        int x2 = x1 + region_size - 1;
        int y2 = y1 + region_size - 1;

        // Write region coordinates for batch 0
        *outputData++ = 0;
        *outputData++ = x1;
        *outputData++ = y1;
        *outputData++ = x2;
        *outputData++ = y2;
      }
    }
  }

  // Replicate regions for all items in batch
  int num_rois = output->dim32(0);
  output->Extend((batch_size - 1) * num_rois, 50);
  auto* outputData = output->template mutable_data<float>();
  for (int b = 1; b < batch_size; ++b) {
    // Copy all rois
    std::copy_n(outputData, num_rois * 5, outputData + b * num_rois * 5);
    // Override batch index
    for (int r = 0; r < num_rois; ++r) {
      outputData[(b * num_rois + r) * 5] = b;
    }
  }

  return true;
}

REGISTER_CPU_OPERATOR(RMACRegions, RMACRegionsOp<CPUContext>);

OPERATOR_SCHEMA(RMACRegions)
    .NumInputs(1)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Computes a fixed-grid of RMAC region coordinates at various levels
as described in https://arxiv.org/abs/1511.05879.
)DOC")
    .Arg("scales", "Number of scales to sample regions at.")
    .Arg("overlap", "Overlap between consecutive regions.")
    .Input(0, "X", "The input 4D tensor of shape NCHW.")
    .Output(
        0,
        "RMAC_REGIONS",
        "The output RMAC regions for all items in the batch. Tensor of shape "
        "(N x 5) following the ROIPoolOp format - each row is of the format "
        "(batch_index x1 y1 x2 y2) where x1, y1, x2, y2 are the region "
        "co-ordinates. Each region is repeated N times corresponding to each "
        "item in the batch.");

SHOULD_NOT_DO_GRADIENT(RMACRegions);

} // namespace caffe2