1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2017, Intel Corporation, all rights reserved.
6 // Third party copyrights are property of their respective owners.
7
8 #ifndef OPENCV_DNN_NMS_INL_HPP
9 #define OPENCV_DNN_NMS_INL_HPP
10
11 #include <opencv2/dnn.hpp>
12
13 namespace cv {
14 namespace dnn {
15
16 namespace
17 {
18
19 template <typename T>
SortScorePairDescend(const std::pair<float,T> & pair1,const std::pair<float,T> & pair2)20 static inline bool SortScorePairDescend(const std::pair<float, T>& pair1,
21 const std::pair<float, T>& pair2)
22 {
23 return pair1.first > pair2.first;
24 }
25
26 } // namespace
27
28 // Get max scores with corresponding indices.
29 // scores: a set of scores.
30 // threshold: only consider scores higher than the threshold.
31 // top_k: if -1, keep all; otherwise, keep at most top_k.
32 // score_index_vec: store the sorted (score, index) pair.
GetMaxScoreIndex(const std::vector<float> & scores,const float threshold,const int top_k,std::vector<std::pair<float,int>> & score_index_vec)33 inline void GetMaxScoreIndex(const std::vector<float>& scores, const float threshold, const int top_k,
34 std::vector<std::pair<float, int> >& score_index_vec)
35 {
36 CV_DbgAssert(score_index_vec.empty());
37 // Generate index score pairs.
38 for (size_t i = 0; i < scores.size(); ++i)
39 {
40 if (scores[i] > threshold)
41 {
42 score_index_vec.push_back(std::make_pair(scores[i], i));
43 }
44 }
45
46 // Sort the score pair according to the scores in descending order
47 std::stable_sort(score_index_vec.begin(), score_index_vec.end(),
48 SortScorePairDescend<int>);
49
50 // Keep top_k scores if needed.
51 if (top_k > 0 && top_k < (int)score_index_vec.size())
52 {
53 score_index_vec.resize(top_k);
54 }
55 }
56
57 // Do non maximum suppression given bboxes and scores.
58 // Inspired by Piotr Dollar's NMS implementation in EdgeBox.
59 // https://goo.gl/jV3JYS
60 // bboxes: a set of bounding boxes.
61 // scores: a set of corresponding confidences.
62 // score_threshold: a threshold used to filter detection results.
63 // nms_threshold: a threshold used in non maximum suppression.
64 // top_k: if not > 0, keep at most top_k picked indices.
65 // limit: early terminate once the # of picked indices has reached it.
66 // indices: the kept indices of bboxes after nms.
67 template <typename BoxType>
NMSFast_(const std::vector<BoxType> & bboxes,const std::vector<float> & scores,const float score_threshold,const float nms_threshold,const float eta,const int top_k,std::vector<int> & indices,float (* computeOverlap)(const BoxType &,const BoxType &),int limit=std::numeric_limits<int>::max ())68 inline void NMSFast_(const std::vector<BoxType>& bboxes,
69 const std::vector<float>& scores, const float score_threshold,
70 const float nms_threshold, const float eta, const int top_k,
71 std::vector<int>& indices,
72 float (*computeOverlap)(const BoxType&, const BoxType&),
73 int limit = std::numeric_limits<int>::max())
74 {
75 CV_Assert(bboxes.size() == scores.size());
76
77 // Get top_k scores (with corresponding indices).
78 std::vector<std::pair<float, int> > score_index_vec;
79 GetMaxScoreIndex(scores, score_threshold, top_k, score_index_vec);
80
81 // Do nms.
82 float adaptive_threshold = nms_threshold;
83 indices.clear();
84 for (size_t i = 0; i < score_index_vec.size(); ++i) {
85 const int idx = score_index_vec[i].second;
86 bool keep = true;
87 for (int k = 0; k < (int)indices.size() && keep; ++k) {
88 const int kept_idx = indices[k];
89 float overlap = computeOverlap(bboxes[idx], bboxes[kept_idx]);
90 keep = overlap <= adaptive_threshold;
91 }
92 if (keep) {
93 indices.push_back(idx);
94 if (indices.size() >= limit) {
95 break;
96 }
97 }
98 if (keep && eta < 1 && adaptive_threshold > 0.5) {
99 adaptive_threshold *= eta;
100 }
101 }
102 }
103
104 }// dnn
105 }// cv
106
107 #endif
108