xref: /aosp_15_r20/external/ComputeLibrary/tests/validation/NEON/DetectionPostProcessLayer.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2019-2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "arm_compute/core/Types.h"
25 #include "arm_compute/runtime/NEON/functions/NEDetectionPostProcessLayer.h"
26 #include "arm_compute/runtime/Tensor.h"
27 #include "arm_compute/runtime/TensorAllocator.h"
28 #include "tests/NEON/Accessor.h"
29 #include "tests/PaddingCalculator.h"
30 #include "tests/datasets/ShapeDatasets.h"
31 #include "tests/framework/Asserts.h"
32 #include "tests/framework/Macros.h"
33 #include "tests/framework/datasets/Datasets.h"
34 #include "tests/validation/Validation.h"
35 
36 namespace arm_compute
37 {
38 namespace test
39 {
40 namespace validation
41 {
42 namespace
43 {
44 template <typename U, typename T>
fill_tensor(U && tensor,const std::vector<T> & v)45 inline void fill_tensor(U &&tensor, const std::vector<T> &v)
46 {
47     std::memcpy(tensor.data(), v.data(), sizeof(T) * v.size());
48 }
49 template <typename U, typename T>
quantize_and_fill_tensor(U && tensor,const std::vector<T> & v)50 inline void quantize_and_fill_tensor(U &&tensor, const std::vector<T> &v)
51 {
52     QuantizationInfo     qi = tensor.quantization_info();
53     std::vector<uint8_t> quantized;
54     quantized.reserve(v.size());
55     for(auto elem : v)
56     {
57         quantized.emplace_back(quantize_qasymm8(elem, qi));
58     }
59     std::memcpy(tensor.data(), quantized.data(), sizeof(uint8_t) * quantized.size());
60 }
qinfo_scaleoffset_from_minmax(const float min,const float max)61 inline QuantizationInfo qinfo_scaleoffset_from_minmax(const float min, const float max)
62 {
63     int           offset = 0;
64     float         scale  = 0;
65     const uint8_t qmin   = std::numeric_limits<uint8_t>::min();
66     const uint8_t qmax   = std::numeric_limits<uint8_t>::max();
67     const float   f_qmin = qmin;
68     const float   f_qmax = qmax;
69 
70     // Continue only if [min,max] is a valid range and not a point
71     if(min != max)
72     {
73         scale                       = (max - min) / (f_qmax - f_qmin);
74         const float offset_from_min = f_qmin - min / scale;
75         const float offset_from_max = f_qmax - max / scale;
76 
77         const float offset_from_min_error = std::abs(f_qmin) + std::abs(min / scale);
78         const float offset_from_max_error = std::abs(f_qmax) + std::abs(max / scale);
79         const float f_offset              = offset_from_min_error < offset_from_max_error ? offset_from_min : offset_from_max;
80 
81         uint8_t uint8_offset = 0;
82         if(f_offset < f_qmin)
83         {
84             uint8_offset = qmin;
85         }
86         else if(f_offset > f_qmax)
87         {
88             uint8_offset = qmax;
89         }
90         else
91         {
92             uint8_offset = static_cast<uint8_t>(support::cpp11::round(f_offset));
93         }
94         offset = uint8_offset;
95     }
96     return QuantizationInfo(scale, offset);
97 }
98 
base_test_case(DetectionPostProcessLayerInfo info,DataType data_type,const SimpleTensor<float> & expected_output_boxes,const SimpleTensor<float> & expected_output_classes,const SimpleTensor<float> & expected_output_scores,const SimpleTensor<float> & expected_num_detection,AbsoluteTolerance<float> tolerance_boxes=AbsoluteTolerance<float> (0.1f),AbsoluteTolerance<float> tolerance_others=AbsoluteTolerance<float> (0.1f))99 inline void base_test_case(DetectionPostProcessLayerInfo info, DataType data_type, const SimpleTensor<float> &expected_output_boxes,
100                            const SimpleTensor<float> &expected_output_classes, const SimpleTensor<float> &expected_output_scores, const SimpleTensor<float> &expected_num_detection,
101                            AbsoluteTolerance<float> tolerance_boxes = AbsoluteTolerance<float>(0.1f), AbsoluteTolerance<float> tolerance_others = AbsoluteTolerance<float>(0.1f))
102 {
103     Tensor box_encoding     = create_tensor<Tensor>(TensorShape(4U, 6U, 1U), data_type, 1, qinfo_scaleoffset_from_minmax(-1.0f, 1.0f));
104     Tensor class_prediction = create_tensor<Tensor>(TensorShape(3U, 6U, 1U), data_type, 1, qinfo_scaleoffset_from_minmax(0.0f, 1.0f));
105     Tensor anchors          = create_tensor<Tensor>(TensorShape(4U, 6U), data_type, 1, qinfo_scaleoffset_from_minmax(0.0f, 100.5f));
106 
107     box_encoding.allocator()->allocate();
108     class_prediction.allocator()->allocate();
109     anchors.allocator()->allocate();
110 
111     std::vector<float> box_encoding_vector =
112     {
113         0.0f, 1.0f, 0.0f, 0.0f,
114         0.0f, -1.0f, 0.0f, 0.0f,
115         0.0f, 0.0f, 0.0f, 0.0f,
116         0.0f, 0.0f, 0.0f, 0.0f,
117         0.0f, 1.0f, 0.0f, 0.0f,
118         0.0f, 0.0f, 0.0f, 0.0f
119     };
120     std::vector<float> class_prediction_vector =
121     {
122         0.0f, 0.7f, 0.68f,
123         0.0f, 0.6f, 0.5f,
124         0.0f, 0.9f, 0.83f,
125         0.0f, 0.91f, 0.97f,
126         0.0f, 0.5f, 0.4f,
127         0.0f, 0.31f, 0.22f
128     };
129     std::vector<float> anchors_vector =
130     {
131         0.4f, 0.4f, 1.1f, 1.1f,
132         0.4f, 0.4f, 1.1f, 1.1f,
133         0.4f, 0.4f, 1.1f, 1.1f,
134         0.4f, 10.4f, 1.1f, 1.1f,
135         0.4f, 10.4f, 1.1f, 1.1f,
136         0.4f, 100.4f, 1.1f, 1.1f
137     };
138 
139     // Fill the tensors with random pre-generated values
140     if(data_type == DataType::F32)
141     {
142         fill_tensor(Accessor(box_encoding), box_encoding_vector);
143         fill_tensor(Accessor(class_prediction), class_prediction_vector);
144         fill_tensor(Accessor(anchors), anchors_vector);
145     }
146     else
147     {
148         quantize_and_fill_tensor(Accessor(box_encoding), box_encoding_vector);
149         quantize_and_fill_tensor(Accessor(class_prediction), class_prediction_vector);
150         quantize_and_fill_tensor(Accessor(anchors), anchors_vector);
151     }
152 
153     // Determine the output through the Compute Library operator
154     Tensor                      output_boxes;
155     Tensor                      output_classes;
156     Tensor                      output_scores;
157     Tensor                      num_detection;
158     NEDetectionPostProcessLayer detection;
159     detection.configure(&box_encoding, &class_prediction, &anchors, &output_boxes, &output_classes, &output_scores, &num_detection, info);
160 
161     output_boxes.allocator()->allocate();
162     output_classes.allocator()->allocate();
163     output_scores.allocator()->allocate();
164     num_detection.allocator()->allocate();
165 
166     // Run the kernel
167     detection.run();
168 
169     // Validate against the expected output
170     // Validate output boxes
171     validate(Accessor(output_boxes), expected_output_boxes, tolerance_boxes);
172     // Validate detection classes
173     validate(Accessor(output_classes), expected_output_classes, tolerance_others);
174     // Validate detection scores
175     validate(Accessor(output_scores), expected_output_scores, tolerance_others);
176     // Validate num detections
177     validate(Accessor(num_detection), expected_num_detection, tolerance_others);
178 }
179 } // namespace
180 
181 TEST_SUITE(NEON)
TEST_SUITE(DetectionPostProcessLayer)182 TEST_SUITE(DetectionPostProcessLayer)
183 
184 // *INDENT-OFF*
185 // clang-format off
186 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(zip(zip(
187         framework::dataset::make("BoxEncodingsInfo", { TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
188                                                 TensorInfo(TensorShape(4U, 10U, 3U), 1, DataType::F32),  // Mismatching batch_size
189                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::S8), // Unsupported data type
190                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32), // Wrong Detection Info
191                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32), // Wrong boxes dimensions
192                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::QASYMM8)}), // Wrong score dimension
193         framework::dataset::make("ClassPredsInfo",{ TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
194                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
195                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
196                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
197                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
198                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::QASYMM8)})),
199         framework::dataset::make("AnchorsInfo",{ TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
200                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
201                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
202                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
203                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
204                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::QASYMM8)})),
205         framework::dataset::make("OutputBoxInfo", { TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32),
206                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32),
207                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::S8),
208                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32),
209                                                 TensorInfo(TensorShape(1U, 5U, 1U), 1, DataType::F32),
210                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32)})),
211         framework::dataset::make("OuputClassesInfo",{ TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
212                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
213                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
214                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
215                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
216                                                 TensorInfo(TensorShape(6U, 1U), 1, DataType::F32)})),
217         framework::dataset::make("OutputScoresInfo",{ TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
218                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
219                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
220                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
221                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
222                                                 TensorInfo(TensorShape(6U, 1U), 1, DataType::F32)})),
223         framework::dataset::make("NumDetectionsInfo",{ TensorInfo(TensorShape(1U), 1, DataType::F32),
224                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
225                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
226                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
227                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
228                                                 TensorInfo(TensorShape(1U), 1, DataType::F32)})),
229         framework::dataset::make("DetectionPostProcessLayerInfo",{ DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
230                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
231                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
232                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 1.5f, 2, {0.0f,0.1f,0.1f,0.1f}),
233                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
234                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f})})),
235         framework::dataset::make("Expected", {true, false, false, false, false, false })),
236         box_encodings_info, classes_info, anchors_info, output_boxes_info, output_classes_info,output_scores_info, num_detection_info, detect_info, expected)
237 {
238     const Status status = NEDetectionPostProcessLayer::validate(&box_encodings_info.clone()->set_is_resizable(false),
239             &classes_info.clone()->set_is_resizable(false),
240             &anchors_info.clone()->set_is_resizable(false),
241             &output_boxes_info.clone()->set_is_resizable(false),
242             &output_classes_info.clone()->set_is_resizable(false),
243             &output_scores_info.clone()->set_is_resizable(false), &num_detection_info.clone()->set_is_resizable(false), detect_info);
244     ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
245 }
246 // clang-format on
247 // *INDENT-ON*
248 
249 TEST_SUITE(F32)
TEST_CASE(Float_general,framework::DatasetMode::ALL)250 TEST_CASE(Float_general, framework::DatasetMode::ALL)
251 {
252     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
253                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/);
254     // Fill expected detection boxes
255     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
256     fill_tensor(expected_output_boxes, std::vector<float> { -0.15, 9.85, 0.95, 10.95, -0.15, -0.15, 0.95, 0.95, -0.15, 99.85, 0.95, 100.95 });
257     // Fill expected detection classes
258     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
259     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
260     // Fill expected detection scores
261     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
262     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
263     // Fill expected num detections
264     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
265     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
266     // Run base test
267     base_test_case(info, DataType::F32, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection);
268 }
269 
TEST_CASE(Float_fast,framework::DatasetMode::ALL)270 TEST_CASE(Float_fast, framework::DatasetMode::ALL)
271 {
272     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
273                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
274                                                                        false /*use_regular_nms*/, 1 /*detections_per_class*/);
275 
276     // Fill expected detection boxes
277     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
278     fill_tensor(expected_output_boxes, std::vector<float> { -0.15, 9.85, 0.95, 10.95, -0.15, -0.15, 0.95, 0.95, -0.15, 99.85, 0.95, 100.95 });
279     // Fill expected detection classes
280     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
281     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
282     // Fill expected detection scores
283     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
284     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
285     // Fill expected num detections
286     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
287     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
288 
289     // Run base test
290     base_test_case(info, DataType::F32, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection);
291 }
292 
TEST_CASE(Float_regular,framework::DatasetMode::ALL)293 TEST_CASE(Float_regular, framework::DatasetMode::ALL)
294 {
295     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
296                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
297                                                                        true /*use_regular_nms*/, 1 /*detections_per_class*/);
298 
299     // Fill expected detection boxes
300     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
301     fill_tensor(expected_output_boxes, std::vector<float> { -0.15, 9.85, 0.95, 10.95, -0.15, 9.85, 0.95, 10.95, 0.0f, 0.0f, 0.0f, 0.0f });
302     // Fill expected detection classes
303     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
304     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
305     // Fill expected detection scores
306     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
307     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.91f, 0.0f });
308     // Fill expected num detections
309     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
310     fill_tensor(expected_num_detection, std::vector<float> { 2.f });
311 
312     // Run test
313     base_test_case(info, DataType::F32, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection);
314 }
315 TEST_SUITE_END() // F32
316 
TEST_SUITE(QASYMM8)317 TEST_SUITE(QASYMM8)
318 TEST_CASE(Quantized_general, framework::DatasetMode::ALL)
319 {
320     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
321                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/);
322 
323     // Fill expected detection boxes
324     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
325     fill_tensor(expected_output_boxes, std::vector<float> { -0.15, 9.85, 0.95, 10.95, -0.15, -0.15, 0.95, 0.95, -0.15, 99.85, 0.95, 100.95 });
326     // Fill expected detection classes
327     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
328     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
329     // Fill expected detection scores
330     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
331     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
332     // Fill expected num detections
333     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
334     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
335     // Run test
336     base_test_case(info, DataType::QASYMM8, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
337 }
338 
TEST_CASE(Quantized_fast,framework::DatasetMode::ALL)339 TEST_CASE(Quantized_fast, framework::DatasetMode::ALL)
340 {
341     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
342                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
343                                                                        false /*use_regular_nms*/, 1 /*detections_per_class*/);
344 
345     // Fill expected detection boxes
346     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
347     fill_tensor(expected_output_boxes, std::vector<float> { -0.15, 9.85, 0.95, 10.95, -0.15, -0.15, 0.95, 0.95, -0.15, 99.85, 0.95, 100.95 });
348     // Fill expected detection classes
349     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
350     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
351     // Fill expected detection scores
352     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
353     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
354     // Fill expected num detections
355     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
356     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
357 
358     // Run base test
359     base_test_case(info, DataType::QASYMM8, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
360 }
361 
TEST_CASE(Quantized_regular,framework::DatasetMode::ALL)362 TEST_CASE(Quantized_regular, framework::DatasetMode::ALL)
363 {
364     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
365                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
366                                                                        true /*use_regular_nms*/, 1 /*detections_per_class*/);
367     // Fill expected detection boxes
368     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
369     fill_tensor(expected_output_boxes, std::vector<float> { -0.15, 9.85, 0.95, 10.95, -0.15, 9.85, 0.95, 10.95, 0.0f, 0.0f, 0.0f, 0.0f });
370     // Fill expected detection classes
371     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
372     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
373     // Fill expected detection scores
374     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
375     fill_tensor(expected_output_scores, std::vector<float> { 0.95f, 0.91f, 0.0f });
376     // Fill expected num detections
377     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
378     fill_tensor(expected_num_detection, std::vector<float> { 2.f });
379 
380     // Run test
381     base_test_case(info, DataType::QASYMM8, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
382 }
383 
384 TEST_SUITE_END() // QASYMM8
385 
386 TEST_SUITE_END() // DetectionPostProcessLayer
387 TEST_SUITE_END() // Neon
388 } // namespace validation
389 } // namespace test
390 } // namespace arm_compute
391