1 #ifndef CAFFE2_OPERATORS_UTILS_NMS_H_ 2 #define CAFFE2_OPERATORS_UTILS_NMS_H_ 7 #include "caffe2/utils/eigen_utils.h" 9 #include "caffe2/core/logging.h" 10 #include "caffe2/utils/math.h" 25 template <
class Derived1,
class Derived2>
26 std::vector<int> nms_cpu(
27 const Eigen::ArrayBase<Derived1>& proposals,
28 const Eigen::ArrayBase<Derived2>& scores,
29 const std::vector<int>& sorted_indices,
32 CAFFE_ENFORCE_EQ(proposals.rows(), scores.rows());
33 CAFFE_ENFORCE_EQ(proposals.cols(), 4);
34 CAFFE_ENFORCE_EQ(scores.cols(), 1);
35 CAFFE_ENFORCE_LE(sorted_indices.size(), proposals.rows());
37 using EArrX = EArrXt<typename Derived1::Scalar>;
39 auto x1 = proposals.col(0);
40 auto y1 = proposals.col(1);
41 auto x2 = proposals.col(2);
42 auto y2 = proposals.col(3);
44 EArrX areas = (x2 - x1 + 1.0) * (y2 - y1 + 1.0);
46 EArrXi order = AsEArrXt(sorted_indices);
47 std::vector<int> keep;
49 while (order.size() > 0) {
51 if (topN >= 0 && keep.size() >= topN) {
57 ConstEigenVectorArrayMap<int> rest_indices(
58 order.data() + 1, order.size() - 1);
59 EArrX xx1 = GetSubArray(x1, rest_indices).cwiseMax(x1[i]);
60 EArrX yy1 = GetSubArray(y1, rest_indices).cwiseMax(y1[i]);
61 EArrX xx2 = GetSubArray(x2, rest_indices).cwiseMin(x2[i]);
62 EArrX yy2 = GetSubArray(y2, rest_indices).cwiseMin(y2[i]);
64 EArrX w = (xx2 - xx1 + 1.0).cwiseMax(0.0);
65 EArrX h = (yy2 - yy1 + 1.0).cwiseMax(0.0);
67 EArrX ovr = inter / (areas[i] + GetSubArray(areas, rest_indices) - inter);
70 auto inds = GetArrayIndices(ovr <= thresh);
71 order = GetSubArray(order, AsEArrXt(inds) + 1);
86 template <
class Derived1,
class Derived2>
87 std::vector<int> nms_cpu(
88 const Eigen::ArrayBase<Derived1>& proposals,
89 const Eigen::ArrayBase<Derived2>& scores,
91 std::vector<int> indices(proposals.rows());
92 std::iota(indices.begin(), indices.end(), 0);
95 indices.data() + indices.size(),
96 [&scores](
int lhs,
int rhs) {
return scores(lhs) > scores(rhs); });
98 return nms_cpu(proposals, scores, indices, thres);
116 template <
class Derived1,
class Derived2,
class Derived3>
117 std::vector<int> soft_nms_cpu(
118 Eigen::ArrayBase<Derived3>* out_scores,
119 const Eigen::ArrayBase<Derived1>& proposals,
120 const Eigen::ArrayBase<Derived2>& scores,
121 const std::vector<int>& indices,
123 float overlap_thresh = 0.3,
124 float score_thresh = 0.001,
125 unsigned int method = 1,
127 CAFFE_ENFORCE_EQ(proposals.rows(), scores.rows());
128 CAFFE_ENFORCE_EQ(proposals.cols(), 4);
129 CAFFE_ENFORCE_EQ(scores.cols(), 1);
131 using EArrX = EArrXt<typename Derived1::Scalar>;
133 const auto& x1 = proposals.col(0);
134 const auto& y1 = proposals.col(1);
135 const auto& x2 = proposals.col(2);
136 const auto& y2 = proposals.col(3);
138 EArrX areas = (x2 - x1 + 1.0) * (y2 - y1 + 1.0);
142 *out_scores = scores;
144 std::vector<int> keep;
145 EArrXi pending = AsEArrXt(indices);
146 while (pending.size() > 0) {
148 if (topN >= 0 && keep.size() >= topN) {
154 auto max_score = GetSubArray(*out_scores, pending).maxCoeff(&max_pos);
155 int i = pending[max_pos];
159 std::swap(pending(0), pending(max_pos));
160 const auto& rest_indices = pending.tail(pending.size() - 1);
161 EArrX xx1 = GetSubArray(x1, rest_indices).cwiseMax(x1[i]);
162 EArrX yy1 = GetSubArray(y1, rest_indices).cwiseMax(y1[i]);
163 EArrX xx2 = GetSubArray(x2, rest_indices).cwiseMin(x2[i]);
164 EArrX yy2 = GetSubArray(y2, rest_indices).cwiseMin(y2[i]);
166 EArrX w = (xx2 - xx1 + 1.0).cwiseMax(0.0);
167 EArrX h = (yy2 - yy1 + 1.0).cwiseMax(0.0);
169 EArrX ovr = inter / (areas[i] + GetSubArray(areas, rest_indices) - inter);
172 for (
int j = 0; j < rest_indices.size(); ++j) {
173 typename Derived2::Scalar weight;
176 weight = (ovr(j) > overlap_thresh) ? (1.0 - ovr(j)) : 1.0;
179 weight = std::exp(-1.0 * ovr(j) * ovr(j) / sigma);
182 weight = (ovr(j) > overlap_thresh) ? 0.0 : 1.0;
184 (*out_scores)(rest_indices[j]) *= weight;
189 const auto& rest_scores = GetSubArray(*out_scores, rest_indices);
190 const auto& inds = GetArrayIndices(rest_scores >= score_thresh);
191 pending = GetSubArray(rest_indices, AsEArrXt(inds));
197 template <
class Derived1,
class Derived2,
class Derived3>
198 std::vector<int> soft_nms_cpu(
199 Eigen::ArrayBase<Derived3>* out_scores,
200 const Eigen::ArrayBase<Derived1>& proposals,
201 const Eigen::ArrayBase<Derived2>& scores,
203 float overlap_thresh = 0.3,
204 float score_thresh = 0.001,
205 unsigned int method = 1,
207 std::vector<int> indices(proposals.rows());
208 std::iota(indices.begin(), indices.end(), 0);
224 #endif // CAFFE2_OPERATORS_UTILS_NMS_H_ A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...