Skip to content

Commit 65c3c7c

Browse files
mitruskamlukasze
andauthored
[Opset13] Fix NMSRotated-13 reference sorting across batch (openvinotoolkit#20669)
* Add sort to test params * Add more tests, batch, classes, sort * test_sort_batch * Fix sorting if sort_result_desc true * Diable clang for test data * Reenable type tests * Fix comment * Use std tie for values comparison * Update var names to lhs and rhs * Apply alignment with nms patch for GPU --------- Co-authored-by: Michal Lukaszewski <michal.lukaszewski@intel.com>
1 parent c491381 commit 65c3c7c

File tree

3 files changed

+146
-18
lines changed

3 files changed

+146
-18
lines changed

src/core/reference/src/op/nms_rotated.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,11 @@ void nms_rotated(const float* boxes_data,
195195
}
196196

197197
if (sort_result_descending) {
198-
std::reverse(filteredBoxes.begin(), filteredBoxes.end());
198+
std::stable_sort(filteredBoxes.begin(), filteredBoxes.end(), [](const BoxInfo& lhs, const BoxInfo& rhs) {
199+
return (lhs.score > rhs.score) ||
200+
((lhs.score == rhs.score) && (std::tie(lhs.batch_index, lhs.class_index, lhs.index) <
201+
std::tie(rhs.batch_index, rhs.class_index, rhs.index)));
202+
});
199203
}
200204

201205
size_t max_num_of_selected_indices = selected_indices_shape[0];

src/plugins/intel_gpu/src/kernel_selector/cl_kernels/non_max_suppression_gpu_ref.cl

-15
Original file line numberDiff line numberDiff line change
@@ -566,16 +566,6 @@ inline void FUNC(swap)(__global BOX_INFO* a, __global BOX_INFO* b)
566566
*b = temp;
567567
}
568568

