blob: 092ce26696a6775c8de5bf133f109f4476b13384 [file] [log] [blame]
Narumol Prangnawarate0a4ad82019-02-04 19:05:27 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5#pragma once
6
7#include "TensorCopyUtils.hpp"
Aron Virginas-Tard4f0fea2019-04-09 14:08:06 +01008#include <ResolveType.hpp>
Narumol Prangnawarate0a4ad82019-02-04 19:05:27 +00009#include "WorkloadTestUtils.hpp"
10
11#include <armnn/Types.hpp>
12#include <backendsCommon/CpuTensorHandle.hpp>
13#include <backendsCommon/IBackendInternal.hpp>
14#include <backendsCommon/WorkloadFactory.hpp>
15#include <backendsCommon/test/WorkloadFactoryHelper.hpp>
16#include <test/TensorHelpers.hpp>
17
18template <typename FactoryType, armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
19void DetectionPostProcessImpl(const armnn::TensorInfo& boxEncodingsInfo,
20 const armnn::TensorInfo& scoresInfo,
21 const armnn::TensorInfo& anchorsInfo,
22 const std::vector<T>& boxEncodingsData,
23 const std::vector<T>& scoresData,
24 const std::vector<T>& anchorsData,
25 const std::vector<float>& expectedDetectionBoxes,
26 const std::vector<float>& expectedDetectionClasses,
27 const std::vector<float>& expectedDetectionScores,
28 const std::vector<float>& expectedNumDetections,
29 bool useRegularNms)
30{
31 std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
32 armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get());
33
34 auto memoryManager = WorkloadFactoryHelper<FactoryType>::GetMemoryManager();
35 FactoryType workloadFactory = WorkloadFactoryHelper<FactoryType>::GetFactory(memoryManager);
36
37 auto boxEncodings = MakeTensor<T, 3>(boxEncodingsInfo, boxEncodingsData);
38 auto scores = MakeTensor<T, 3>(scoresInfo, scoresData);
39 auto anchors = MakeTensor<T, 2>(anchorsInfo, anchorsData);
40
41 armnn::TensorInfo detectionBoxesInfo({ 1, 3, 4 }, armnn::DataType::Float32);
42 armnn::TensorInfo detectionScoresInfo({ 1, 3 }, armnn::DataType::Float32);
43 armnn::TensorInfo detectionClassesInfo({ 1, 3 }, armnn::DataType::Float32);
44 armnn::TensorInfo numDetectionInfo({ 1 }, armnn::DataType::Float32);
45
46 LayerTestResult<float, 3> detectionBoxesResult(detectionBoxesInfo);
47 detectionBoxesResult.outputExpected = MakeTensor<float, 3>(detectionBoxesInfo, expectedDetectionBoxes);
48 LayerTestResult<float, 2> detectionClassesResult(detectionClassesInfo);
49 detectionClassesResult.outputExpected = MakeTensor<float, 2>(detectionClassesInfo, expectedDetectionClasses);
50 LayerTestResult<float, 2> detectionScoresResult(detectionScoresInfo);
51 detectionScoresResult.outputExpected = MakeTensor<float, 2>(detectionScoresInfo, expectedDetectionScores);
52 LayerTestResult<float, 1> numDetectionsResult(numDetectionInfo);
53 numDetectionsResult.outputExpected = MakeTensor<float, 1>(numDetectionInfo, expectedNumDetections);
54
55 std::unique_ptr<armnn::ITensorHandle> boxedHandle = workloadFactory.CreateTensorHandle(boxEncodingsInfo);
56 std::unique_ptr<armnn::ITensorHandle> scoreshandle = workloadFactory.CreateTensorHandle(scoresInfo);
57 std::unique_ptr<armnn::ITensorHandle> anchorsHandle = workloadFactory.CreateTensorHandle(anchorsInfo);
58 std::unique_ptr<armnn::ITensorHandle> outputBoxesHandle = workloadFactory.CreateTensorHandle(detectionBoxesInfo);
59 std::unique_ptr<armnn::ITensorHandle> classesHandle = workloadFactory.CreateTensorHandle(detectionClassesInfo);
60 std::unique_ptr<armnn::ITensorHandle> outputScoresHandle = workloadFactory.CreateTensorHandle(detectionScoresInfo);
61 std::unique_ptr<armnn::ITensorHandle> numDetectionHandle = workloadFactory.CreateTensorHandle(numDetectionInfo);
62
63 armnn::ScopedCpuTensorHandle anchorsTensor(anchorsInfo);
64 AllocateAndCopyDataToITensorHandle(&anchorsTensor, &anchors[0][0]);
65
66 armnn::DetectionPostProcessQueueDescriptor data;
67 data.m_Parameters.m_UseRegularNms = useRegularNms;
68 data.m_Parameters.m_MaxDetections = 3;
69 data.m_Parameters.m_MaxClassesPerDetection = 1;
70 data.m_Parameters.m_DetectionsPerClass =1;
71 data.m_Parameters.m_NmsScoreThreshold = 0.0;
72 data.m_Parameters.m_NmsIouThreshold = 0.5;
73 data.m_Parameters.m_NumClasses = 2;
74 data.m_Parameters.m_ScaleY = 10.0;
75 data.m_Parameters.m_ScaleX = 10.0;
76 data.m_Parameters.m_ScaleH = 5.0;
77 data.m_Parameters.m_ScaleW = 5.0;
78 data.m_Anchors = &anchorsTensor;
79
80 armnn::WorkloadInfo info;
81 AddInputToWorkload(data, info, boxEncodingsInfo, boxedHandle.get());
82 AddInputToWorkload(data, info, scoresInfo, scoreshandle.get());
83 AddOutputToWorkload(data, info, detectionBoxesInfo, outputBoxesHandle.get());
84 AddOutputToWorkload(data, info, detectionClassesInfo, classesHandle.get());
85 AddOutputToWorkload(data, info, detectionScoresInfo, outputScoresHandle.get());
86 AddOutputToWorkload(data, info, numDetectionInfo, numDetectionHandle.get());
87
88 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDetectionPostProcess(data, info);
89
90 boxedHandle->Allocate();
91 scoreshandle->Allocate();
92 outputBoxesHandle->Allocate();
93 classesHandle->Allocate();
94 outputScoresHandle->Allocate();
95 numDetectionHandle->Allocate();
96
97 CopyDataToITensorHandle(boxedHandle.get(), boxEncodings.origin());
98 CopyDataToITensorHandle(scoreshandle.get(), scores.origin());
99
100 workload->Execute();
101
102 CopyDataFromITensorHandle(detectionBoxesResult.output.origin(), outputBoxesHandle.get());
103 CopyDataFromITensorHandle(detectionClassesResult.output.origin(), classesHandle.get());
104 CopyDataFromITensorHandle(detectionScoresResult.output.origin(), outputScoresHandle.get());
105 CopyDataFromITensorHandle(numDetectionsResult.output.origin(), numDetectionHandle.get());
106
107 BOOST_TEST(CompareTensors(detectionBoxesResult.output, detectionBoxesResult.outputExpected));
108 BOOST_TEST(CompareTensors(detectionClassesResult.output, detectionClassesResult.outputExpected));
109 BOOST_TEST(CompareTensors(detectionScoresResult.output, detectionScoresResult.outputExpected));
110 BOOST_TEST(CompareTensors(numDetectionsResult.output, numDetectionsResult.outputExpected));
111}
112
113inline void QuantizeData(uint8_t* quant, const float* dequant, const armnn::TensorInfo& info)
114{
115 for (size_t i = 0; i < info.GetNumElements(); i++)
116 {
117 quant[i] = armnn::Quantize<uint8_t>(dequant[i], info.GetQuantizationScale(), info.GetQuantizationOffset());
118 }
119}
120
121template <typename FactoryType>
122void DetectionPostProcessRegularNmsFloatTest()
123{
124 armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::Float32);
125 armnn::TensorInfo scoresInfo({ 1, 6, 3}, armnn::DataType::Float32);
126 armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
127
128 std::vector<float> boxEncodingsData({
129 0.0f, 0.0f, 0.0f, 0.0f,
130 0.0f, 1.0f, 0.0f, 0.0f,
131 0.0f, -1.0f, 0.0f, 0.0f,
132 0.0f, 0.0f, 0.0f, 0.0f,
133 0.0f, 1.0f, 0.0f, 0.0f,
134 0.0f, 0.0f, 0.0f, 0.0f
135 });
136 std::vector<float> scoresData({
137 0.0f, 0.9f, 0.8f,
138 0.0f, 0.75f, 0.72f,
139 0.0f, 0.6f, 0.5f,
140 0.0f, 0.93f, 0.95f,
141 0.0f, 0.5f, 0.4f,
142 0.0f, 0.3f, 0.2f
143 });
144 std::vector<float> anchorsData({
145 0.5f, 0.5f, 1.0f, 1.0f,
146 0.5f, 0.5f, 1.0f, 1.0f,
147 0.5f, 0.5f, 1.0f, 1.0f,
148 0.5f, 10.5f, 1.0f, 1.0f,
149 0.5f, 10.5f, 1.0f, 1.0f,
150 0.5f, 100.5f, 1.0f, 1.0f
151 });
152
153 std::vector<float> expectedDetectionBoxes({
154 0.0f, 10.0f, 1.0f, 11.0f,
155 0.0f, 10.0f, 1.0f, 11.0f,
156 0.0f, 0.0f, 0.0f, 0.0f
157 });
158 std::vector<float> expectedDetectionScores({ 0.95f, 0.93f, 0.0f });
159 std::vector<float> expectedDetectionClasses({ 1.0f, 0.0f, 0.0f });
160 std::vector<float> expectedNumDetections({ 2.0f });
161
162 return DetectionPostProcessImpl<FactoryType, armnn::DataType::Float32>(boxEncodingsInfo,
163 scoresInfo,
164 anchorsInfo,
165 boxEncodingsData,
166 scoresData,
167 anchorsData,
168 expectedDetectionBoxes,
169 expectedDetectionClasses,
170 expectedDetectionScores,
171 expectedNumDetections,
172 true);
173}
174
175template <typename FactoryType>
176void DetectionPostProcessRegularNmsUint8Test()
177{
178 armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::QuantisedAsymm8);
179 armnn::TensorInfo scoresInfo({ 1, 6, 3 }, armnn::DataType::QuantisedAsymm8);
180 armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::QuantisedAsymm8);
181
182 boxEncodingsInfo.SetQuantizationScale(1.0f);
183 boxEncodingsInfo.SetQuantizationOffset(1);
184 scoresInfo.SetQuantizationScale(0.01f);
185 scoresInfo.SetQuantizationOffset(0);
186 anchorsInfo.SetQuantizationScale(0.5f);
187 anchorsInfo.SetQuantizationOffset(0);
188
189 std::vector<float> boxEncodings({
190 0.0f, 0.0f, 0.0f, 0.0f,
191 0.0f, 1.0f, 0.0f, 0.0f,
192 0.0f, -1.0f, 0.0f, 0.0f,
193 0.0f, 0.0f, 0.0f, 0.0f,
194 0.0f, 1.0f, 0.0f, 0.0f,
195 0.0f, 0.0f, 0.0f, 0.0f
196 });
197 std::vector<float> scores({
198 0.0f, 0.9f, 0.8f,
199 0.0f, 0.75f, 0.72f,
200 0.0f, 0.6f, 0.5f,
201 0.0f, 0.93f, 0.95f,
202 0.0f, 0.5f, 0.4f,
203 0.0f, 0.3f, 0.2f
204 });
205 std::vector<float> anchors({
206 0.5f, 0.5f, 1.0f, 1.0f,
207 0.5f, 0.5f, 1.0f, 1.0f,
208 0.5f, 0.5f, 1.0f, 1.0f,
209 0.5f, 10.5f, 1.0f, 1.0f,
210 0.5f, 10.5f, 1.0f, 1.0f,
211 0.5f, 100.5f, 1.0f, 1.0f
212 });
213
214 std::vector<uint8_t> boxEncodingsData(boxEncodings.size(), 0);
215 std::vector<uint8_t> scoresData(scores.size(), 0);
216 std::vector<uint8_t> anchorsData(anchors.size(), 0);
217 QuantizeData(boxEncodingsData.data(), boxEncodings.data(), boxEncodingsInfo);
218 QuantizeData(scoresData.data(), scores.data(), scoresInfo);
219 QuantizeData(anchorsData.data(), anchors.data(), anchorsInfo);
220
221 std::vector<float> expectedDetectionBoxes({
222 0.0f, 10.0f, 1.0f, 11.0f,
223 0.0f, 10.0f, 1.0f, 11.0f,
224 0.0f, 0.0f, 0.0f, 0.0f
225 });
226 std::vector<float> expectedDetectionScores({ 0.95f, 0.93f, 0.0f });
227 std::vector<float> expectedDetectionClasses({ 1.0f, 0.0f, 0.0f });
228 std::vector<float> expectedNumDetections({ 2.0f });
229
230 return DetectionPostProcessImpl<FactoryType, armnn::DataType::QuantisedAsymm8>(boxEncodingsInfo,
231 scoresInfo,
232 anchorsInfo,
233 boxEncodingsData,
234 scoresData,
235 anchorsData,
236 expectedDetectionBoxes,
237 expectedDetectionClasses,
238 expectedDetectionScores,
239 expectedNumDetections,
240 true);
241}
242
243template <typename FactoryType>
244void DetectionPostProcessFastNmsFloatTest()
245{
246 armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::Float32);
247 armnn::TensorInfo scoresInfo({ 1, 6, 3}, armnn::DataType::Float32);
248 armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32);
249
250 std::vector<float> boxEncodingsData({
251 0.0f, 0.0f, 0.0f, 0.0f,
252 0.0f, 1.0f, 0.0f, 0.0f,
253 0.0f, -1.0f, 0.0f, 0.0f,
254 0.0f, 0.0f, 0.0f, 0.0f,
255 0.0f, 1.0f, 0.0f, 0.0f,
256 0.0f, 0.0f, 0.0f, 0.0f
257 });
258 std::vector<float> scoresData({
259 0.0f, 0.9f, 0.8f,
260 0.0f, 0.75f, 0.72f,
261 0.0f, 0.6f, 0.5f,
262 0.0f, 0.93f, 0.95f,
263 0.0f, 0.5f, 0.4f,
264 0.0f, 0.3f, 0.2f
265 });
266 std::vector<float> anchorsData({
267 0.5f, 0.5f, 1.0f, 1.0f,
268 0.5f, 0.5f, 1.0f, 1.0f,
269 0.5f, 0.5f, 1.0f, 1.0f,
270 0.5f, 10.5f, 1.0f, 1.0f,
271 0.5f, 10.5f, 1.0f, 1.0f,
272 0.5f, 100.5f, 1.0f, 1.0f
273 });
274
275 std::vector<float> expectedDetectionBoxes({
276 0.0f, 10.0f, 1.0f, 11.0f,
277 0.0f, 0.0f, 1.0f, 1.0f,
278 0.0f, 100.0f, 1.0f, 101.0f
279 });
280 std::vector<float> expectedDetectionScores({ 0.95f, 0.9f, 0.3f });
281 std::vector<float> expectedDetectionClasses({ 1.0f, 0.0f, 0.0f });
282 std::vector<float> expectedNumDetections({ 3.0f });
283
284 return DetectionPostProcessImpl<FactoryType, armnn::DataType::Float32>(boxEncodingsInfo,
285 scoresInfo,
286 anchorsInfo,
287 boxEncodingsData,
288 scoresData,
289 anchorsData,
290 expectedDetectionBoxes,
291 expectedDetectionClasses,
292 expectedDetectionScores,
293 expectedNumDetections,
294 false);
295}
296
297template <typename FactoryType>
298void DetectionPostProcessFastNmsUint8Test()
299{
300 armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::QuantisedAsymm8);
301 armnn::TensorInfo scoresInfo({ 1, 6, 3 }, armnn::DataType::QuantisedAsymm8);
302 armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::QuantisedAsymm8);
303
304 boxEncodingsInfo.SetQuantizationScale(1.0f);
305 boxEncodingsInfo.SetQuantizationOffset(1);
306 scoresInfo.SetQuantizationScale(0.01f);
307 scoresInfo.SetQuantizationOffset(0);
308 anchorsInfo.SetQuantizationScale(0.5f);
309 anchorsInfo.SetQuantizationOffset(0);
310
311 std::vector<float> boxEncodings({
312 0.0f, 0.0f, 0.0f, 0.0f,
313 0.0f, 1.0f, 0.0f, 0.0f,
314 0.0f, -1.0f, 0.0f, 0.0f,
315 0.0f, 0.0f, 0.0f, 0.0f,
316 0.0f, 1.0f, 0.0f, 0.0f,
317 0.0f, 0.0f, 0.0f, 0.0f
318 });
319 std::vector<float> scores({
320 0.0f, 0.9f, 0.8f,
321 0.0f, 0.75f, 0.72f,
322 0.0f, 0.6f, 0.5f,
323 0.0f, 0.93f, 0.95f,
324 0.0f, 0.5f, 0.4f,
325 0.0f, 0.3f, 0.2f
326 });
327 std::vector<float> anchors({
328 0.5f, 0.5f, 1.0f, 1.0f,
329 0.5f, 0.5f, 1.0f, 1.0f,
330 0.5f, 0.5f, 1.0f, 1.0f,
331 0.5f, 10.5f, 1.0f, 1.0f,
332 0.5f, 10.5f, 1.0f, 1.0f,
333 0.5f, 100.5f, 1.0f, 1.0f
334 });
335
336 std::vector<uint8_t> boxEncodingsData(boxEncodings.size(), 0);
337 std::vector<uint8_t> scoresData(scores.size(), 0);
338 std::vector<uint8_t> anchorsData(anchors.size(), 0);
339 QuantizeData(boxEncodingsData.data(), boxEncodings.data(), boxEncodingsInfo);
340 QuantizeData(scoresData.data(), scores.data(), scoresInfo);
341 QuantizeData(anchorsData.data(), anchors.data(), anchorsInfo);
342
343 std::vector<float> expectedDetectionBoxes({
344 0.0f, 10.0f, 1.0f, 11.0f,
345 0.0f, 0.0f, 1.0f, 1.0f,
346 0.0f, 100.0f, 1.0f, 101.0f
347 });
348 std::vector<float> expectedDetectionScores({ 0.95f, 0.9f, 0.3f });
349 std::vector<float> expectedDetectionClasses({ 1.0f, 0.0f, 0.0f });
350 std::vector<float> expectedNumDetections({ 3.0f });
351
352 return DetectionPostProcessImpl<FactoryType, armnn::DataType::QuantisedAsymm8>(boxEncodingsInfo,
353 scoresInfo,
354 anchorsInfo,
355 boxEncodingsData,
356 scoresData,
357 anchorsData,
358 expectedDetectionBoxes,
359 expectedDetectionClasses,
360 expectedDetectionScores,
361 expectedNumDetections,
362 false);
363}