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
|