*/
CV_EXPORTS_W void shrinkCaffeModel(const String& src, const String& dst);
+ /** @brief
+ * @param bboxes
+ * @param scores
+ * @param score_threshold
+ * @param nms_threshold
+ * @param eta
+ * @param top_k
+ * @param indices
+ */
+ CV_EXPORTS_W void NMSBoxes(const std::vector<Rect>& bboxes, const std::vector<float>& scores,
+ const float score_threshold, const float nms_threshold,
+ const float eta, const int top_k, CV_OUT std::vector<int>& indices);
+
//! @}
CV__DNN_EXPERIMENTAL_NS_END
--- /dev/null
+// 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 > -1 && top_k < (int)score_index_vec.size())
+ {
+ score_index_vec.resize(top_k);
+ }
+}
+
+template <typename BoxType>
+struct NMSOverlap
+{
+ float operator() (const BoxType& a, const BoxType& b);
+};
+
+template <>
+inline float NMSOverlap<Rect>::operator() (const Rect& a, const Rect& b)
+{
+ float rectIntersectionArea = (float)(a & b).area();
+ return rectIntersectionArea / (a.area() + b.area() - rectIntersectionArea);
+}
+
+// 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 -1, keep at most top_k picked indices.
+// 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, NMSOverlap<BoxType> computeOverlap)
+{
+ 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();
+ while (score_index_vec.size() != 0) {
+ const int idx = score_index_vec.front().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);
+ score_index_vec.erase(score_index_vec.begin());
+ if (keep && eta < 1 && adaptive_threshold > 0.5) {
+ adaptive_threshold *= eta;
+ }
+ }
+}
+
+}// dnn
+}// cv
+
+#endif
#include <float.h>
#include <string>
#include <caffe.pb.h>
+#include <opencv2/dnn/nms.inl.hpp>
namespace cv
{
}
}
- // 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 -1, keep at most top_k picked indices.
- // indices: the kept indices of bboxes after nms.
+
+
static void ApplyNMSFast(const std::vector<caffe::NormalizedBBox>& 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)
{
- 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();
- while (score_index_vec.size() != 0) {
- const int idx = score_index_vec.front().second;
- bool keep = true;
- for (int k = 0; k < (int)indices.size() && keep; ++k) {
- const int kept_idx = indices[k];
- float overlap = JaccardOverlap<true>(bboxes[idx], bboxes[kept_idx]);
- keep = overlap <= adaptive_threshold;
- }
- if (keep)
- indices.push_back(idx);
- score_index_vec.erase(score_index_vec.begin());
- if (keep && eta < 1 && adaptive_threshold > 0.5) {
- adaptive_threshold *= eta;
- }
- }
- }
-
- // 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.
- static 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(),
- util::SortScorePairDescend<int>);
-
- // Keep top_k scores if needed.
- if (top_k > -1 && top_k < (int)score_index_vec.size())
- {
- score_index_vec.resize(top_k);
- }
+ NMSFast_(bboxes, scores, score_threshold, nms_threshold, eta, top_k, indices, NMSOverlap<caffe::NormalizedBBox>());
}
// Compute the jaccard (intersection over union IoU) overlap between two bboxes.
}
};
+template <>
+float NMSOverlap<caffe::NormalizedBBox>::operator() (const caffe::NormalizedBBox& a, const caffe::NormalizedBBox& b)
+{
+ return DetectionOutputLayerImpl::JaccardOverlap<true>(a, b);
+}
+
const std::string DetectionOutputLayerImpl::_layerName = std::string("DetectionOutput");
Ptr<DetectionOutputLayer> DetectionOutputLayer::create(const LayerParams ¶ms)
--- /dev/null
+// 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.
+
+#include "precomp.hpp"
+#include <opencv2/dnn/nms.inl.hpp>
+
+namespace cv
+{
+namespace dnn
+{
+
+void NMSBoxes(const std::vector<Rect>& 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)
+{
+ NMSFast_(bboxes, scores, score_threshold, nms_threshold, eta, top_k, indices, NMSOverlap<Rect>());
+}
+
+}// dnn
+}// cv