1 #include "caffe2/operators/collect_and_distribute_fpn_rpn_proposals_op.h" 4 #include "caffe2/mkl/operators/operator_fallback_mkl.h" 5 #endif // CAFFE2_USE_MKL 12 ERArrXXf BoxesArea(
const ERArrXXf& boxes) {
18 const auto w = boxes.col(2) - boxes.col(0) + 1;
19 const auto h = boxes.col(3) - boxes.col(1) + 1;
20 const ERArrXXf areas = w * h;
21 CAFFE_ENFORCE((areas >= 0).all(),
"Negative areas founds: ", boxes);
27 ERArrXXf MapRoIsToFpnLevels(Eigen::Ref<const ERArrXXf> rois,
28 const float k_min,
const float k_max,
29 const float s0,
const float lvl0) {
31 ERArrXXf s = BoxesArea(rois).sqrt();
39 auto target_lvls = (lvl0 + (s / s0 + 1e-6).log() / log(2)).floor();
40 auto target_lvls_clipped = target_lvls.min(k_max).max(k_min);
41 return target_lvls_clipped;
46 void SortAndLimitRoIsByScores(Eigen::Ref<const EArrXf> scores,
int n,
48 CAFFE_ENFORCE(rois.rows() == scores.size(),
"RoIs and scores count mismatch");
50 std::vector<int> idxs(rois.rows());
51 std::iota(idxs.begin(), idxs.end(), 0);
54 auto comp = [&scores](
int lhs,
int rhs) {
55 return scores(lhs) > scores(rhs);
57 ERArrXXf rois_copy = rois;
60 if (n > 0 && n < rois.rows()) {
61 std::nth_element(idxs.begin(), idxs.begin() + n, idxs.end(), comp);
62 rois.resize(n, rois.cols());
66 std::sort(idxs.begin(), idxs.begin() + n, comp);
68 for (
int i = 0; i < n; i++) {
69 rois.row(i) = rois_copy.row(idxs[i]);
75 void ArgSort(EArrXi& arr) {
77 std::vector<int> idxs(arr.size());
78 std::iota(std::begin(idxs), std::end(idxs), 0);
79 std::sort(idxs.begin(), idxs.end(), [&arr](
int lhs,
int rhs) {
80 return arr(lhs) < arr(rhs);
83 for (
int i = 0; i < arr.size(); i++) {
90 void RowsWhereRoILevelEquals(Eigen::Ref<const ERArrXXf> rois,
91 const ERArrXXf& lvls,
const int lvl,
92 ERArrXXf* out_filtered, EArrXi* out_indices) {
93 CAFFE_ENFORCE(out_filtered !=
nullptr,
"Output filtered required");
94 CAFFE_ENFORCE(out_indices !=
nullptr,
"Output indices required");
95 CAFFE_ENFORCE(rois.rows() == lvls.rows(),
"RoIs and lvls count mismatch");
97 int filtered_size = (lvls == lvl).rowwise().any().count();
99 out_filtered->resize(filtered_size, rois.cols());
100 out_indices->resize(filtered_size);
101 for (
int i = 0, filtered_idx = 0; i < rois.rows(); i++) {
102 auto lvl_row = lvls.row(i);
103 if ((lvl_row == lvl).any()) {
104 out_filtered->row(filtered_idx) = rois.row(i);
105 (*out_indices)(filtered_idx) = i;
114 bool CollectAndDistributeFpnRpnProposalsOp<CPUContext>::RunOnDevice() {
115 int num_rpn_lvls = rpn_max_level_ - rpn_min_level_ + 1;
116 CAFFE_ENFORCE_EQ(InputSize(), 2 * num_rpn_lvls);
119 const auto& first_roi_in = Input(0);
120 const auto N = first_roi_in.dim(0);
121 CAFFE_ENFORCE_EQ(first_roi_in.dims(), (vector<TIndex>{N, 5}));
124 const auto& first_score_in = Input(num_rpn_lvls);
125 CAFFE_ENFORCE_EQ(first_score_in.dims(), (vector<TIndex>{N}));
127 int num_roi_lvls = roi_max_level_ - roi_min_level_ + 1;
128 CAFFE_ENFORCE_EQ(OutputSize(), num_roi_lvls + 2);
141 ERArrXXf rois(N * num_rpn_lvls, 5);
142 EArrXf scores(N * num_rpn_lvls);
143 for (
int i = 0; i < num_rpn_lvls; i++) {
145 const auto& roi_in = Input(i);
146 CAFFE_ENFORCE_EQ(roi_in.dims(), (vector<TIndex>{N, 5}));
148 Eigen::Map<const ERArrXXf> roi(roi_in.data<
float>(), N, 5);
149 rois.block(i * N, 0, N, 5) = roi;
152 const auto& score_in = Input(num_rpn_lvls + i);
153 CAFFE_ENFORCE_EQ(score_in.dims(), (vector<TIndex>{N}));
157 Eigen::Map<const EArrXf> score(score_in.data<
float>(), N);
158 scores.segment(i * N, N) = score;
165 utils::SortAndLimitRoIsByScores(scores, rpn_post_nms_topN_, rois);
172 const int lvl_min = roi_min_level_;
173 const int lvl_max = roi_max_level_;
174 const int canon_scale = roi_canonical_scale_;
175 const int canon_level = roi_canonical_level_;
176 auto rois_block = rois.block(0, 1, rois.rows(), 4);
177 auto lvls = utils::MapRoIsToFpnLevels(rois_block,
179 canon_scale, canon_level);
184 auto* rois_out = Output(0);
185 rois_out->Resize(rois.rows(), rois.cols());
186 Eigen::Map<ERArrXXf> rois_out_mat(rois_out->mutable_data<
float>(),
187 rois.rows(), rois.cols());
204 EArrXi rois_idx_restore;
205 for (
int i = 0, lvl = lvl_min; i < num_roi_lvls; i++, lvl++) {
206 ERArrXXf blob_roi_level;
208 utils::RowsWhereRoILevelEquals(rois, lvls, lvl, &blob_roi_level, &idx_lvl);
211 auto* roi_out = Output(i + 1);
212 roi_out->Resize(blob_roi_level.rows(), blob_roi_level.cols());
213 Eigen::Map<ERArrXXf> roi_out_mat(roi_out->mutable_data<
float>(),
214 blob_roi_level.rows(),
215 blob_roi_level.cols());
216 roi_out_mat = blob_roi_level;
219 rois_idx_restore.conservativeResize(rois_idx_restore.size() + idx_lvl.size());
220 rois_idx_restore.tail(idx_lvl.size()) = idx_lvl;
222 utils::ArgSort(rois_idx_restore);
223 auto* rois_idx_restore_out = Output(OutputSize() - 1);
224 rois_idx_restore_out->Resize(rois_idx_restore.size());
225 Eigen::Map<EArrXi> rois_idx_restore_out_mat(rois_idx_restore_out->mutable_data<
int>(),
226 rois_idx_restore.size());
227 rois_idx_restore_out_mat = rois_idx_restore;
234 REGISTER_CPU_OPERATOR(CollectAndDistributeFpnRpnProposals, CollectAndDistributeFpnRpnProposalsOp<CPUContext>);
236 #ifdef CAFFE2_HAS_MKL_DNN 237 REGISTER_MKL_OPERATOR(
238 CollectAndDistributeFpnRpnProposals,
239 mkl::MKLFallbackOp<CollectAndDistributeFpnRpnProposalsOp<CPUContext>>);
240 #endif // CAFFE2_HAS_MKL_DNN 242 OPERATOR_SCHEMA(CollectAndDistributeFpnRpnProposals)
243 .NumInputs(2, INT_MAX)
244 .NumOutputs(3, INT_MAX)
246 Merge RPN proposals generated at multiple FPN levels and then 247 distribute those proposals to their appropriate FPN levels for Faster RCNN. 248 An anchor at one FPN level may predict an RoI that will map to another level, 249 hence the need to redistribute the proposals. 251 Only inference is supported. To train, please use the original Python 252 operator in Detectron. 254 Inputs and outputs are examples only; if min/max levels change, 255 the number of inputs and outputs, as well as their level numbering, 258 .Arg("roi_canonical_scale",
"(int) ROI_CANONICAL_SCALE")
259 .Arg(
"roi_canonical_level",
"(int) ROI_CANONICAL_LEVEL")
260 .Arg(
"roi_max_level",
"(int) ROI_MAX_LEVEL")
261 .Arg(
"roi_min_level",
"(int) ROI_MIN_LEVEL")
262 .Arg(
"rpn_max_level",
"(int) RPN_MAX_LEVEL")
263 .Arg(
"rpn_min_level",
"(int) RPN_MIN_LEVEL")
264 .Arg(
"rpn_post_nms_topN",
"(int) RPN_POST_NMS_TOP_N")
268 "RPN proposals for FPN level 2, size (n x 5), " 269 "format (image_index, x1, y1, x2, y2). See rpn_rois " 270 "documentation from GenerateProposals.")
274 "RPN proposals for FPN level 3, size (n x 5), " 275 "format (image_index, x1, y1, x2, y2). See rpn_rois " 276 "documentation from GenerateProposals.")
280 "RPN proposals for FPN level 4, size (n x 5), " 281 "format (image_index, x1, y1, x2, y2). See rpn_rois " 282 "documentation from GenerateProposals.")
286 "RPN proposals for FPN level 5, size (n x 5), " 287 "format (image_index, x1, y1, x2, y2). See rpn_rois " 288 "documentation from GenerateProposals.")
292 "RPN proposals for FPN level 6, size (n x 5), " 293 "format (image_index, x1, y1, x2, y2). See rpn_rois " 294 "documentation from GenerateProposals.")
297 "rpn_roi_probs_fpn2",
298 "RPN objectness probabilities for FPN level 2, size (n). " 299 "See rpn_roi_probs documentation from GenerateProposals.")
302 "rpn_roi_probs_fpn3",
303 "RPN objectness probabilities for FPN level 3, size (n). " 304 "See rpn_roi_probs documentation from GenerateProposals.")
307 "rpn_roi_probs_fpn4",
308 "RPN objectness probabilities for FPN level 4, size (n). " 309 "See rpn_roi_probs documentation from GenerateProposals.")
312 "rpn_roi_probs_fpn5",
313 "RPN objectness probabilities for FPN level 5, size (n). " 314 "See rpn_roi_probs documentation from GenerateProposals.")
317 "rpn_roi_probs_fpn6",
318 "RPN objectness probabilities for FPN level 6, size (n). " 319 "See rpn_roi_probs documentation from GenerateProposals.")
323 "Top proposals limited to rpn_post_nms_topN total, " 324 "size (n x 5), format (image_index, x1, y1, x2, y2)")
328 "RPN proposals for ROI level 2, size (n x 5), " 329 "format (image_index, x1, y1, x2, y2)")
333 "RPN proposals for ROI level 3, size (n x 5), " 334 "format (image_index, x1, y1, x2, y2)")
338 "RPN proposals for ROI level 4, size (n x 5), " 339 "format (image_index, x1, y1, x2, y2)")
343 "RPN proposals for ROI level 5, size (n x 5), " 344 "format (image_index, x1, y1, x2, y2)")
348 "Permutation on the concatenation of all " 349 "rois_fpni, i=min...max, such that when applied the RPN RoIs are " 350 "restored to their original order in the input blobs.");
352 SHOULD_NOT_DO_GRADIENT(CollectAndDistributeFpnRpnProposals);
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...