mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 09:25:45 +08:00
batched nms impl
This commit is contained in:
parent
6ca205a029
commit
9fded9ca53
@ -1194,6 +1194,27 @@ CV__DNN_INLINE_NS_BEGIN
|
|||||||
CV_OUT std::vector<int>& indices,
|
CV_OUT std::vector<int>& indices,
|
||||||
const float eta = 1.f, const int top_k = 0);
|
const float eta = 1.f, const int top_k = 0);
|
||||||
|
|
||||||
|
/** @brief Performs batched non maximum suppression on given boxes and corresponding scores across different classes.
|
||||||
|
|
||||||
|
* @param bboxes a set of bounding boxes to apply NMS.
|
||||||
|
* @param scores a set of corresponding confidences.
|
||||||
|
* @param class_ids a set of corresponding class ids. Ids are integer and usually start from 0.
|
||||||
|
* @param score_threshold a threshold used to filter boxes by score.
|
||||||
|
* @param nms_threshold a threshold used in non maximum suppression.
|
||||||
|
* @param indices the kept indices of bboxes after NMS.
|
||||||
|
* @param eta a coefficient in adaptive threshold formula: \f$nms\_threshold_{i+1}=eta\cdot nms\_threshold_i\f$.
|
||||||
|
* @param top_k if `>0`, keep at most @p top_k picked indices.
|
||||||
|
*/
|
||||||
|
CV_EXPORTS void NMSBoxesBatched(const std::vector<Rect>& bboxes, const std::vector<float>& scores, const std::vector<int>& class_ids,
|
||||||
|
const float score_threshold, const float nms_threshold,
|
||||||
|
CV_OUT std::vector<int>& indices,
|
||||||
|
const float eta = 1.f, const int top_k = 0);
|
||||||
|
|
||||||
|
CV_EXPORTS_W void NMSBoxesBatched(const std::vector<Rect2d>& bboxes, const std::vector<float>& scores, const std::vector<int>& class_ids,
|
||||||
|
const float score_threshold, const float nms_threshold,
|
||||||
|
CV_OUT std::vector<int>& indices,
|
||||||
|
const float eta = 1.f, const int top_k = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enum of Soft NMS methods.
|
* @brief Enum of Soft NMS methods.
|
||||||
* @see softNMSBoxes
|
* @see softNMSBoxes
|
||||||
|
@ -58,6 +58,61 @@ void NMSBoxes(const std::vector<RotatedRect>& bboxes, const std::vector<float>&
|
|||||||
NMSFast_(bboxes, scores, score_threshold, nms_threshold, eta, top_k, indices, rotatedRectIOU);
|
NMSFast_(bboxes, scores, score_threshold, nms_threshold, eta, top_k, indices, rotatedRectIOU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Rect_t>
|
||||||
|
static inline void NMSBoxesBatchedImpl(const std::vector<Rect_t>& bboxes,
|
||||||
|
const std::vector<float>& scores, const std::vector<int>& class_ids,
|
||||||
|
const float score_threshold, const float nms_threshold,
|
||||||
|
std::vector<int>& indices, const float eta, const int top_k)
|
||||||
|
{
|
||||||
|
double x1, y1, x2, y2, max_coord = 0;
|
||||||
|
for (int i = 0; i < bboxes.size(); i++)
|
||||||
|
{
|
||||||
|
x1 = bboxes[i].x;
|
||||||
|
y1 = bboxes[i].y;
|
||||||
|
x2 = x1 + bboxes[i].width;
|
||||||
|
y2 = y1 + bboxes[i].height;
|
||||||
|
|
||||||
|
max_coord = std::max(x1, max_coord);
|
||||||
|
max_coord = std::max(y1, max_coord);
|
||||||
|
max_coord = std::max(x2, max_coord);
|
||||||
|
max_coord = std::max(y2, max_coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate offset and add offset to each bbox
|
||||||
|
std::vector<Rect_t> bboxes_offset;
|
||||||
|
double offset;
|
||||||
|
for (int i = 0; i < bboxes.size(); i++)
|
||||||
|
{
|
||||||
|
offset = class_ids[i] * (max_coord + 1);
|
||||||
|
bboxes_offset.push_back(
|
||||||
|
Rect_t(bboxes[i].x + offset, bboxes[i].y + offset,
|
||||||
|
bboxes[i].width, bboxes[i].height)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
NMSFast_(bboxes_offset, scores, score_threshold, nms_threshold, eta, top_k, indices, rectOverlap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NMSBoxesBatched(const std::vector<Rect>& bboxes,
|
||||||
|
const std::vector<float>& scores, const std::vector<int>& class_ids,
|
||||||
|
const float score_threshold, const float nms_threshold,
|
||||||
|
std::vector<int>& indices, const float eta, const int top_k)
|
||||||
|
{
|
||||||
|
CV_Assert_N(bboxes.size() == scores.size(), scores.size() == class_ids.size(), nms_threshold >= 0, eta > 0);
|
||||||
|
|
||||||
|
NMSBoxesBatchedImpl(bboxes, scores, class_ids, score_threshold, nms_threshold, indices, eta, top_k);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NMSBoxesBatched(const std::vector<Rect2d>& bboxes,
|
||||||
|
const std::vector<float>& scores, const std::vector<int>& class_ids,
|
||||||
|
const float score_threshold, const float nms_threshold,
|
||||||
|
std::vector<int>& indices, const float eta, const int top_k)
|
||||||
|
{
|
||||||
|
CV_Assert_N(bboxes.size() == scores.size(), scores.size() == class_ids.size(), nms_threshold >= 0, eta > 0);
|
||||||
|
|
||||||
|
NMSBoxesBatchedImpl(bboxes, scores, class_ids, score_threshold, nms_threshold, indices, eta, top_k);
|
||||||
|
}
|
||||||
|
|
||||||
void softNMSBoxes(const std::vector<Rect>& bboxes,
|
void softNMSBoxes(const std::vector<Rect>& bboxes,
|
||||||
const std::vector<float>& scores,
|
const std::vector<float>& scores,
|
||||||
std::vector<float>& updated_scores,
|
std::vector<float>& updated_scores,
|
||||||
|
@ -37,6 +37,36 @@ TEST(NMS, Accuracy)
|
|||||||
ASSERT_EQ(indices[i], ref_indices[i]);
|
ASSERT_EQ(indices[i], ref_indices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BatchedNMS, Accuracy)
|
||||||
|
{
|
||||||
|
//reference results obtained using tf.image.non_max_suppression with iou_threshold=0.5
|
||||||
|
std::string dataPath = findDataFile("dnn/batched_nms_reference.yml");
|
||||||
|
FileStorage fs(dataPath, FileStorage::READ);
|
||||||
|
|
||||||
|
std::vector<Rect> bboxes;
|
||||||
|
std::vector<float> scores;
|
||||||
|
std::vector<int> idxs;
|
||||||
|
std::vector<int> ref_indices;
|
||||||
|
|
||||||
|
fs["boxes"] >> bboxes;
|
||||||
|
fs["probs"] >> scores;
|
||||||
|
fs["idxs"] >> idxs;
|
||||||
|
fs["output"] >> ref_indices;
|
||||||
|
|
||||||
|
const float nms_thresh = .5f;
|
||||||
|
const float score_thresh = .05f;
|
||||||
|
std::vector<int> indices;
|
||||||
|
cv::dnn::NMSBoxesBatched(bboxes, scores, idxs, score_thresh, nms_thresh, indices);
|
||||||
|
|
||||||
|
ASSERT_EQ(ref_indices.size(), indices.size());
|
||||||
|
|
||||||
|
std::sort(indices.begin(), indices.end());
|
||||||
|
std::sort(ref_indices.begin(), ref_indices.end());
|
||||||
|
|
||||||
|
for(size_t i = 0; i < indices.size(); i++)
|
||||||
|
ASSERT_EQ(indices[i], ref_indices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SoftNMS, Accuracy)
|
TEST(SoftNMS, Accuracy)
|
||||||
{
|
{
|
||||||
//reference results are obtained using TF v2.7 tf.image.non_max_suppression_with_scores
|
//reference results are obtained using TF v2.7 tf.image.non_max_suppression_with_scores
|
||||||
|
Loading…
Reference in New Issue
Block a user