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