1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "flatbuffers/flexbuffers.h"
17 #include "tensorflow/lite/c/builtin_op_data.h"
18 #include "tensorflow/lite/c/common.h"
19 #include "tensorflow/lite/micro/kernels/kernel_runner.h"
20 #include "tensorflow/lite/micro/test_helpers.h"
21 #include "tensorflow/lite/micro/testing/micro_test.h"
22 
23 // See: tensorflow/lite/micro/kernels/detection_postprocess_test/README.md
24 #include "tensorflow/lite/micro/kernels/flexbuffers_generated_data.h"
25 
26 namespace tflite {
27 namespace testing {
28 namespace {
29 
30 // Common inputs and outputs.
31 
32 static constexpr int kInputShape1[] = {3, 1, 6, 4};
33 static constexpr int kInputShape2[] = {3, 1, 6, 3};
34 static constexpr int kInputShape3[] = {2, 6, 4};
35 static constexpr int kOutputShape1[] = {3, 1, 3, 4};
36 static constexpr int kOutputShape2[] = {2, 1, 3};
37 static constexpr int kOutputShape3[] = {2, 1, 3};
38 static constexpr int kOutputShape4[] = {1, 1};
39 
40 // six boxes in center-size encoding
41 static constexpr float kInputData1[] = {
42     0.0, 0.0,  0.0, 0.0,  // box #1
43     0.0, 1.0,  0.0, 0.0,  // box #2
44     0.0, -1.0, 0.0, 0.0,  // box #3
45     0.0, 0.0,  0.0, 0.0,  // box #4
46     0.0, 1.0,  0.0, 0.0,  // box #5
47     0.0, 0.0,  0.0, 0.0   // box #6
48 };
49 
50 // class scores - two classes with background
51 static constexpr float kInputData2[] = {0., .9,  .8,  0., .75, .72, 0., .6, .5,
52                                         0., .93, .95, 0., .5,  .4,  0., .3, .2};
53 
54 // six anchors in center-size encoding
55 static constexpr float kInputData3[] = {
56     0.5, 0.5,   1.0, 1.0,  // anchor #1
57     0.5, 0.5,   1.0, 1.0,  // anchor #2
58     0.5, 0.5,   1.0, 1.0,  // anchor #3
59     0.5, 10.5,  1.0, 1.0,  // anchor #4
60     0.5, 10.5,  1.0, 1.0,  // anchor #5
61     0.5, 100.5, 1.0, 1.0   // anchor #6
62 };
63 // Same boxes in box-corner encoding:
64 // { 0.0, 0.0, 1.0, 1.0,
65 //   0.0, 0.1, 1.0, 1.1,
66 //   0.0, -0.1, 1.0, 0.9,
67 //   0.0, 10.0, 1.0, 11.0,
68 //   0.0, 10.1, 1.0, 11.1,
69 //   0.0, 100.0, 1.0, 101.0}
70 
71 static constexpr float kGolden1[] = {0.0, 10.0, 1.0, 11.0,  0.0, 0.0,
72                                      1.0, 1.0,  0.0, 100.0, 1.0, 101.0};
73 static constexpr float kGolden2[] = {1, 0, 0};
74 static constexpr float kGolden3[] = {0.95, 0.9, 0.3};
75 static constexpr float kGolden4[] = {3.0};
76 
TestDetectionPostprocess(const int * input_dims_data1,const float * input_data1,const int * input_dims_data2,const float * input_data2,const int * input_dims_data3,const float * input_data3,const int * output_dims_data1,float * output_data1,const int * output_dims_data2,float * output_data2,const int * output_dims_data3,float * output_data3,const int * output_dims_data4,float * output_data4,const float * golden1,const float * golden2,const float * golden3,const float * golden4,const float tolerance,bool use_regular_nms,uint8_t * input_data_quantized1=nullptr,uint8_t * input_data_quantized2=nullptr,uint8_t * input_data_quantized3=nullptr,const float input_min1=0,const float input_max1=0,const float input_min2=0,const float input_max2=0,const float input_min3=0,const float input_max3=0)77 void TestDetectionPostprocess(
78     const int* input_dims_data1, const float* input_data1,
79     const int* input_dims_data2, const float* input_data2,
80     const int* input_dims_data3, const float* input_data3,
81     const int* output_dims_data1, float* output_data1,
82     const int* output_dims_data2, float* output_data2,
83     const int* output_dims_data3, float* output_data3,
84     const int* output_dims_data4, float* output_data4, const float* golden1,
85     const float* golden2, const float* golden3, const float* golden4,
86     const float tolerance, bool use_regular_nms,
87     uint8_t* input_data_quantized1 = nullptr,
88     uint8_t* input_data_quantized2 = nullptr,
89     uint8_t* input_data_quantized3 = nullptr, const float input_min1 = 0,
90     const float input_max1 = 0, const float input_min2 = 0,
91     const float input_max2 = 0, const float input_min3 = 0,
92     const float input_max3 = 0) {
93   TfLiteIntArray* input_dims1 = IntArrayFromInts(input_dims_data1);
94   TfLiteIntArray* input_dims2 = IntArrayFromInts(input_dims_data2);
95   TfLiteIntArray* input_dims3 = IntArrayFromInts(input_dims_data3);
96   TfLiteIntArray* output_dims1 = nullptr;
97   TfLiteIntArray* output_dims2 = nullptr;
98   TfLiteIntArray* output_dims3 = nullptr;
99   TfLiteIntArray* output_dims4 = nullptr;
100 
101   const int zero_length_int_array_data[] = {0};
102   TfLiteIntArray* zero_length_int_array =
103       IntArrayFromInts(zero_length_int_array_data);
104 
105   output_dims1 = output_dims_data1 == nullptr
106                      ? const_cast<TfLiteIntArray*>(zero_length_int_array)
107                      : IntArrayFromInts(output_dims_data1);
108   output_dims2 = output_dims_data2 == nullptr
109                      ? const_cast<TfLiteIntArray*>(zero_length_int_array)
110                      : IntArrayFromInts(output_dims_data2);
111   output_dims3 = output_dims_data3 == nullptr
112                      ? const_cast<TfLiteIntArray*>(zero_length_int_array)
113                      : IntArrayFromInts(output_dims_data3);
114   output_dims4 = output_dims_data4 == nullptr
115                      ? const_cast<TfLiteIntArray*>(zero_length_int_array)
116                      : IntArrayFromInts(output_dims_data4);
117 
118   constexpr int inputs_size = 3;
119   constexpr int outputs_size = 4;
120   constexpr int tensors_size = inputs_size + outputs_size;
121 
122   TfLiteTensor tensors[tensors_size];
123   if (input_min1 != 0 || input_max1 != 0 || input_min2 != 0 ||
124       input_max2 != 0 || input_min3 != 0 || input_max3 != 0) {
125     const float input_scale1 = ScaleFromMinMax<uint8_t>(input_min1, input_max1);
126     const int input_zero_point1 =
127         ZeroPointFromMinMax<uint8_t>(input_min1, input_max1);
128     const float input_scale2 = ScaleFromMinMax<uint8_t>(input_min2, input_max2);
129     const int input_zero_point2 =
130         ZeroPointFromMinMax<uint8_t>(input_min2, input_max2);
131     const float input_scale3 = ScaleFromMinMax<uint8_t>(input_min3, input_max3);
132     const int input_zero_point3 =
133         ZeroPointFromMinMax<uint8_t>(input_min3, input_max3);
134 
135     tensors[0] =
136         CreateQuantizedTensor(input_data1, input_data_quantized1, input_dims1,
137                               input_scale1, input_zero_point1);
138     tensors[1] =
139         CreateQuantizedTensor(input_data2, input_data_quantized2, input_dims2,
140                               input_scale2, input_zero_point2);
141     tensors[2] =
142         CreateQuantizedTensor(input_data3, input_data_quantized3, input_dims3,
143                               input_scale3, input_zero_point3);
144   } else {
145     tensors[0] = CreateTensor(input_data1, input_dims1);
146     tensors[1] = CreateTensor(input_data2, input_dims2);
147     tensors[2] = CreateTensor(input_data3, input_dims3);
148   }
149   tensors[3] = CreateTensor(output_data1, output_dims1);
150   tensors[4] = CreateTensor(output_data2, output_dims2);
151   tensors[5] = CreateTensor(output_data3, output_dims3);
152   tensors[6] = CreateTensor(output_data4, output_dims4);
153 
154   ::tflite::AllOpsResolver resolver;
155   const TfLiteRegistration* registration =
156       resolver.FindOp("TFLite_Detection_PostProcess");
157   TF_LITE_MICRO_EXPECT_NE(nullptr, registration);
158 
159   int inputs_array_data[] = {3, 0, 1, 2};
160   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
161   int outputs_array_data[] = {4, 3, 4, 5, 6};
162   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
163 
164   micro::KernelRunner runner(*registration, tensors, tensors_size, inputs_array,
165                              outputs_array, nullptr);
166 
167   // Using generated data as input to operator.
168   int data_size = 0;
169   const unsigned char* init_data = nullptr;
170   if (use_regular_nms) {
171     init_data = g_gen_data_regular_nms;
172     data_size = g_gen_data_size_regular_nms;
173   } else {
174     init_data = g_gen_data_none_regular_nms;
175     data_size = g_gen_data_size_none_regular_nms;
176   }
177 
178   // TfLite uses a char* for the raw bytes whereas flexbuffers use an unsigned
179   // char*. This small discrepancy results in compiler warnings unless we
180   // reinterpret_cast right before passing in the flexbuffer bytes to the
181   // KernelRunner.
182   TF_LITE_MICRO_EXPECT_EQ(
183       kTfLiteOk, runner.InitAndPrepare(reinterpret_cast<const char*>(init_data),
184                                        data_size));
185 
186   // Output dimensions should not be undefined after Prepare
187   TF_LITE_MICRO_EXPECT_NE(nullptr, tensors[3].dims);
188   TF_LITE_MICRO_EXPECT_NE(nullptr, tensors[4].dims);
189   TF_LITE_MICRO_EXPECT_NE(nullptr, tensors[5].dims);
190   TF_LITE_MICRO_EXPECT_NE(nullptr, tensors[6].dims);
191 
192   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
193 
194   const int output_elements_count1 = tensors[3].dims->size;
195   const int output_elements_count2 = tensors[4].dims->size;
196   const int output_elements_count3 = tensors[5].dims->size;
197   const int output_elements_count4 = tensors[6].dims->size;
198 
199   for (int i = 0; i < output_elements_count1; ++i) {
200     TF_LITE_MICRO_EXPECT_NEAR(golden1[i], output_data1[i], tolerance);
201   }
202   for (int i = 0; i < output_elements_count2; ++i) {
203     TF_LITE_MICRO_EXPECT_NEAR(golden2[i], output_data2[i], tolerance);
204   }
205   for (int i = 0; i < output_elements_count3; ++i) {
206     TF_LITE_MICRO_EXPECT_NEAR(golden3[i], output_data3[i], tolerance);
207   }
208   for (int i = 0; i < output_elements_count4; ++i) {
209     TF_LITE_MICRO_EXPECT_NEAR(golden4[i], output_data4[i], tolerance);
210   }
211 }
212 }  // namespace
213 }  // namespace testing
214 }  // namespace tflite
215 
216 TF_LITE_MICRO_TESTS_BEGIN
217 
TF_LITE_MICRO_TEST(DetectionPostprocessFloatFastNMS)218 TF_LITE_MICRO_TEST(DetectionPostprocessFloatFastNMS) {
219   float output_data1[12];
220   float output_data2[3];
221   float output_data3[3];
222   float output_data4[1];
223 
224   tflite::testing::TestDetectionPostprocess(
225       tflite::testing::kInputShape1, tflite::testing::kInputData1,
226       tflite::testing::kInputShape2, tflite::testing::kInputData2,
227       tflite::testing::kInputShape3, tflite::testing::kInputData3,
228       tflite::testing::kOutputShape1, output_data1,
229       tflite::testing::kOutputShape2, output_data2,
230       tflite::testing::kOutputShape3, output_data3,
231       tflite::testing::kOutputShape4, output_data4, tflite::testing::kGolden1,
232       tflite::testing::kGolden2, tflite::testing::kGolden3,
233       tflite::testing::kGolden4,
234       /* tolerance */ 0, /* Use regular NMS: */ false);
235 }
236 
TF_LITE_MICRO_TEST(DetectionPostprocessQuantizedFastNMS)237 TF_LITE_MICRO_TEST(DetectionPostprocessQuantizedFastNMS) {
238   float output_data1[12];
239   float output_data2[3];
240   float output_data3[3];
241   float output_data4[1];
242   const int kInputElements1 = tflite::testing::kInputShape1[1] *
243                               tflite::testing::kInputShape1[2] *
244                               tflite::testing::kInputShape1[3];
245   const int kInputElements2 = tflite::testing::kInputShape2[1] *
246                               tflite::testing::kInputShape2[2] *
247                               tflite::testing::kInputShape2[3];
248   const int kInputElements3 =
249       tflite::testing::kInputShape3[1] * tflite::testing::kInputShape3[2];
250 
251   uint8_t input_data_quantized1[kInputElements1 + 10];
252   uint8_t input_data_quantized2[kInputElements2 + 10];
253   uint8_t input_data_quantized3[kInputElements3 + 10];
254 
255   tflite::testing::TestDetectionPostprocess(
256       tflite::testing::kInputShape1, tflite::testing::kInputData1,
257       tflite::testing::kInputShape2, tflite::testing::kInputData2,
258       tflite::testing::kInputShape3, tflite::testing::kInputData3,
259       tflite::testing::kOutputShape1, output_data1,
260       tflite::testing::kOutputShape2, output_data2,
261       tflite::testing::kOutputShape3, output_data3,
262       tflite::testing::kOutputShape4, output_data4, tflite::testing::kGolden1,
263       tflite::testing::kGolden2, tflite::testing::kGolden3,
264       tflite::testing::kGolden4,
265       /* tolerance */ 3e-1, /* Use regular NMS: */ false, input_data_quantized1,
266       input_data_quantized2, input_data_quantized3,
267       /* input1 min/max*/ -1.0, 1.0, /* input2 min/max */ 0.0, 1.0,
268       /* input3 min/max */ 0.0, 100.5);
269 }
270 
TF_LITE_MICRO_TEST(DetectionPostprocessFloatRegularNMS)271 TF_LITE_MICRO_TEST(DetectionPostprocessFloatRegularNMS) {
272   float output_data1[12];
273   float output_data2[3];
274   float output_data3[3];
275   float output_data4[1];
276   const float kGolden1[] = {0.0, 10.0, 1.0, 11.0, 0.0, 10.0,
277                             1.0, 11.0, 0.0, 0.0,  0.0, 0.0};
278   const float kGolden3[] = {0.95, 0.9, 0.0};
279   const float kGolden4[] = {2.0};
280 
281   tflite::testing::TestDetectionPostprocess(
282       tflite::testing::kInputShape1, tflite::testing::kInputData1,
283       tflite::testing::kInputShape2, tflite::testing::kInputData2,
284       tflite::testing::kInputShape3, tflite::testing::kInputData3,
285       tflite::testing::kOutputShape1, output_data1,
286       tflite::testing::kOutputShape2, output_data2,
287       tflite::testing::kOutputShape3, output_data3,
288       tflite::testing::kOutputShape4, output_data4, kGolden1,
289       tflite::testing::kGolden2, kGolden3, kGolden4,
290       /* tolerance */ 1e-1, /* Use regular NMS: */ true);
291 }
292 
TF_LITE_MICRO_TEST(DetectionPostprocessQuantizedRegularNMS)293 TF_LITE_MICRO_TEST(DetectionPostprocessQuantizedRegularNMS) {
294   float output_data1[12];
295   float output_data2[3];
296   float output_data3[3];
297   float output_data4[1];
298   const int kInputElements1 = tflite::testing::kInputShape1[1] *
299                               tflite::testing::kInputShape1[2] *
300                               tflite::testing::kInputShape1[3];
301   const int kInputElements2 = tflite::testing::kInputShape2[1] *
302                               tflite::testing::kInputShape2[2] *
303                               tflite::testing::kInputShape2[3];
304   const int kInputElements3 =
305       tflite::testing::kInputShape3[1] * tflite::testing::kInputShape3[2];
306 
307   uint8_t input_data_quantized1[kInputElements1 + 10];
308   uint8_t input_data_quantized2[kInputElements2 + 10];
309   uint8_t input_data_quantized3[kInputElements3 + 10];
310 
311   const float kGolden1[] = {0.0, 10.0, 1.0, 11.0, 0.0, 10.0,
312                             1.0, 11.0, 0.0, 0.0,  0.0, 0.0};
313   const float kGolden3[] = {0.95, 0.9, 0.0};
314   const float kGolden4[] = {2.0};
315 
316   tflite::testing::TestDetectionPostprocess(
317       tflite::testing::kInputShape1, tflite::testing::kInputData1,
318       tflite::testing::kInputShape2, tflite::testing::kInputData2,
319       tflite::testing::kInputShape3, tflite::testing::kInputData3,
320       tflite::testing::kOutputShape1, output_data1,
321       tflite::testing::kOutputShape2, output_data2,
322       tflite::testing::kOutputShape3, output_data3,
323       tflite::testing::kOutputShape4, output_data4, kGolden1,
324       tflite::testing::kGolden2, kGolden3, kGolden4,
325       /* tolerance */ 3e-1, /* Use regular NMS: */ true, input_data_quantized1,
326       input_data_quantized2, input_data_quantized3,
327       /* input1 min/max*/ -1.0, 1.0, /* input2 min/max */ 0.0, 1.0,
328       /* input3 min/max */ 0.0, 100.5);
329 }
330 
TF_LITE_MICRO_TEST(DetectionPostprocessFloatFastNMSwithNoBackgroundClassAndKeypoints)331 TF_LITE_MICRO_TEST(
332     DetectionPostprocessFloatFastNMSwithNoBackgroundClassAndKeypoints) {
333   const int kInputShape1[] = {3, 1, 6, 5};
334   const int kInputShape2[] = {3, 1, 6, 2};
335 
336   // six boxes in center-size encoding
337   const float kInputData1[] = {
338       0.0, 0.0,  0.0, 0.0, 1.0,  // box #1
339       0.0, 1.0,  0.0, 0.0, 1.0,  // box #2
340       0.0, -1.0, 0.0, 0.0, 1.0,  // box #3
341       0.0, 0.0,  0.0, 0.0, 1.0,  // box #4
342       0.0, 1.0,  0.0, 0.0, 1.0,  // box #5
343       0.0, 0.0,  0.0, 0.0, 1.0,  // box #6
344   };
345 
346   // class scores - two classes without background
347   const float kInputData2[] = {.9,  .8,  .75, .72, .6, .5,
348                                .93, .95, .5,  .4,  .3, .2};
349 
350   float output_data1[12];
351   float output_data2[3];
352   float output_data3[3];
353   float output_data4[1];
354 
355   tflite::testing::TestDetectionPostprocess(
356       kInputShape1, kInputData1, kInputShape2, kInputData2,
357       tflite::testing::kInputShape3, tflite::testing::kInputData3,
358       tflite::testing::kOutputShape1, output_data1,
359       tflite::testing::kOutputShape2, output_data2,
360       tflite::testing::kOutputShape3, output_data3,
361       tflite::testing::kOutputShape4, output_data4, tflite::testing::kGolden1,
362       tflite::testing::kGolden2, tflite::testing::kGolden3,
363       tflite::testing::kGolden4,
364       /* tolerance */ 0, /* Use regular NMS: */ false);
365 }
366 
TF_LITE_MICRO_TEST(DetectionPostprocessFloatRegularNMSwithNoBackgroundClassAndKeypoints)367 TF_LITE_MICRO_TEST(
368     DetectionPostprocessFloatRegularNMSwithNoBackgroundClassAndKeypoints) {
369   const int kInputShape2[] = {3, 1, 6, 2};
370 
371   // class scores - two classes without background
372   const float kInputData2[] = {.9,  .8,  .75, .72, .6, .5,
373                                .93, .95, .5,  .4,  .3, .2};
374 
375   const float kGolden1[] = {0.0, 10.0, 1.0, 11.0, 0.0, 10.0,
376                             1.0, 11.0, 0.0, 0.0,  0.0, 0.0};
377   const float kGolden3[] = {0.95, 0.9, 0.0};
378   const float kGolden4[] = {2.0};
379 
380   float output_data1[12];
381   float output_data2[3];
382   float output_data3[3];
383   float output_data4[1];
384 
385   tflite::testing::TestDetectionPostprocess(
386       tflite::testing::kInputShape1, tflite::testing::kInputData1, kInputShape2,
387       kInputData2, tflite::testing::kInputShape3, tflite::testing::kInputData3,
388       tflite::testing::kOutputShape1, output_data1,
389       tflite::testing::kOutputShape2, output_data2,
390       tflite::testing::kOutputShape3, output_data3,
391       tflite::testing::kOutputShape4, output_data4, kGolden1,
392       tflite::testing::kGolden2, kGolden3, kGolden4,
393       /* tolerance */ 1e-1, /* Use regular NMS: */ true);
394 }
395 
TF_LITE_MICRO_TEST(DetectionPostprocessFloatFastNMSWithBackgroundClassAndKeypoints)396 TF_LITE_MICRO_TEST(
397     DetectionPostprocessFloatFastNMSWithBackgroundClassAndKeypoints) {
398   const int kInputShape1[] = {3, 1, 6, 5};
399 
400   // six boxes in center-size encoding
401   const float kInputData1[] = {
402       0.0, 0.0,  0.0, 0.0, 1.0,  // box #1
403       0.0, 1.0,  0.0, 0.0, 1.0,  // box #2
404       0.0, -1.0, 0.0, 0.0, 1.0,  // box #3
405       0.0, 0.0,  0.0, 0.0, 1.0,  // box #4
406       0.0, 1.0,  0.0, 0.0, 1.0,  // box #5
407       0.0, 0.0,  0.0, 0.0, 1.0,  // box #6
408   };
409 
410   float output_data1[12];
411   float output_data2[3];
412   float output_data3[3];
413   float output_data4[1];
414 
415   tflite::testing::TestDetectionPostprocess(
416       kInputShape1, kInputData1, tflite::testing::kInputShape2,
417       tflite::testing::kInputData2, tflite::testing::kInputShape3,
418       tflite::testing::kInputData3, tflite::testing::kOutputShape1,
419       output_data1, tflite::testing::kOutputShape2, output_data2,
420       tflite::testing::kOutputShape3, output_data3,
421       tflite::testing::kOutputShape4, output_data4, tflite::testing::kGolden1,
422       tflite::testing::kGolden2, tflite::testing::kGolden3,
423       tflite::testing::kGolden4,
424       /* tolerance */ 0, /* Use regular NMS: */ false);
425 }
426 
TF_LITE_MICRO_TEST(DetectionPostprocessQuantizedFastNMSwithNoBackgroundClassAndKeypoints)427 TF_LITE_MICRO_TEST(
428     DetectionPostprocessQuantizedFastNMSwithNoBackgroundClassAndKeypoints) {
429   const int kInputShape1[] = {3, 1, 6, 5};
430   const int kInputShape2[] = {3, 1, 6, 2};
431 
432   // six boxes in center-size encoding
433   const float kInputData1[] = {
434       0.0, 0.0,  0.0, 0.0, 1.0,  // box #1
435       0.0, 1.0,  0.0, 0.0, 1.0,  // box #2
436       0.0, -1.0, 0.0, 0.0, 1.0,  // box #3
437       0.0, 0.0,  0.0, 0.0, 1.0,  // box #4
438       0.0, 1.0,  0.0, 0.0, 1.0,  // box #5
439       0.0, 0.0,  0.0, 0.0, 1.0,  // box #6
440   };
441 
442   // class scores - two classes without background
443   const float kInputData2[] = {.9,  .8,  .75, .72, .6, .5,
444                                .93, .95, .5,  .4,  .3, .2};
445 
446   const int kInputElements1 = tflite::testing::kInputShape1[1] *
447                               tflite::testing::kInputShape1[2] *
448                               tflite::testing::kInputShape1[3];
449   const int kInputElements2 = tflite::testing::kInputShape2[1] *
450                               tflite::testing::kInputShape2[2] *
451                               tflite::testing::kInputShape2[3];
452   const int kInputElements3 =
453       tflite::testing::kInputShape3[1] * tflite::testing::kInputShape3[2];
454 
455   uint8_t input_data_quantized1[kInputElements1 + 10];
456   uint8_t input_data_quantized2[kInputElements2 + 10];
457   uint8_t input_data_quantized3[kInputElements3 + 10];
458 
459   float output_data1[12];
460   float output_data2[3];
461   float output_data3[3];
462   float output_data4[1];
463 
464   tflite::testing::TestDetectionPostprocess(
465       kInputShape1, kInputData1, kInputShape2, kInputData2,
466       tflite::testing::kInputShape3, tflite::testing::kInputData3,
467       tflite::testing::kOutputShape1, output_data1,
468       tflite::testing::kOutputShape2, output_data2,
469       tflite::testing::kOutputShape3, output_data3,
470       tflite::testing::kOutputShape4, output_data4, tflite::testing::kGolden1,
471       tflite::testing::kGolden2, tflite::testing::kGolden3,
472       tflite::testing::kGolden4,
473       /* tolerance */ 3e-1, /* Use regular NMS: */ false, input_data_quantized1,
474       input_data_quantized2, input_data_quantized3,
475       /* input1 min/max*/ -1.0, 1.0, /* input2 min/max */ 0.0, 1.0,
476       /* input3 min/max */ 0.0, 100.5);
477 }
478 
479 TF_LITE_MICRO_TESTS_END
480