// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "TensorCopyUtils.hpp" #include #include "WorkloadTestUtils.hpp" #include #include #include #include #include #include template > void DetectionPostProcessImpl(const armnn::TensorInfo& boxEncodingsInfo, const armnn::TensorInfo& scoresInfo, const armnn::TensorInfo& anchorsInfo, const std::vector& boxEncodingsData, const std::vector& scoresData, const std::vector& anchorsData, const std::vector& expectedDetectionBoxes, const std::vector& expectedDetectionClasses, const std::vector& expectedDetectionScores, const std::vector& expectedNumDetections, bool useRegularNms) { std::unique_ptr profiler = std::make_unique(); armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get()); auto memoryManager = WorkloadFactoryHelper::GetMemoryManager(); FactoryType workloadFactory = WorkloadFactoryHelper::GetFactory(memoryManager); auto boxEncodings = MakeTensor(boxEncodingsInfo, boxEncodingsData); auto scores = MakeTensor(scoresInfo, scoresData); auto anchors = MakeTensor(anchorsInfo, anchorsData); armnn::TensorInfo detectionBoxesInfo({ 1, 3, 4 }, armnn::DataType::Float32); armnn::TensorInfo detectionScoresInfo({ 1, 3 }, armnn::DataType::Float32); armnn::TensorInfo detectionClassesInfo({ 1, 3 }, armnn::DataType::Float32); armnn::TensorInfo numDetectionInfo({ 1 }, armnn::DataType::Float32); LayerTestResult detectionBoxesResult(detectionBoxesInfo); detectionBoxesResult.outputExpected = MakeTensor(detectionBoxesInfo, expectedDetectionBoxes); LayerTestResult detectionClassesResult(detectionClassesInfo); detectionClassesResult.outputExpected = MakeTensor(detectionClassesInfo, expectedDetectionClasses); LayerTestResult detectionScoresResult(detectionScoresInfo); detectionScoresResult.outputExpected = MakeTensor(detectionScoresInfo, expectedDetectionScores); LayerTestResult numDetectionsResult(numDetectionInfo); numDetectionsResult.outputExpected = MakeTensor(numDetectionInfo, expectedNumDetections); std::unique_ptr boxedHandle = workloadFactory.CreateTensorHandle(boxEncodingsInfo); std::unique_ptr scoreshandle = workloadFactory.CreateTensorHandle(scoresInfo); std::unique_ptr anchorsHandle = workloadFactory.CreateTensorHandle(anchorsInfo); std::unique_ptr outputBoxesHandle = workloadFactory.CreateTensorHandle(detectionBoxesInfo); std::unique_ptr classesHandle = workloadFactory.CreateTensorHandle(detectionClassesInfo); std::unique_ptr outputScoresHandle = workloadFactory.CreateTensorHandle(detectionScoresInfo); std::unique_ptr numDetectionHandle = workloadFactory.CreateTensorHandle(numDetectionInfo); armnn::ScopedCpuTensorHandle anchorsTensor(anchorsInfo); AllocateAndCopyDataToITensorHandle(&anchorsTensor, &anchors[0][0]); armnn::DetectionPostProcessQueueDescriptor data; data.m_Parameters.m_UseRegularNms = useRegularNms; data.m_Parameters.m_MaxDetections = 3; data.m_Parameters.m_MaxClassesPerDetection = 1; data.m_Parameters.m_DetectionsPerClass =1; data.m_Parameters.m_NmsScoreThreshold = 0.0; data.m_Parameters.m_NmsIouThreshold = 0.5; data.m_Parameters.m_NumClasses = 2; data.m_Parameters.m_ScaleY = 10.0; data.m_Parameters.m_ScaleX = 10.0; data.m_Parameters.m_ScaleH = 5.0; data.m_Parameters.m_ScaleW = 5.0; data.m_Anchors = &anchorsTensor; armnn::WorkloadInfo info; AddInputToWorkload(data, info, boxEncodingsInfo, boxedHandle.get()); AddInputToWorkload(data, info, scoresInfo, scoreshandle.get()); AddOutputToWorkload(data, info, detectionBoxesInfo, outputBoxesHandle.get()); AddOutputToWorkload(data, info, detectionClassesInfo, classesHandle.get()); AddOutputToWorkload(data, info, detectionScoresInfo, outputScoresHandle.get()); AddOutputToWorkload(data, info, numDetectionInfo, numDetectionHandle.get()); std::unique_ptr workload = workloadFactory.CreateDetectionPostProcess(data, info); boxedHandle->Allocate(); scoreshandle->Allocate(); outputBoxesHandle->Allocate(); classesHandle->Allocate(); outputScoresHandle->Allocate(); numDetectionHandle->Allocate(); CopyDataToITensorHandle(boxedHandle.get(), boxEncodings.origin()); CopyDataToITensorHandle(scoreshandle.get(), scores.origin()); workload->Execute(); CopyDataFromITensorHandle(detectionBoxesResult.output.origin(), outputBoxesHandle.get()); CopyDataFromITensorHandle(detectionClassesResult.output.origin(), classesHandle.get()); CopyDataFromITensorHandle(detectionScoresResult.output.origin(), outputScoresHandle.get()); CopyDataFromITensorHandle(numDetectionsResult.output.origin(), numDetectionHandle.get()); BOOST_TEST(CompareTensors(detectionBoxesResult.output, detectionBoxesResult.outputExpected)); BOOST_TEST(CompareTensors(detectionClassesResult.output, detectionClassesResult.outputExpected)); BOOST_TEST(CompareTensors(detectionScoresResult.output, detectionScoresResult.outputExpected)); BOOST_TEST(CompareTensors(numDetectionsResult.output, numDetectionsResult.outputExpected)); } inline void QuantizeData(uint8_t* quant, const float* dequant, const armnn::TensorInfo& info) { for (size_t i = 0; i < info.GetNumElements(); i++) { quant[i] = armnn::Quantize(dequant[i], info.GetQuantizationScale(), info.GetQuantizationOffset()); } } template void DetectionPostProcessRegularNmsFloatTest() { armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::Float32); armnn::TensorInfo scoresInfo({ 1, 6, 3}, armnn::DataType::Float32); armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32); std::vector boxEncodingsData({ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }); std::vector scoresData({ 0.0f, 0.9f, 0.8f, 0.0f, 0.75f, 0.72f, 0.0f, 0.6f, 0.5f, 0.0f, 0.93f, 0.95f, 0.0f, 0.5f, 0.4f, 0.0f, 0.3f, 0.2f }); std::vector anchorsData({ 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 100.5f, 1.0f, 1.0f }); std::vector expectedDetectionBoxes({ 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 0.0f, 0.0f, 0.0f }); std::vector expectedDetectionScores({ 0.95f, 0.93f, 0.0f }); std::vector expectedDetectionClasses({ 1.0f, 0.0f, 0.0f }); std::vector expectedNumDetections({ 2.0f }); return DetectionPostProcessImpl(boxEncodingsInfo, scoresInfo, anchorsInfo, boxEncodingsData, scoresData, anchorsData, expectedDetectionBoxes, expectedDetectionClasses, expectedDetectionScores, expectedNumDetections, true); } template void DetectionPostProcessRegularNmsUint8Test() { armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::QuantisedAsymm8); armnn::TensorInfo scoresInfo({ 1, 6, 3 }, armnn::DataType::QuantisedAsymm8); armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::QuantisedAsymm8); boxEncodingsInfo.SetQuantizationScale(1.0f); boxEncodingsInfo.SetQuantizationOffset(1); scoresInfo.SetQuantizationScale(0.01f); scoresInfo.SetQuantizationOffset(0); anchorsInfo.SetQuantizationScale(0.5f); anchorsInfo.SetQuantizationOffset(0); std::vector boxEncodings({ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }); std::vector scores({ 0.0f, 0.9f, 0.8f, 0.0f, 0.75f, 0.72f, 0.0f, 0.6f, 0.5f, 0.0f, 0.93f, 0.95f, 0.0f, 0.5f, 0.4f, 0.0f, 0.3f, 0.2f }); std::vector anchors({ 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 100.5f, 1.0f, 1.0f }); std::vector boxEncodingsData(boxEncodings.size(), 0); std::vector scoresData(scores.size(), 0); std::vector anchorsData(anchors.size(), 0); QuantizeData(boxEncodingsData.data(), boxEncodings.data(), boxEncodingsInfo); QuantizeData(scoresData.data(), scores.data(), scoresInfo); QuantizeData(anchorsData.data(), anchors.data(), anchorsInfo); std::vector expectedDetectionBoxes({ 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 0.0f, 0.0f, 0.0f }); std::vector expectedDetectionScores({ 0.95f, 0.93f, 0.0f }); std::vector expectedDetectionClasses({ 1.0f, 0.0f, 0.0f }); std::vector expectedNumDetections({ 2.0f }); return DetectionPostProcessImpl(boxEncodingsInfo, scoresInfo, anchorsInfo, boxEncodingsData, scoresData, anchorsData, expectedDetectionBoxes, expectedDetectionClasses, expectedDetectionScores, expectedNumDetections, true); } template void DetectionPostProcessFastNmsFloatTest() { armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::Float32); armnn::TensorInfo scoresInfo({ 1, 6, 3}, armnn::DataType::Float32); armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32); std::vector boxEncodingsData({ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }); std::vector scoresData({ 0.0f, 0.9f, 0.8f, 0.0f, 0.75f, 0.72f, 0.0f, 0.6f, 0.5f, 0.0f, 0.93f, 0.95f, 0.0f, 0.5f, 0.4f, 0.0f, 0.3f, 0.2f }); std::vector anchorsData({ 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 100.5f, 1.0f, 1.0f }); std::vector expectedDetectionBoxes({ 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 100.0f, 1.0f, 101.0f }); std::vector expectedDetectionScores({ 0.95f, 0.9f, 0.3f }); std::vector expectedDetectionClasses({ 1.0f, 0.0f, 0.0f }); std::vector expectedNumDetections({ 3.0f }); return DetectionPostProcessImpl(boxEncodingsInfo, scoresInfo, anchorsInfo, boxEncodingsData, scoresData, anchorsData, expectedDetectionBoxes, expectedDetectionClasses, expectedDetectionScores, expectedNumDetections, false); } template void DetectionPostProcessFastNmsUint8Test() { armnn::TensorInfo boxEncodingsInfo({ 1, 6, 4 }, armnn::DataType::QuantisedAsymm8); armnn::TensorInfo scoresInfo({ 1, 6, 3 }, armnn::DataType::QuantisedAsymm8); armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::QuantisedAsymm8); boxEncodingsInfo.SetQuantizationScale(1.0f); boxEncodingsInfo.SetQuantizationOffset(1); scoresInfo.SetQuantizationScale(0.01f); scoresInfo.SetQuantizationOffset(0); anchorsInfo.SetQuantizationScale(0.5f); anchorsInfo.SetQuantizationOffset(0); std::vector boxEncodings({ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }); std::vector scores({ 0.0f, 0.9f, 0.8f, 0.0f, 0.75f, 0.72f, 0.0f, 0.6f, 0.5f, 0.0f, 0.93f, 0.95f, 0.0f, 0.5f, 0.4f, 0.0f, 0.3f, 0.2f }); std::vector anchors({ 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 100.5f, 1.0f, 1.0f }); std::vector boxEncodingsData(boxEncodings.size(), 0); std::vector scoresData(scores.size(), 0); std::vector anchorsData(anchors.size(), 0); QuantizeData(boxEncodingsData.data(), boxEncodings.data(), boxEncodingsInfo); QuantizeData(scoresData.data(), scores.data(), scoresInfo); QuantizeData(anchorsData.data(), anchors.data(), anchorsInfo); std::vector expectedDetectionBoxes({ 0.0f, 10.0f, 1.0f, 11.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 100.0f, 1.0f, 101.0f }); std::vector expectedDetectionScores({ 0.95f, 0.9f, 0.3f }); std::vector expectedDetectionClasses({ 1.0f, 0.0f, 0.0f }); std::vector expectedNumDetections({ 3.0f }); return DetectionPostProcessImpl(boxEncodingsInfo, scoresInfo, anchorsInfo, boxEncodingsData, scoresData, anchorsData, expectedDetectionBoxes, expectedDetectionClasses, expectedDetectionScores, expectedNumDetections, false); }