569-
#ifdef ROTATION
570-
inline void FUNC(reverseOutputBoxList)(__global BOX_INFO *outBoxes, int boxNum)
571-
{
572-
for (int i = 0; i < boxNum / 2; ++i) {
573-
FUNC_CALL(swap)(&outBoxes[i], &outBoxes[boxNum - 1 - i]);
574-
}
575-
}
576-
577-
#else
578-
579569
inline void FUNC(sortOutputBoxList)(__global BOX_INFO *outSortedBoxes, int boxNum)
580570
{
581571
for (int i = 0; i < boxNum - 1; ++i) {
@@ -597,7 +587,6 @@ inline void FUNC(sortOutputBoxList)(__global BOX_INFO *outSortedBoxes, int boxNu
597587
break;
598588
}
599589
}
600-
#endif // ROTATION
601590

602591

603592
#ifdef NMS_STAGE_0
@@ -880,11 +869,7 @@ KERNEL (non_max_suppression_ref_stage_3)(
880869
}
881870

882871
#if SORT_RESULT_DESCENDING == 1
883-
#ifdef ROTATION
884-
FUNC_CALL(reverseOutputBoxList)(sortedBoxList, outputIdx);
885-
#else
886872
FUNC_CALL(sortOutputBoxList)(sortedBoxList, outputIdx);
887-
#endif
888873
#endif
889874

890875
unroll_for (int i = 0; i < outputIdx; i++) {

src/plugins/template/tests/functional/op_reference/nms_rotated.cpp

+141-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct NMSRotatedParams {
2121
reference_tests::Tensor iouThreshold;
2222
reference_tests::Tensor scoreThreshold;
2323
reference_tests::Tensor softNmsSigma;
24+
bool sortResultsDescending = true;
2425
bool clockwise = true;
2526
reference_tests::Tensor expectedSelectedIndices;
2627
reference_tests::Tensor expectedSelectedScores;
@@ -35,6 +36,7 @@ struct Builder : ParamsBuilder<NMSRotatedParams> {
3536
REFERENCE_TESTS_ADD_SET_PARAM(Builder, iouThreshold);
3637
REFERENCE_TESTS_ADD_SET_PARAM(Builder, scoreThreshold);
3738
REFERENCE_TESTS_ADD_SET_PARAM(Builder, softNmsSigma);
39+
REFERENCE_TESTS_ADD_SET_PARAM(Builder, sortResultsDescending);
3840
REFERENCE_TESTS_ADD_SET_PARAM(Builder, clockwise);
3941
REFERENCE_TESTS_ADD_SET_PARAM(Builder, expectedSelectedIndices);
4042
REFERENCE_TESTS_ADD_SET_PARAM(Builder, expectedSelectedScores);
@@ -91,7 +93,7 @@ class ReferenceNMSRotatedTest : public testing::TestWithParam<NMSRotatedParams>,
9193
max_output_boxes_per_class,
9294
iou_threshold,
9395
score_threshold,
94-
false,
96+
params.sortResultsDescending,
9597
params.expectedSelectedIndices.type,
9698
params.clockwise);
9799
return std::make_shared<Model>(nms->outputs(), ParameterVector{boxes, scores});
@@ -129,7 +131,7 @@ class ReferenceNMSRotatedTestWithoutConstants : public ReferenceNMSRotatedTest {
129131
max_output_boxes_per_class,
130132
iou_threshold,
131133
score_threshold,
132-
false,
134+
params.sortResultsDescending,
133135
params.expectedSelectedIndices.type,
134136
params.clockwise);
135137
return std::make_shared<Model>(
@@ -146,6 +148,8 @@ TEST_P(ReferenceNMSRotatedTestWithoutConstants, CompareWithRefs) {
146148
Exec();
147149
}
148150

151+
// clang-format off
152+
// To make the test data shape more readable
149153
template <element::Type_t ET, element::Type_t ET_BOX, element::Type_t ET_TH, element::Type_t ET_IND>
150154
std::vector<NMSRotatedParams> generateParams() {
151155
using T = typename element_type_traits<ET>::value_type;
@@ -173,6 +177,140 @@ std::vector<NMSRotatedParams> generateParams() {
173177
std::vector<T_TH>{0.0, 0.0, 0.96, 0.0, 0.0, 0.7, 0.0, 0.0, 0.65}))
174178
.expectedValidOutputs(reference_tests::Tensor(ET_IND, {1}, std::vector<T_IND>{3}))
175179
.testcaseName("NMSRotated_new_rotation_basic"),
180+
Builder{}
181+
.boxes(reference_tests::Tensor(ET, {1, 4, 5}, std::vector<T>{/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
182+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
183+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
184+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6}))
185+
.scores(reference_tests::Tensor(ET, {1, 2, 4}, std::vector<T>{/*0*/ 0.65, 0.7, 0.55, 0.96, /*1*/ 0.65, 0.7, 0.55, 0.96}))
186+
.maxOutputBoxesPerClass(reference_tests::Tensor(ET_BOX, {}, std::vector<T_BOX>{5000}))
187+
.iouThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.5f}))
188+
.scoreThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
189+
.softNmsSigma(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
190+
.sortResultsDescending(false)
191+
.expectedSelectedIndices(reference_tests::Tensor(
192+
ET_IND,
193+
{6, 3},
194+
std::vector<T_IND>{0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 1, 3, 0, 1, 1, 0, 1, 0})) // batch, class, box_id (sorted max score first)
195+
.expectedSelectedScores(
196+
reference_tests::Tensor(ET_TH,
197+
{6, 3},
198+
std::vector<T_TH>{0.0, 0.0, 0.96, 0.0, 0.0, 0.7, 0.0, 0.0, 0.65, 0.0, 1.0, 0.96, 0.0, 1.0, 0.7, 0.0, 1.0, 0.65}))
199+
.expectedValidOutputs(reference_tests::Tensor(ET_IND, {1}, std::vector<T_IND>{6}))
200+
.testcaseName("NMSRotated_new_rotation_class_2"),
201+
Builder{}
202+
.boxes(reference_tests::Tensor(ET, {2, 4, 5}, std::vector<T>{/* First batch */
203+
/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
204+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
205+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
206+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6,
207+
/* Second batch */
208+
/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
209+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
210+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
211+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6}))
212+
.scores(reference_tests::Tensor(ET, {2, 1, 4}, std::vector<T>{0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96}))
213+
.maxOutputBoxesPerClass(reference_tests::Tensor(ET_BOX, {}, std::vector<T_BOX>{5000}))
214+
.iouThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.5f}))
215+
.scoreThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
216+
.softNmsSigma(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
217+
.sortResultsDescending(false)
218+
.expectedSelectedIndices(reference_tests::Tensor(
219+
ET_IND,
220+
{6, 3},
221+
std::vector<T_IND>{0, 0, 3, 0, 0, 1, 0, 0, 0,
222+
1, 0, 3, 1, 0, 1, 1, 0, 0})) // batch, class, box_id (sorted max score first)
223+
.expectedSelectedScores(
224+
reference_tests::Tensor(ET_TH,
225+
{6, 3},
226+
std::vector<T_TH>{0.0, 0.0, 0.96, 0.0, 0.0, 0.7, 0.0, 0.0, 0.65, 1.0, 0.0, 0.96, 1.0, 0.0, 0.7, 1.0, 0.0, 0.65}))
227+
.expectedValidOutputs(reference_tests::Tensor(ET_IND, {1}, std::vector<T_IND>{6}))
228+
.testcaseName("NMSRotated_new_rotation_batch_2"),
229+
Builder{}
230+
.boxes(reference_tests::Tensor(ET, {2, 4, 5}, std::vector<T>{/* First batch */
231+
/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
232+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
233+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
234+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6,
235+
/* Second batch */
236+
/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
237+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
238+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
239+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6}))
240+
.scores(reference_tests::Tensor(ET, {2, 2, 4}, std::vector<T>{0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96,
241+
0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96,
242+
0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96,
243+
0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96}))
244+
.maxOutputBoxesPerClass(reference_tests::Tensor(ET_BOX, {}, std::vector<T_BOX>{5000}))
245+
.iouThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.5f}))
246+
.scoreThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
247+
.softNmsSigma(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
248+
.sortResultsDescending(false)
249+
.expectedSelectedIndices(reference_tests::Tensor(
250+
ET_IND,
251+
{12, 3},
252+
std::vector<T_IND>{0, 0, 3, 0, 0, 1, 0, 0, 0,
253+
0, 1, 3, 0, 1, 1, 0, 1, 0,
254+
1, 0, 3, 1, 0, 1, 1, 0, 0,
255+
1, 1, 3, 1, 1, 1, 1, 1, 0})) // batch, class, box_id (sorted max score first)
256+
.expectedSelectedScores(
257+
reference_tests::Tensor(ET_TH,
258+
{12, 3},
259+
std::vector<T_TH>{0.0, 0.0, 0.96, 0.0, 0.0, 0.7, 0.0, 0.0, 0.65,
260+
0.0, 1.0, 0.96, 0.0, 1.0, 0.7, 0.0, 1.0, 0.65,
261+
1.0, 0.0, 0.96, 1.0, 0.0, 0.7, 1.0, 0.0, 0.65,
262+
1.0, 1.0, 0.96, 1.0, 1.0, 0.7, 1.0, 1.0, 0.65,
263+
}))
264+
265+
.expectedValidOutputs(reference_tests::Tensor(ET_IND, {1}, std::vector<T_IND>{12}))
266+
.testcaseName("NMSRotated_new_rotation_batch_2_class_2_sort_attr_false"),
267+
Builder{}
268+
.boxes(reference_tests::Tensor(ET, {2, 4, 5}, std::vector<T>{/* First batch */
269+
/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
270+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
271+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
272+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6,
273+
/* Second batch */
274+
/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
275+
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
276+
/*2*/ 4.0, 8.0, 10.0, 12.0, 0.3,
277+
/*3*/ 2.0, 5.0, 13.0, 7.0, 0.6}))
278+
.scores(reference_tests::Tensor(ET, {2, 2, 4}, std::vector<T>{0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96,
279+
0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96,
280+
0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96,
281+
0.65, 0.7, 0.55, 0.96, 0.65, 0.7, 0.55, 0.96}))
282+
.maxOutputBoxesPerClass(reference_tests::Tensor(ET_BOX, {}, std::vector<T_BOX>{5000}))
283+
.iouThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.5f}))
284+
.scoreThreshold(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
285+
.softNmsSigma(reference_tests::Tensor(ET_TH, {}, std::vector<T_TH>{0.0f}))
286+
.sortResultsDescending(true)
287+
288+
.expectedSelectedIndices(reference_tests::Tensor(
289+
ET_IND,
290+
{12, 3},
291+
std::vector<T_IND>{0, 0, 3, 0, 1, 3, 1, 0, 3, 1, 1, 3,
292+
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
293+
0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0})) // batch, class, box_id (sorted max score first)
294+
.expectedSelectedScores(
295+
reference_tests::Tensor(ET_TH,
296+
{12, 3},
297+
std::vector<T_TH>{0.0, 0.0, 0.96,
298+
0.0, 1.0, 0.96,
299+
1.0, 0.0, 0.96,
300+
1.0, 1.0, 0.96,
301+
302+
0.0, 0.0, 0.7,
303+
0.0, 1.0, 0.7,
304+
1.0, 0.0, 0.7,
305+
1.0, 1.0, 0.7,
306+
307+
0.0, 0.0, 0.65,
308+
0.0, 1.0, 0.65,
309+
1.0, 0.0, 0.65,
310+
1.0, 1.0, 0.65
311+
}))
312+
.expectedValidOutputs(reference_tests::Tensor(ET_IND, {1}, std::vector<T_IND>{12}))
313+
.testcaseName("NMSRotated_new_rotation_batch_2_class_2_sort_attr_true"),
176314
Builder{}
177315
.boxes(reference_tests::Tensor(ET, {1, 4, 5}, std::vector<T>{/*0*/ 7.0, 4.0, 8.0, 7.0, 0.5,
178316
/*1*/ 4.0, 7.0, 9.0, 11.0, 0.6,
@@ -418,6 +556,7 @@ std::vector<NMSRotatedParams> generateParams() {
418556
};
419557
return params;
420558
}
559+
// clang-format on
421560

422561
std::vector<NMSRotatedParams> generateCombinedParams() {
423562
const std::vector<std::vector<NMSRotatedParams>> generatedParams{

0 commit comments

Comments
 (0)