blob: 304520c24f974e764ede74d2736806391d03926c [file] [log] [blame]
keidav011b3e2ea2019-02-21 10:07:37 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "../TfLiteParser.hpp"
keidav011b3e2ea2019-02-21 10:07:37 +00007#include "ParserFlatbuffersFixture.hpp"
8#include "ParserPrototxtFixture.hpp"
keidav01222c7532019-03-14 17:12:10 +00009#include "ParserHelper.hpp"
Jan Eilersbb446e52020-04-02 13:56:54 +010010#include "test/GraphUtils.hpp"
keidav011b3e2ea2019-02-21 10:07:37 +000011
Jan Eilersbb446e52020-04-02 13:56:54 +010012#include <armnn/utility/PolymorphicDowncast.hpp>
Aron Virginas-Tar48623a02019-10-22 10:00:28 +010013#include <QuantizeHelper.hpp>
14
Jan Eilersbb446e52020-04-02 13:56:54 +010015#include <boost/test/unit_test.hpp>
16
keidav011b3e2ea2019-02-21 10:07:37 +000017BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
18
19struct DetectionPostProcessFixture : ParserFlatbuffersFixture
20{
keidav01222c7532019-03-14 17:12:10 +000021 explicit DetectionPostProcessFixture(const std::string& custom_options)
keidav011b3e2ea2019-02-21 10:07:37 +000022 {
23 /*
24 The following values were used for the custom_options:
keidav0107d58c72019-02-26 11:57:39 +000025 use_regular_nms = true
keidav011b3e2ea2019-02-21 10:07:37 +000026 max_classes_per_detection = 1
keidav01222c7532019-03-14 17:12:10 +000027 detections_per_class = 1
keidav011b3e2ea2019-02-21 10:07:37 +000028 nms_score_threshold = 0.0
29 nms_iou_threshold = 0.5
30 max_detections = 3
31 max_detections = 3
32 num_classes = 2
33 h_scale = 5
34 w_scale = 5
35 x_scale = 10
36 y_scale = 10
37 */
38 m_JsonString = R"(
39 {
40 "version": 3,
41 "operator_codes": [{
42 "builtin_code": "CUSTOM",
43 "custom_code": "TFLite_Detection_PostProcess"
44 }],
45 "subgraphs": [{
46 "tensors": [{
47 "shape": [1, 6, 4],
48 "type": "UINT8",
49 "buffer": 0,
50 "name": "box_encodings",
51 "quantization": {
52 "min": [0.0],
53 "max": [255.0],
54 "scale": [1.0],
55 "zero_point": [ 1 ]
56 }
57 },
58 {
59 "shape": [1, 6, 3],
60 "type": "UINT8",
61 "buffer": 1,
62 "name": "scores",
63 "quantization": {
64 "min": [0.0],
65 "max": [255.0],
66 "scale": [0.01],
67 "zero_point": [0]
68 }
69 },
70 {
71 "shape": [6, 4],
72 "type": "UINT8",
73 "buffer": 2,
74 "name": "anchors",
75 "quantization": {
76 "min": [0.0],
77 "max": [255.0],
78 "scale": [0.5],
79 "zero_point": [0]
80 }
81 },
82 {
keidav011b3e2ea2019-02-21 10:07:37 +000083 "type": "FLOAT32",
84 "buffer": 3,
85 "name": "detection_boxes",
86 "quantization": {}
87 },
88 {
keidav011b3e2ea2019-02-21 10:07:37 +000089 "type": "FLOAT32",
90 "buffer": 4,
91 "name": "detection_classes",
92 "quantization": {}
93 },
94 {
keidav011b3e2ea2019-02-21 10:07:37 +000095 "type": "FLOAT32",
96 "buffer": 5,
97 "name": "detection_scores",
98 "quantization": {}
99 },
100 {
keidav011b3e2ea2019-02-21 10:07:37 +0000101 "type": "FLOAT32",
102 "buffer": 6,
103 "name": "num_detections",
104 "quantization": {}
105 }
106 ],
107 "inputs": [0, 1, 2],
108 "outputs": [3, 4, 5, 6],
109 "operators": [{
110 "opcode_index": 0,
111 "inputs": [0, 1, 2],
112 "outputs": [3, 4, 5, 6],
113 "builtin_options_type": 0,
keidav01222c7532019-03-14 17:12:10 +0000114 "custom_options": [)" + custom_options + R"(],
keidav011b3e2ea2019-02-21 10:07:37 +0000115 "custom_options_format": "FLEXBUFFERS"
116 }]
117 }],
118 "buffers": [{},
119 {},
120 { "data": [ 1, 1, 2, 2,
121 1, 1, 2, 2,
122 1, 1, 2, 2,
123 1, 21, 2, 2,
124 1, 21, 2, 2,
125 1, 201, 2, 2]},
126 {},
127 {},
128 {},
129 {},
130 ]
131 }
132 )";
133 }
134};
135
keidav01222c7532019-03-14 17:12:10 +0000136struct ParseDetectionPostProcessCustomOptions : DetectionPostProcessFixture
137{
138private:
139 static armnn::DetectionPostProcessDescriptor GenerateDescriptor()
140 {
141 static armnn::DetectionPostProcessDescriptor descriptor;
142 descriptor.m_UseRegularNms = true;
143 descriptor.m_MaxDetections = 3u;
144 descriptor.m_MaxClassesPerDetection = 1u;
145 descriptor.m_DetectionsPerClass = 1u;
146 descriptor.m_NumClasses = 2u;
147 descriptor.m_NmsScoreThreshold = 0.0f;
148 descriptor.m_NmsIouThreshold = 0.5f;
149 descriptor.m_ScaleH = 5.0f;
150 descriptor.m_ScaleW = 5.0f;
151 descriptor.m_ScaleX = 10.0f;
152 descriptor.m_ScaleY = 10.0f;
153
154 return descriptor;
155 }
156
157public:
158 ParseDetectionPostProcessCustomOptions()
159 : DetectionPostProcessFixture(
160 GenerateDetectionPostProcessJsonString(GenerateDescriptor()))
161 {}
162};
163
164BOOST_FIXTURE_TEST_CASE( ParseDetectionPostProcess, ParseDetectionPostProcessCustomOptions )
keidav011b3e2ea2019-02-21 10:07:37 +0000165{
166 Setup();
167
168 // Inputs
169 using UnquantizedContainer = std::vector<float>;
170 UnquantizedContainer boxEncodings =
171 {
172 0.0f, 0.0f, 0.0f, 0.0f,
173 0.0f, 1.0f, 0.0f, 0.0f,
174 0.0f, -1.0f, 0.0f, 0.0f,
175 0.0f, 0.0f, 0.0f, 0.0f,
176 0.0f, 1.0f, 0.0f, 0.0f,
177 0.0f, 0.0f, 0.0f, 0.0f
178 };
179
180 UnquantizedContainer scores =
181 {
182 0.0f, 0.9f, 0.8f,
183 0.0f, 0.75f, 0.72f,
184 0.0f, 0.6f, 0.5f,
185 0.0f, 0.93f, 0.95f,
186 0.0f, 0.5f, 0.4f,
187 0.0f, 0.3f, 0.2f
188 };
189
190 // Outputs
191 UnquantizedContainer detectionBoxes =
192 {
193 0.0f, 10.0f, 1.0f, 11.0f,
194 0.0f, 10.0f, 1.0f, 11.0f,
195 0.0f, 0.0f, 0.0f, 0.0f
196 };
197
198 UnquantizedContainer detectionClasses = { 1.0f, 0.0f, 0.0f };
199 UnquantizedContainer detectionScores = { 0.95f, 0.93f, 0.0f };
200
201 UnquantizedContainer numDetections = { 2.0f };
202
203 // Quantize inputs and outputs
204 using QuantizedContainer = std::vector<uint8_t>;
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100205
206 QuantizedContainer quantBoxEncodings = armnnUtils::QuantizedVector<uint8_t>(boxEncodings, 1.00f, 1);
207 QuantizedContainer quantScores = armnnUtils::QuantizedVector<uint8_t>(scores, 0.01f, 0);
keidav011b3e2ea2019-02-21 10:07:37 +0000208
209 std::map<std::string, QuantizedContainer> input =
210 {
211 { "box_encodings", quantBoxEncodings },
212 { "scores", quantScores }
213 };
214
215 std::map<std::string, UnquantizedContainer> output =
216 {
217 { "detection_boxes", detectionBoxes},
218 { "detection_classes", detectionClasses},
219 { "detection_scores", detectionScores},
220 { "num_detections", numDetections}
221 };
222
Derek Lambertif90c56d2020-01-10 17:14:08 +0000223 RunTest<armnn::DataType::QAsymmU8, armnn::DataType::Float32>(0, input, output);
keidav011b3e2ea2019-02-21 10:07:37 +0000224}
225
keidav01222c7532019-03-14 17:12:10 +0000226BOOST_FIXTURE_TEST_CASE(DetectionPostProcessGraphStructureTest, ParseDetectionPostProcessCustomOptions)
keidav011b3e2ea2019-02-21 10:07:37 +0000227{
228 /*
229 Inputs: box_encodings scores
230 \ /
231 DetectionPostProcess
232 / / \ \
233 / / \ \
234 Outputs: detection detection detection num_detections
235 boxes classes scores
236 */
237
238 ReadStringToBinary();
239
240 armnn::INetworkPtr network = m_Parser->CreateNetworkFromBinary(m_GraphBinary);
241
242 auto optimized = Optimize(*network, { armnn::Compute::CpuRef }, m_Runtime->GetDeviceSpec());
243
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000244 armnn::Graph& graph = GetGraphForTesting(optimized.get());
keidav011b3e2ea2019-02-21 10:07:37 +0000245
246 // Check the number of layers in the graph
247 BOOST_TEST((graph.GetNumInputs() == 2));
248 BOOST_TEST((graph.GetNumOutputs() == 4));
249 BOOST_TEST((graph.GetNumLayers() == 7));
250
251 // Input layers
252 armnn::Layer* boxEncodingLayer = GetFirstLayerWithName(graph, "box_encodings");
253 BOOST_TEST((boxEncodingLayer->GetType() == armnn::LayerType::Input));
254 BOOST_TEST(CheckNumberOfInputSlot(boxEncodingLayer, 0));
255 BOOST_TEST(CheckNumberOfOutputSlot(boxEncodingLayer, 1));
256
257 armnn::Layer* scoresLayer = GetFirstLayerWithName(graph, "scores");
258 BOOST_TEST((scoresLayer->GetType() == armnn::LayerType::Input));
259 BOOST_TEST(CheckNumberOfInputSlot(scoresLayer, 0));
260 BOOST_TEST(CheckNumberOfOutputSlot(scoresLayer, 1));
261
262 // DetectionPostProcess layer
263 armnn::Layer* detectionPostProcessLayer = GetFirstLayerWithName(graph, "DetectionPostProcess:0:0");
264 BOOST_TEST((detectionPostProcessLayer->GetType() == armnn::LayerType::DetectionPostProcess));
265 BOOST_TEST(CheckNumberOfInputSlot(detectionPostProcessLayer, 2));
266 BOOST_TEST(CheckNumberOfOutputSlot(detectionPostProcessLayer, 4));
267
268 // Output layers
269 armnn::Layer* detectionBoxesLayer = GetFirstLayerWithName(graph, "detection_boxes");
270 BOOST_TEST((detectionBoxesLayer->GetType() == armnn::LayerType::Output));
271 BOOST_TEST(CheckNumberOfInputSlot(detectionBoxesLayer, 1));
272 BOOST_TEST(CheckNumberOfOutputSlot(detectionBoxesLayer, 0));
273
274 armnn::Layer* detectionClassesLayer = GetFirstLayerWithName(graph, "detection_classes");
275 BOOST_TEST((detectionClassesLayer->GetType() == armnn::LayerType::Output));
276 BOOST_TEST(CheckNumberOfInputSlot(detectionClassesLayer, 1));
277 BOOST_TEST(CheckNumberOfOutputSlot(detectionClassesLayer, 0));
278
279 armnn::Layer* detectionScoresLayer = GetFirstLayerWithName(graph, "detection_scores");
280 BOOST_TEST((detectionScoresLayer->GetType() == armnn::LayerType::Output));
281 BOOST_TEST(CheckNumberOfInputSlot(detectionScoresLayer, 1));
282 BOOST_TEST(CheckNumberOfOutputSlot(detectionScoresLayer, 0));
283
284 armnn::Layer* numDetectionsLayer = GetFirstLayerWithName(graph, "num_detections");
285 BOOST_TEST((numDetectionsLayer->GetType() == armnn::LayerType::Output));
286 BOOST_TEST(CheckNumberOfInputSlot(numDetectionsLayer, 1));
287 BOOST_TEST(CheckNumberOfOutputSlot(numDetectionsLayer, 0));
288
289 // Check the connections
Derek Lambertif90c56d2020-01-10 17:14:08 +0000290 armnn::TensorInfo boxEncodingTensor(armnn::TensorShape({ 1, 6, 4 }), armnn::DataType::QAsymmU8, 1, 1);
291 armnn::TensorInfo scoresTensor(armnn::TensorShape({ 1, 6, 3 }), armnn::DataType::QAsymmU8,
keidav011b3e2ea2019-02-21 10:07:37 +0000292 0.00999999978f, 0);
293
294 armnn::TensorInfo detectionBoxesTensor(armnn::TensorShape({ 1, 3, 4 }), armnn::DataType::Float32, 0, 0);
295 armnn::TensorInfo detectionClassesTensor(armnn::TensorShape({ 1, 3 }), armnn::DataType::Float32, 0, 0);
296 armnn::TensorInfo detectionScoresTensor(armnn::TensorShape({ 1, 3 }), armnn::DataType::Float32, 0, 0);
297 armnn::TensorInfo numDetectionsTensor(armnn::TensorShape({ 1} ), armnn::DataType::Float32, 0, 0);
298
299 BOOST_TEST(IsConnected(boxEncodingLayer, detectionPostProcessLayer, 0, 0, boxEncodingTensor));
300 BOOST_TEST(IsConnected(scoresLayer, detectionPostProcessLayer, 0, 1, scoresTensor));
301 BOOST_TEST(IsConnected(detectionPostProcessLayer, detectionBoxesLayer, 0, 0, detectionBoxesTensor));
302 BOOST_TEST(IsConnected(detectionPostProcessLayer, detectionClassesLayer, 1, 0, detectionClassesTensor));
303 BOOST_TEST(IsConnected(detectionPostProcessLayer, detectionScoresLayer, 2, 0, detectionScoresTensor));
304 BOOST_TEST(IsConnected(detectionPostProcessLayer, numDetectionsLayer, 3, 0, numDetectionsTensor));
305}
306
307BOOST_AUTO_TEST_SUITE_END()