1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6
7 #include <armnnUtils/Permute.hpp>
8
9 #include <armnnUtils/QuantizeHelper.hpp>
10 #include <ResolveType.hpp>
11
12 #include <CommonTestUtils.hpp>
13
14 #include <map>
15 #include <vector>
16
17 namespace
18 {
19
CreateResizeNetwork(const armnn::ResizeDescriptor & descriptor,const armnn::TensorInfo & inputInfo,const armnn::TensorInfo & outputInfo)20 armnn::INetworkPtr CreateResizeNetwork(const armnn::ResizeDescriptor& descriptor,
21 const armnn::TensorInfo& inputInfo,
22 const armnn::TensorInfo& outputInfo)
23 {
24 using namespace armnn;
25
26 INetworkPtr network(INetwork::Create());
27 IConnectableLayer* input = network->AddInputLayer(0, "input");
28 IConnectableLayer* resize = network->AddResizeLayer(descriptor, "resize");
29 IConnectableLayer* output = network->AddOutputLayer(0, "output");
30
31 Connect(input, resize, inputInfo, 0, 0);
32 Connect(resize, output, outputInfo, 0, 0);
33
34 return network;
35 }
36
37 template<armnn::DataType ArmnnType>
ResizeEndToEnd(const std::vector<armnn::BackendId> & backends,armnn::DataLayout dataLayout,armnn::ResizeMethod resizeMethod)38 void ResizeEndToEnd(const std::vector<armnn::BackendId>& backends,
39 armnn::DataLayout dataLayout,
40 armnn::ResizeMethod resizeMethod)
41 {
42 using namespace armnn;
43 using T = ResolveType<ArmnnType>;
44
45 constexpr unsigned int inputWidth = 3u;
46 constexpr unsigned int inputHeight = inputWidth;
47
48 constexpr unsigned int outputWidth = 5u;
49 constexpr unsigned int outputHeight = outputWidth;
50
51 TensorShape inputShape = MakeTensorShape(1, 1, inputHeight, inputWidth, dataLayout);
52 TensorShape outputShape = MakeTensorShape(1, 1, outputHeight, outputWidth, dataLayout);
53
54 const float qScale = IsQuantizedType<T>() ? 0.25f : 1.0f;
55 const int32_t qOffset = IsQuantizedType<T>() ? 50 : 0;
56
57 TensorInfo inputInfo(inputShape, ArmnnType, qScale, qOffset, true);
58 TensorInfo outputInfo(outputShape, ArmnnType, qScale, qOffset);
59
60 std::vector<float> inputData =
61 {
62 1.f, 2.f, 3.f,
63 4.f, 5.f, 6.f,
64 7.f, 8.f, 9.f
65 };
66
67 std::vector<float> expectedOutputData;
68 switch(resizeMethod)
69 {
70 case ResizeMethod::Bilinear:
71 {
72 expectedOutputData =
73 {
74 1.0f, 1.6f, 2.2f, 2.8f, 3.0f,
75 2.8f, 3.4f, 4.0f, 4.6f, 4.8f,
76 4.6f, 5.2f, 5.8f, 6.4f, 6.6f,
77 6.4f, 7.0f, 7.6f, 8.2f, 8.4f,
78 7.0f, 7.6f, 8.2f, 8.8f, 9.0f
79 };
80 break;
81 }
82 case ResizeMethod::NearestNeighbor:
83 {
84 expectedOutputData =
85 {
86 1.f, 1.f, 2.f, 2.f, 3.f,
87 1.f, 1.f, 2.f, 2.f, 3.f,
88 4.f, 4.f, 5.f, 5.f, 6.f,
89 4.f, 4.f, 5.f, 5.f, 6.f,
90 7.f, 7.f, 8.f, 8.f, 9.f
91 };
92 break;
93 }
94 default:
95 {
96 throw InvalidArgumentException("Unrecognized resize method");
97 }
98 }
99
100 ResizeDescriptor descriptor;
101 descriptor.m_TargetWidth = outputWidth;
102 descriptor.m_TargetHeight = outputHeight;
103 descriptor.m_Method = resizeMethod;
104 descriptor.m_DataLayout = dataLayout;
105
106 // swizzle data if needed
107 if (dataLayout == armnn::DataLayout::NHWC)
108 {
109 constexpr size_t dataTypeSize = sizeof(float);
110 const armnn::PermutationVector nchwToNhwc = { 0, 3, 1, 2 };
111
112 std::vector<float> tmp(inputData.size());
113 armnnUtils::Permute(inputInfo.GetShape(), nchwToNhwc, inputData.data(), tmp.data(), dataTypeSize);
114 inputData = tmp;
115 }
116
117 // quantize data
118 std::vector<T> qInputData = armnnUtils::QuantizedVector<T>(inputData, qScale, qOffset);
119 std::vector<T> qExpectedOutputData = armnnUtils::QuantizedVector<T>(expectedOutputData, qScale, qOffset);
120
121 INetworkPtr network = CreateResizeNetwork(descriptor, inputInfo, outputInfo);
122
123 EndToEndLayerTestImpl<ArmnnType, ArmnnType>(std::move(network),
124 { { 0, qInputData } },
125 { { 0, qExpectedOutputData } },
126 backends);
127 }
128
129 } // anonymous namespace
130
131 template<armnn::DataType ArmnnType>
ResizeBilinearEndToEnd(const std::vector<armnn::BackendId> & backends,armnn::DataLayout dataLayout)132 void ResizeBilinearEndToEnd(const std::vector<armnn::BackendId>& backends,
133 armnn::DataLayout dataLayout)
134 {
135 ResizeEndToEnd<ArmnnType>(backends, dataLayout, armnn::ResizeMethod::Bilinear);
136 }
137
138 template<armnn::DataType ArmnnType>
ResizeNearestNeighborEndToEnd(const std::vector<armnn::BackendId> & backends,armnn::DataLayout dataLayout)139 void ResizeNearestNeighborEndToEnd(const std::vector<armnn::BackendId>& backends,
140 armnn::DataLayout dataLayout)
141 {
142 ResizeEndToEnd<ArmnnType>(backends, dataLayout, armnn::ResizeMethod::NearestNeighbor);
143 }
144