xref: /aosp_15_r20/external/ComputeLibrary/tests/validation/CPP/DetectionPostProcessLayer.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2019-2020 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/CPP/functions/CPPDetectionPostProcessLayer.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 D, 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<D>   quantized;
54     quantized.reserve(v.size());
55     for(auto elem : v)
56     {
57         quantized.emplace_back(Qasymm8QuantizationHelper<D>::quantize(elem, qi));
58     }
59     std::memcpy(tensor.data(), quantized.data(), sizeof(D) * quantized.size());
60 }
61 template <typename T>
calc_qinfo(const float min,const float max,float & scale)62 inline int calc_qinfo(const float min, const float max, float &scale)
63 {
64     const auto  qmin   = std::numeric_limits<T>::min();
65     const auto  qmax   = std::numeric_limits<T>::max();
66     const float f_qmin = qmin;
67     const float f_qmax = qmax;
68 
69     scale                       = (max - min) / (f_qmax - f_qmin);
70     const float offset_from_min = f_qmin - min / scale;
71     const float offset_from_max = f_qmax - max / scale;
72 
73     const float offset_from_min_error = std::abs(f_qmin) + std::abs(min / scale);
74     const float offset_from_max_error = std::abs(f_qmax) + std::abs(max / scale);
75     const float f_offset              = offset_from_min_error < offset_from_max_error ? offset_from_min : offset_from_max;
76     T           tmp_offset;
77     if(f_offset < f_qmin)
78     {
79         tmp_offset = qmin;
80     }
81     else if(f_offset > f_qmax)
82     {
83         tmp_offset = qmax;
84     }
85     else
86     {
87         tmp_offset = static_cast<T>(arm_compute::support::cpp11::round(f_offset));
88     }
89     return static_cast<int>(tmp_offset);
90 }
qinfo_scaleoffset_from_minmax(DataType data_type,const float min,const float max)91 inline QuantizationInfo qinfo_scaleoffset_from_minmax(DataType data_type, const float min, const float max)
92 {
93     int   offset = 0;
94     float scale  = 0;
95 
96     // Continue only if [min,max] is a valid range and not a point
97     if(min != max)
98     {
99         if(data_type == DataType::QASYMM8_SIGNED)
100         {
101             offset = calc_qinfo<int8_t>(min, max, scale);
102         }
103         else
104         {
105             offset = calc_qinfo<uint8_t>(min, max, scale);
106         }
107     }
108     return QuantizationInfo(scale, offset);
109 }
110 
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))111 inline void base_test_case(DetectionPostProcessLayerInfo info, DataType data_type, const SimpleTensor<float> &expected_output_boxes,
112                            const SimpleTensor<float> &expected_output_classes, const SimpleTensor<float> &expected_output_scores, const SimpleTensor<float> &expected_num_detection,
113                            AbsoluteTolerance<float> tolerance_boxes = AbsoluteTolerance<float>(0.1f), AbsoluteTolerance<float> tolerance_others = AbsoluteTolerance<float>(0.1f))
114 {
115     Tensor box_encoding     = create_tensor<Tensor>(TensorShape(4U, 6U, 1U), data_type, 1, qinfo_scaleoffset_from_minmax(data_type, -1.0f, 1.0f));
116     Tensor class_prediction = create_tensor<Tensor>(TensorShape(3U, 6U, 1U), data_type, 1, qinfo_scaleoffset_from_minmax(data_type, 0.0f, 1.0f));
117     Tensor anchors          = create_tensor<Tensor>(TensorShape(4U, 6U), data_type, 1, qinfo_scaleoffset_from_minmax(data_type, 0.0f, 100.5f));
118 
119     box_encoding.allocator()->allocate();
120     class_prediction.allocator()->allocate();
121     anchors.allocator()->allocate();
122 
123     std::vector<float> box_encoding_vector =
124     {
125         0.0f, 1.0f, 0.0f, 0.0f,
126         0.0f, -1.0f, 0.0f, 0.0f,
127         0.0f, 0.0f, 0.0f, 0.0f,
128         0.0f, 0.0f, 0.0f, 0.0f,
129         0.0f, 1.0f, 0.0f, 0.0f,
130         0.0f, 0.0f, 0.0f, 0.0f
131     };
132     std::vector<float> class_prediction_vector =
133     {
134         0.0f, 0.7f, 0.68f,
135         0.0f, 0.6f, 0.5f,
136         0.0f, 0.9f, 0.83f,
137         0.0f, 0.91f, 0.97f,
138         0.0f, 0.5f, 0.4f,
139         0.0f, 0.31f, 0.22f
140     };
141     std::vector<float> anchors_vector =
142     {
143         0.4f, 0.4f, 1.1f, 1.1f,
144         0.4f, 0.4f, 1.1f, 1.1f,
145         0.4f, 0.4f, 1.1f, 1.1f,
146         0.4f, 10.4f, 1.1f, 1.1f,
147         0.4f, 10.4f, 1.1f, 1.1f,
148         0.4f, 100.4f, 1.1f, 1.1f
149     };
150 
151     // Fill the tensors with random pre-generated values
152     switch(data_type)
153     {
154         case DataType::F32:
155         {
156             fill_tensor(Accessor(box_encoding), box_encoding_vector);
157             fill_tensor(Accessor(class_prediction), class_prediction_vector);
158             fill_tensor(Accessor(anchors), anchors_vector);
159         }
160         break;
161         case DataType::QASYMM8:
162         {
163             quantize_and_fill_tensor<uint8_t>(Accessor(box_encoding), box_encoding_vector);
164             quantize_and_fill_tensor<uint8_t>(Accessor(class_prediction), class_prediction_vector);
165             quantize_and_fill_tensor<uint8_t>(Accessor(anchors), anchors_vector);
166         }
167         break;
168         case DataType::QASYMM8_SIGNED:
169         {
170             quantize_and_fill_tensor<int8_t>(Accessor(box_encoding), box_encoding_vector);
171             quantize_and_fill_tensor<int8_t>(Accessor(class_prediction), class_prediction_vector);
172             quantize_and_fill_tensor<int8_t>(Accessor(anchors), anchors_vector);
173         }
174         break;
175         default:
176             return;
177     }
178 
179     // Determine the output through the CPP kernel
180     Tensor                       output_boxes;
181     Tensor                       output_classes;
182     Tensor                       output_scores;
183     Tensor                       num_detection;
184     CPPDetectionPostProcessLayer detection;
185     detection.configure(&box_encoding, &class_prediction, &anchors, &output_boxes, &output_classes, &output_scores, &num_detection, info);
186 
187     output_boxes.allocator()->allocate();
188     output_classes.allocator()->allocate();
189     output_scores.allocator()->allocate();
190     num_detection.allocator()->allocate();
191 
192     // Run the kernel
193     detection.run();
194 
195     // Validate against the expected output
196     // Validate output boxes
197     validate(Accessor(output_boxes), expected_output_boxes, tolerance_boxes);
198     // Validate detection classes
199     validate(Accessor(output_classes), expected_output_classes, tolerance_others);
200     // Validate detection scores
201     validate(Accessor(output_scores), expected_output_scores, tolerance_others);
202     // Validate num detections
203     validate(Accessor(num_detection), expected_num_detection, tolerance_others);
204 }
205 } // namespace
206 
207 TEST_SUITE(CPP)
TEST_SUITE(DetectionPostProcessLayer)208 TEST_SUITE(DetectionPostProcessLayer)
209 
210 // *INDENT-OFF*
211 // clang-format off
212 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(zip(zip(
213         framework::dataset::make("BoxEncodingsInfo", { TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
214                                                 TensorInfo(TensorShape(4U, 10U, 3U), 1, DataType::F32),  // Mismatching batch_size
215                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::S8), // Unsupported data type
216                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32), // Wrong Detection Info
217                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32), // Wrong boxes dimensions
218                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::QASYMM8), // Wrong score dimension
219                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::QASYMM8_SIGNED)}), // Wrong score dimension
220         framework::dataset::make("ClassPredsInfo",{ TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
221                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
222                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
223                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
224                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::F32),
225                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::QASYMM8),
226                                                 TensorInfo(TensorShape(3U ,10U), 1, DataType::QASYMM8_SIGNED)})),
227         framework::dataset::make("AnchorsInfo",{ TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
228                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
229                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
230                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
231                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::F32),
232                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::QASYMM8),
233                                                 TensorInfo(TensorShape(4U, 10U, 1U), 1, DataType::QASYMM8_SIGNED)})),
234         framework::dataset::make("OutputBoxInfo", { TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32),
235                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32),
236                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::S8),
237                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32),
238                                                 TensorInfo(TensorShape(1U, 5U, 1U), 1, DataType::F32),
239                                                 TensorInfo(TensorShape(4U, 3U, 1U), 1, DataType::F32)})),
240         framework::dataset::make("OuputClassesInfo",{ TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
241                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
242                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
243                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
244                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
245                                                 TensorInfo(TensorShape(6U, 1U), 1, DataType::F32)})),
246         framework::dataset::make("OutputScoresInfo",{ TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
247                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
248                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
249                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
250                                                 TensorInfo(TensorShape(3U, 1U), 1, DataType::F32),
251                                                 TensorInfo(TensorShape(6U, 1U), 1, DataType::F32)})),
252         framework::dataset::make("NumDetectionsInfo",{ TensorInfo(TensorShape(1U), 1, DataType::F32),
253                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
254                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
255                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
256                                                 TensorInfo(TensorShape(1U), 1, DataType::F32),
257                                                 TensorInfo(TensorShape(1U), 1, DataType::F32)})),
258         framework::dataset::make("DetectionPostProcessLayerInfo",{ DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
259                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
260                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
261                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 1.5f, 2, {0.0f,0.1f,0.1f,0.1f}),
262                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f}),
263                                                 DetectionPostProcessLayerInfo(3, 1, 0.0f, 0.5f, 2, {0.1f,0.1f,0.1f,0.1f})})),
264         framework::dataset::make("Expected", {true, false, false, false, false, false })),
265         box_encodings_info, classes_info, anchors_info, output_boxes_info, output_classes_info,output_scores_info, num_detection_info, detect_info, expected)
266 {
267     const Status status = CPPDetectionPostProcessLayer::validate(&box_encodings_info.clone()->set_is_resizable(false),
268             &classes_info.clone()->set_is_resizable(false),
269             &anchors_info.clone()->set_is_resizable(false),
270             &output_boxes_info.clone()->set_is_resizable(false),
271             &output_classes_info.clone()->set_is_resizable(false),
272             &output_scores_info.clone()->set_is_resizable(false), &num_detection_info.clone()->set_is_resizable(false), detect_info);
273     ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
274 }
275 // clang-format on
276 // *INDENT-ON*
277 
278 TEST_SUITE(F32)
TEST_CASE(Float_general,framework::DatasetMode::ALL)279 TEST_CASE(Float_general, framework::DatasetMode::ALL)
280 {
281     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
282                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/);
283     // Fill expected detection boxes
284     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
285     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 });
286     // Fill expected detection classes
287     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
288     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
289     // Fill expected detection scores
290     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
291     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
292     // Fill expected num detections
293     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
294     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
295     // Run base test
296     base_test_case(info, DataType::F32, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection);
297 }
298 
TEST_CASE(Float_fast,framework::DatasetMode::ALL)299 TEST_CASE(Float_fast, framework::DatasetMode::ALL)
300 {
301     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
302                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
303                                                                        false /*use_regular_nms*/, 1 /*detections_per_class*/);
304 
305     // Fill expected detection boxes
306     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
307     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 });
308     // Fill expected detection classes
309     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
310     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
311     // Fill expected detection scores
312     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
313     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
314     // Fill expected num detections
315     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
316     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
317 
318     // Run base test
319     base_test_case(info, DataType::F32, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection);
320 }
321 
TEST_CASE(Float_regular,framework::DatasetMode::ALL)322 TEST_CASE(Float_regular, framework::DatasetMode::ALL)
323 {
324     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
325                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
326                                                                        true /*use_regular_nms*/, 1 /*detections_per_class*/);
327 
328     // Fill expected detection boxes
329     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
330     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 });
331     // Fill expected detection classes
332     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
333     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
334     // Fill expected detection scores
335     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
336     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.91f, 0.0f });
337     // Fill expected num detections
338     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
339     fill_tensor(expected_num_detection, std::vector<float> { 2.f });
340 
341     // Run test
342     base_test_case(info, DataType::F32, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection);
343 }
344 TEST_SUITE_END() // F32
345 
TEST_SUITE(QASYMM8)346 TEST_SUITE(QASYMM8)
347 TEST_CASE(Quantized_general, framework::DatasetMode::ALL)
348 {
349     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
350                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/);
351 
352     // Fill expected detection boxes
353     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
354     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 });
355     // Fill expected detection classes
356     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
357     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
358     // Fill expected detection scores
359     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
360     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
361     // Fill expected num detections
362     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
363     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
364     // Run test
365     base_test_case(info, DataType::QASYMM8, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
366 }
367 
TEST_CASE(Quantized_fast,framework::DatasetMode::ALL)368 TEST_CASE(Quantized_fast, framework::DatasetMode::ALL)
369 {
370     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
371                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
372                                                                        false /*use_regular_nms*/, 1 /*detections_per_class*/);
373 
374     // Fill expected detection boxes
375     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
376     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 });
377     // Fill expected detection classes
378     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
379     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
380     // Fill expected detection scores
381     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
382     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
383     // Fill expected num detections
384     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
385     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
386 
387     // Run base test
388     base_test_case(info, DataType::QASYMM8, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
389 }
390 
TEST_CASE(Quantized_regular,framework::DatasetMode::ALL)391 TEST_CASE(Quantized_regular, framework::DatasetMode::ALL)
392 {
393     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
394                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
395                                                                        true /*use_regular_nms*/, 1 /*detections_per_class*/);
396     // Fill expected detection boxes
397     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
398     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 });
399     // Fill expected detection classes
400     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
401     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
402     // Fill expected detection scores
403     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
404     fill_tensor(expected_output_scores, std::vector<float> { 0.95f, 0.91f, 0.0f });
405     // Fill expected num detections
406     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
407     fill_tensor(expected_num_detection, std::vector<float> { 2.f });
408 
409     // Run test
410     base_test_case(info, DataType::QASYMM8, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
411 }
412 
413 TEST_SUITE_END() // QASYMM8
414 
TEST_SUITE(QASYMM8_SIGNED)415 TEST_SUITE(QASYMM8_SIGNED)
416 TEST_CASE(Quantized_general, framework::DatasetMode::ALL)
417 {
418     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
419                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/);
420 
421     // Fill expected detection boxes
422     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
423     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 });
424     // Fill expected detection classes
425     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
426     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
427     // Fill expected detection scores
428     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
429     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
430     // Fill expected num detections
431     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
432     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
433     // Run test
434     base_test_case(info, DataType::QASYMM8_SIGNED, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
435 }
436 
TEST_CASE(Quantized_fast,framework::DatasetMode::ALL)437 TEST_CASE(Quantized_fast, framework::DatasetMode::ALL)
438 {
439     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
440                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
441                                                                        false /*use_regular_nms*/, 1 /*detections_per_class*/);
442 
443     // Fill expected detection boxes
444     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
445     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 });
446     // Fill expected detection classes
447     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
448     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
449     // Fill expected detection scores
450     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
451     fill_tensor(expected_output_scores, std::vector<float> { 0.97f, 0.95f, 0.31f });
452     // Fill expected num detections
453     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
454     fill_tensor(expected_num_detection, std::vector<float> { 3.f });
455 
456     // Run base test
457     base_test_case(info, DataType::QASYMM8_SIGNED, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
458 }
459 
TEST_CASE(Quantized_regular,framework::DatasetMode::ALL)460 TEST_CASE(Quantized_regular, framework::DatasetMode::ALL)
461 {
462     DetectionPostProcessLayerInfo info = DetectionPostProcessLayerInfo(3 /*max_detections*/, 1 /*max_classes_per_detection*/, 0.0 /*nms_score_threshold*/,
463                                                                        0.5 /*nms_iou_threshold*/, 2 /*num_classes*/, { 11.0, 11.0, 6.0, 6.0 } /*scale*/,
464                                                                        true /*use_regular_nms*/, 1 /*detections_per_class*/);
465     // Fill expected detection boxes
466     SimpleTensor<float> expected_output_boxes(TensorShape(4U, 3U), DataType::F32);
467     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 });
468     // Fill expected detection classes
469     SimpleTensor<float> expected_output_classes(TensorShape(3U), DataType::F32);
470     fill_tensor(expected_output_classes, std::vector<float> { 1.0f, 0.0f, 0.0f });
471     // Fill expected detection scores
472     SimpleTensor<float> expected_output_scores(TensorShape(3U), DataType::F32);
473     fill_tensor(expected_output_scores, std::vector<float> { 0.95f, 0.91f, 0.0f });
474     // Fill expected num detections
475     SimpleTensor<float> expected_num_detection(TensorShape(1U), DataType::F32);
476     fill_tensor(expected_num_detection, std::vector<float> { 2.f });
477 
478     // Run test
479     base_test_case(info, DataType::QASYMM8_SIGNED, expected_output_boxes, expected_output_classes, expected_output_scores, expected_num_detection, AbsoluteTolerance<float>(0.3f));
480 }
481 
482 TEST_SUITE_END() // QASYMM8_SIGNED
483 
484 TEST_SUITE_END() // DetectionPostProcessLayer
485 TEST_SUITE_END() // CPP
486 } // namespace validation
487 } // namespace test
488 } // namespace arm_compute
489