Blame view

3rdparty/opencv-4.5.4/modules/dnn/src/nms.inl.hpp 3.54 KB
f4334277   Hu Chunming   提交3rdparty
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
  // This file is part of OpenCV project.
  // It is subject to the license terms in the LICENSE file found in the top-level directory
  // of this distribution and at http://opencv.org/license.html.
  //
  // Copyright (C) 2017, Intel Corporation, all rights reserved.
  // Third party copyrights are property of their respective owners.
  
  #ifndef OPENCV_DNN_NMS_INL_HPP
  #define OPENCV_DNN_NMS_INL_HPP
  
  #include <opencv2/dnn.hpp>
  
  namespace cv {
  namespace dnn {
  
  namespace
  {
  
  template <typename T>
  static inline bool SortScorePairDescend(const std::pair<float, T>& pair1,
                            const std::pair<float, T>& pair2)
  {
      return pair1.first > pair2.first;
  }
  
  } // namespace
  
  // Get max scores with corresponding indices.
  //    scores: a set of scores.
  //    threshold: only consider scores higher than the threshold.
  //    top_k: if -1, keep all; otherwise, keep at most top_k.
  //    score_index_vec: store the sorted (score, index) pair.
  inline void GetMaxScoreIndex(const std::vector<float>& scores, const float threshold, const int top_k,
                        std::vector<std::pair<float, int> >& score_index_vec)
  {
      CV_DbgAssert(score_index_vec.empty());
      // Generate index score pairs.
      for (size_t i = 0; i < scores.size(); ++i)
      {
          if (scores[i] > threshold)
          {
              score_index_vec.push_back(std::make_pair(scores[i], i));
          }
      }
  
      // Sort the score pair according to the scores in descending order
      std::stable_sort(score_index_vec.begin(), score_index_vec.end(),
                       SortScorePairDescend<int>);
  
      // Keep top_k scores if needed.
      if (top_k > 0 && top_k < (int)score_index_vec.size())
      {
          score_index_vec.resize(top_k);
      }
  }
  
  // Do non maximum suppression given bboxes and scores.
  // Inspired by Piotr Dollar's NMS implementation in EdgeBox.
  // https://goo.gl/jV3JYS
  //    bboxes: a set of bounding boxes.
  //    scores: a set of corresponding confidences.
  //    score_threshold: a threshold used to filter detection results.
  //    nms_threshold: a threshold used in non maximum suppression.
  //    top_k: if not > 0, keep at most top_k picked indices.
  //    limit: early terminate once the # of picked indices has reached it.
  //    indices: the kept indices of bboxes after nms.
  template <typename BoxType>
  inline void 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())
  {
      CV_Assert(bboxes.size() == scores.size());
  
      // Get top_k scores (with corresponding indices).
      std::vector<std::pair<float, int> > score_index_vec;
      GetMaxScoreIndex(scores, score_threshold, top_k, score_index_vec);
  
      // Do nms.
      float adaptive_threshold = nms_threshold;
      indices.clear();
      for (size_t i = 0; i < score_index_vec.size(); ++i) {
          const int idx = score_index_vec[i].second;
          bool keep = true;
          for (int k = 0; k < (int)indices.size() && keep; ++k) {
              const int kept_idx = indices[k];
              float overlap = computeOverlap(bboxes[idx], bboxes[kept_idx]);
              keep = overlap <= adaptive_threshold;
          }
          if (keep) {
              indices.push_back(idx);
              if (indices.size() >= limit) {
                  break;
              }
          }
          if (keep && eta < 1 && adaptive_threshold > 0.5) {
            adaptive_threshold *= eta;
          }
      }
  }
  
  }// dnn
  }// cv
  
  #endif