ArmNN
 21.05
ImageTensorGenerator.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "../InferenceTestImage.hpp"
7 
8 #include <armnn/TypesUtils.hpp>
9 
10 #include <armnnUtils/Permute.hpp>
11 
12 #include <algorithm>
13 #include <fstream>
14 #include <iterator>
15 #include <string>
16 
17 // Parameters used in normalizing images
19 {
20  float scale{ 1.0 };
21  std::array<float, 3> mean{ { 0.0, 0.0, 0.0 } };
22  std::array<float, 3> stddev{ { 1.0, 1.0, 1.0 } };
23 };
24 
26 {
27  TFLite = 0,
28 };
29 
30 /** Get normalization parameters.
31  * Note that different flavours of models and different model data types have different normalization methods.
32  * This tool currently only supports TF and TFLite models
33  *
34  * @param[in] modelFormat One of the supported frontends
35  * @param[in] outputType Output type of the image tensor, also the type of the intended model
36  */
38  const armnn::DataType& outputType)
39 {
40  NormalizationParameters normParams;
41  // Explicitly set default parameters
42  normParams.scale = 1.0;
43  normParams.mean = { 0.0, 0.0, 0.0 };
44  normParams.stddev = { 1.0, 1.0, 1.0 };
45  switch (modelFormat)
46  {
48  default:
49  switch (outputType)
50  {
52  normParams.scale = 127.5;
53  normParams.mean = { 1.0, 1.0, 1.0 };
54  break;
56  normParams.mean = { 128.0, 128.0, 128.0 };
57  break;
59  default:
60  break;
61  }
62  break;
63  }
64  return normParams;
65 }
66 
67 /** Prepare raw image tensor data by loading the image from imagePath and preprocessing it.
68  *
69  * @param[in] imagePath Path to the image file
70  * @param[in] newWidth The new width of the output image tensor
71  * @param[in] newHeight The new height of the output image tensor
72  * @param[in] normParams Normalization parameters for the normalization of the image
73  * @param[in] batchSize Batch size
74  * @param[in] outputLayout Data layout of the output image tensor
75  */
76 template <typename ElemType>
77 std::vector<ElemType> PrepareImageTensor(const std::string& imagePath,
78  unsigned int newWidth,
79  unsigned int newHeight,
80  const NormalizationParameters& normParams,
81  unsigned int batchSize = 1,
82  const armnn::DataLayout& outputLayout = armnn::DataLayout::NHWC);
83 
84 // Prepare float32 image tensor
85 template <>
86 std::vector<float> PrepareImageTensor<float>(const std::string& imagePath,
87  unsigned int newWidth,
88  unsigned int newHeight,
89  const NormalizationParameters& normParams,
90  unsigned int batchSize,
91  const armnn::DataLayout& outputLayout)
92 {
93  // Generate image tensor
94  std::vector<float> imageData;
95  InferenceTestImage testImage(imagePath.c_str());
96  if (newWidth == 0)
97  {
98  newWidth = testImage.GetWidth();
99  }
100  if (newHeight == 0)
101  {
102  newHeight = testImage.GetHeight();
103  }
104  // Resize the image to new width and height or keep at original dimensions if the new width and height are specified
105  // as 0 Centre/Normalise the image.
106  imageData = testImage.Resize(newWidth, newHeight, CHECK_LOCATION(),
108  normParams.stddev, normParams.scale);
109  if (outputLayout == armnn::DataLayout::NCHW)
110  {
111  // Convert to NCHW format
112  const armnn::PermutationVector NHWCToArmNN = { 0, 2, 3, 1 };
113  armnn::TensorShape dstShape({ batchSize, 3, newHeight, newWidth });
114  std::vector<float> tempImage(imageData.size());
115  armnnUtils::Permute(dstShape, NHWCToArmNN, imageData.data(), tempImage.data(), sizeof(float));
116  imageData.swap(tempImage);
117  }
118  return imageData;
119 }
120 
121 // Prepare int32 image tensor
122 template <>
123 std::vector<int> PrepareImageTensor<int>(const std::string& imagePath,
124  unsigned int newWidth,
125  unsigned int newHeight,
126  const NormalizationParameters& normParams,
127  unsigned int batchSize,
128  const armnn::DataLayout& outputLayout)
129 {
130  // Get float32 image tensor
131  std::vector<float> imageDataFloat =
132  PrepareImageTensor<float>(imagePath, newWidth, newHeight, normParams, batchSize, outputLayout);
133  // Convert to int32 image tensor with static cast
134  std::vector<int> imageDataInt;
135  imageDataInt.reserve(imageDataFloat.size());
136  std::transform(imageDataFloat.begin(), imageDataFloat.end(), std::back_inserter(imageDataInt),
137  [](float val) { return static_cast<int>(val); });
138  return imageDataInt;
139 }
140 
141 // Prepare qasymm8 image tensor
142 template <>
143 std::vector<uint8_t> PrepareImageTensor<uint8_t>(const std::string& imagePath,
144  unsigned int newWidth,
145  unsigned int newHeight,
146  const NormalizationParameters& normParams,
147  unsigned int batchSize,
148  const armnn::DataLayout& outputLayout)
149 {
150  // Get float32 image tensor
151  std::vector<float> imageDataFloat =
152  PrepareImageTensor<float>(imagePath, newWidth, newHeight, normParams, batchSize, outputLayout);
153  std::vector<uint8_t> imageDataQasymm8;
154  imageDataQasymm8.reserve(imageDataFloat.size());
155  // Convert to uint8 image tensor with static cast
156  std::transform(imageDataFloat.begin(), imageDataFloat.end(), std::back_inserter(imageDataQasymm8),
157  [](float val) { return static_cast<uint8_t>(val); });
158  return imageDataQasymm8;
159 }
160 
161 /** Write image tensor to ofstream
162  *
163  * @param[in] imageData Image tensor data
164  * @param[in] imageTensorFile Output filestream (ofstream) to which the image tensor data is written
165  */
166 template <typename ElemType>
167 void WriteImageTensorImpl(const std::vector<ElemType>& imageData, std::ofstream& imageTensorFile)
168 {
169  std::copy(imageData.begin(), imageData.end(), std::ostream_iterator<ElemType>(imageTensorFile, " "));
170 }
171 
172 // For uint8_t image tensor, cast it to int before writing it to prevent writing data as characters instead of
173 // numerical values
174 template <>
175 void WriteImageTensorImpl<uint8_t>(const std::vector<uint8_t>& imageData, std::ofstream& imageTensorFile)
176 {
177  std::copy(imageData.begin(), imageData.end(), std::ostream_iterator<int>(imageTensorFile, " "));
178 }
DataLayout
Definition: Types.hpp:54
std::array< float, 3 > stddev
NormalizationParameters GetNormalizationParameters(const SupportedFrontend &modelFormat, const armnn::DataType &outputType)
Get normalization parameters.
std::vector< ElemType > PrepareImageTensor(const std::string &imagePath, unsigned int newWidth, unsigned int newHeight, const NormalizationParameters &normParams, unsigned int batchSize=1, const armnn::DataLayout &outputLayout=armnn::DataLayout::NHWC)
Prepare raw image tensor data by loading the image from imagePath and preprocessing it...
void WriteImageTensorImpl(const std::vector< ElemType > &imageData, std::ofstream &imageTensorFile)
Write image tensor to ofstream.
std::vector< uint8_t > PrepareImageTensor< uint8_t >(const std::string &imagePath, unsigned int newWidth, unsigned int newHeight, const NormalizationParameters &normParams, unsigned int batchSize, const armnn::DataLayout &outputLayout)
const armnn::PermutationVector NHWCToArmNN
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Permute.cpp:131
DataType
Definition: Types.hpp:36
unsigned int GetWidth() const
void WriteImageTensorImpl< uint8_t >(const std::vector< uint8_t > &imageData, std::ofstream &imageTensorFile)
std::vector< int > PrepareImageTensor< int >(const std::string &imagePath, unsigned int newWidth, unsigned int newHeight, const NormalizationParameters &normParams, unsigned int batchSize, const armnn::DataLayout &outputLayout)
#define CHECK_LOCATION()
Definition: Exceptions.hpp:197
std::array< float, 3 > mean
std::vector< float > PrepareImageTensor< float >(const std::string &imagePath, unsigned int newWidth, unsigned int newHeight, const NormalizationParameters &normParams, unsigned int batchSize, const armnn::DataLayout &outputLayout)