|
|
|
@@ -19,18 +19,84 @@ |
|
|
|
#include "nnacl/errorcode.h" |
|
|
|
#include "nnacl/op_base.h" |
|
|
|
|
|
|
|
int ScoreWithIndexCmp(const void *a, const void *b) { |
|
|
|
ScoreWithIndex *pa = (ScoreWithIndex *)a; |
|
|
|
ScoreWithIndex *pb = (ScoreWithIndex *)b; |
|
|
|
bool ScoreWithIndexCmp(ScoreWithIndex *pa, ScoreWithIndex *pb) { |
|
|
|
if (pa->score > pb->score) { |
|
|
|
return -1; |
|
|
|
return true; |
|
|
|
} else if (pa->score < pb->score) { |
|
|
|
return 1; |
|
|
|
return false; |
|
|
|
} else { |
|
|
|
return pa->index - pb->index; |
|
|
|
return pa->index < pb->index; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void PushHeap(ScoreWithIndex *root, int cur, int top_index, ScoreWithIndex value) { |
|
|
|
int parent = (cur - 1) / 2; |
|
|
|
while (cur > top_index && ScoreWithIndexCmp(root + parent, &value)) { |
|
|
|
*(root + cur) = root[parent]; |
|
|
|
cur = parent; |
|
|
|
parent = (cur - 1) / 2; |
|
|
|
} |
|
|
|
*(root + cur) = value; |
|
|
|
} |
|
|
|
|
|
|
|
void AdjustHeap(ScoreWithIndex *root, int cur, int limit, ScoreWithIndex value) { |
|
|
|
int top_index = cur; |
|
|
|
int second_child = cur; |
|
|
|
while (second_child < (limit - 1) / 2) { |
|
|
|
second_child = 2 * (second_child + 1); |
|
|
|
if (ScoreWithIndexCmp(root + second_child, root + second_child - 1)) { |
|
|
|
second_child--; |
|
|
|
} |
|
|
|
*(root + cur) = *(root + second_child); |
|
|
|
cur = second_child; |
|
|
|
} |
|
|
|
if ((limit & 1) == 0 && second_child == (limit - 2) / 2) { |
|
|
|
second_child = 2 * (second_child + 1); |
|
|
|
*(root + cur) = *(root + second_child - 1); |
|
|
|
cur = second_child - 1; |
|
|
|
} |
|
|
|
PushHeap(root, cur, top_index, value); |
|
|
|
} |
|
|
|
|
|
|
|
void PopHeap(ScoreWithIndex *root, int limit, ScoreWithIndex *result) { |
|
|
|
ScoreWithIndex value = *result; |
|
|
|
*result = *root; |
|
|
|
AdjustHeap(root, 0, limit, value); |
|
|
|
} |
|
|
|
|
|
|
|
void MakeHeap(ScoreWithIndex *values, int limit) { |
|
|
|
if (limit < 2) return; |
|
|
|
int parent = (limit - 2) / 2; |
|
|
|
while (true) { |
|
|
|
AdjustHeap(values, parent, limit, values[parent]); |
|
|
|
if (parent == 0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
parent--; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void SortHeap(ScoreWithIndex *root, int limit) { |
|
|
|
while (limit > 1) { |
|
|
|
--limit; |
|
|
|
PopHeap(root, limit, root + limit); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void HeapSelect(ScoreWithIndex *root, int cur, int limit) { |
|
|
|
MakeHeap(root, cur); |
|
|
|
for (int i = cur; i < limit; ++i) { |
|
|
|
if (ScoreWithIndexCmp(root + i, root)) { |
|
|
|
PopHeap(root, cur, root + i); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void PartialSort(ScoreWithIndex *values, int num_to_sort, int num_values) { |
|
|
|
HeapSelect(values, num_to_sort, num_values); |
|
|
|
SortHeap(values, num_to_sort); |
|
|
|
} |
|
|
|
|
|
|
|
float IntersectionOverUnion(const BboxCorner *a, const BboxCorner *b) { |
|
|
|
const float area_a = (a->ymax - a->ymin) * (a->xmax - a->xmin); |
|
|
|
const float area_b = (b->ymax - b->ymin) * (b->xmax - b->xmin); |
|
|
|
@@ -70,7 +136,7 @@ int NmsSingleClass(const int candidate_num, const float *decoded_boxes, const in |
|
|
|
const int output_num = candidate_num < max_detections ? candidate_num : max_detections; |
|
|
|
int possible_candidate_num = candidate_num; |
|
|
|
int selected_num = 0; |
|
|
|
qsort(score_with_index, candidate_num, sizeof(ScoreWithIndex), ScoreWithIndexCmp); |
|
|
|
PartialSort(score_with_index, candidate_num, candidate_num); |
|
|
|
for (int i = 0; i < candidate_num; ++i) { |
|
|
|
nms_candidate[i] = 1; |
|
|
|
} |
|
|
|
@@ -134,7 +200,7 @@ int NmsMultiClassesRegular(const int num_boxes, const int num_classes_with_bg, c |
|
|
|
} |
|
|
|
all_classes_output_num = |
|
|
|
all_classes_sorted_num < param->max_detections_ ? all_classes_sorted_num : param->max_detections_; |
|
|
|
qsort(score_with_index_all, all_classes_sorted_num, sizeof(ScoreWithIndex), ScoreWithIndexCmp); |
|
|
|
PartialSort(score_with_index_all, all_classes_output_num, all_classes_sorted_num); |
|
|
|
for (int i = 0; i < all_classes_output_num; ++i) { |
|
|
|
score_with_index_all[i].index = indexes[score_with_index_all[i].index]; |
|
|
|
} |
|
|
|
@@ -178,8 +244,7 @@ int NmsMultiClassesFast(const int num_boxes, const int num_classes_with_bg, cons |
|
|
|
// save box and class info to index |
|
|
|
score_with_class_all[i * param->num_classes_ + j - first_class_index].index = i * num_classes_with_bg + j; |
|
|
|
} |
|
|
|
qsort(score_with_class_all + i * param->num_classes_, param->num_classes_, sizeof(ScoreWithIndex), |
|
|
|
ScoreWithIndexCmp); |
|
|
|
PartialSort(score_with_class_all + i * param->num_classes_, max_classes_per_anchor, param->num_classes_); |
|
|
|
const float score_max = (score_with_class_all + i * param->num_classes_)->score; |
|
|
|
if (score_max >= param->nms_score_threshold_) { |
|
|
|
score_with_class[candidate_num].index = i; |
|
|
|
|