File: rmac_regions_op.cc

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (135 lines) | stat: -rw-r--r-- 4,338 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
128
129
130
131
132
133
134
135
#include "caffe2/operators/rmac_regions_op.h"

// NOLINTNEXTLINE(modernize-deprecated-headers)
#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) {
      // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions)
      float b = (std::max(H, W) - minW) / (1.0 * idx);
      // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions)
      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 =
        // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions)
        (l + Wd - 1 > 0) ? ((W - region_size) / (1.0 * (l + Wd - 1))) : 0;
    float bh =
        // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions)
        (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) {
        // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions)
        int x1 = bw * i;
        // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions,bugprone-narrowing-conversions)
        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
        // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
        *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