Compute Library
 21.08
Utils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "Utils.h"
25 
26 #ifdef ARM_COMPUTE_CL
29 #endif /* ARM_COMPUTE_CL */
30 
31 #include <cctype>
32 #include <cerrno>
33 #include <iomanip>
34 #include <string>
35 
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wswitch-default"
38 #pragma GCC diagnostic ignored "-Wunused-parameter"
39 #pragma GCC diagnostic ignored "-Wstrict-overflow"
40 #if (defined(__GNUC__) && (__GNUC__ >= 7))
41 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
42 #endif // (defined(__GNUC__) && (__GNUC__ >= 7))
43 #if defined(__clang__)
44 #pragma GCC diagnostic ignored "-Wparentheses-equality"
45 #endif // defined(__clang__)
46 #define STB_IMAGE_IMPLEMENTATION
47 #include "stb/stb_image.h"
48 #pragma GCC diagnostic pop
49 
50 namespace arm_compute
51 {
52 namespace utils
53 {
54 namespace
55 {
56 /* Advance the iterator to the first character which is not a comment
57  *
58  * @param[in,out] fs Stream to drop comments from
59  */
60 void discard_comments(std::ifstream &fs)
61 {
62  while(fs.peek() == '#')
63  {
64  fs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
65  }
66 }
67 
68 /* Advance the string iterator to the next character which is neither a space or a comment
69  *
70  * @param[in,out] fs Stream to drop comments from
71  */
72 void discard_comments_and_spaces(std::ifstream &fs)
73 {
74  while(true)
75  {
76  discard_comments(fs);
77 
78  if(isspace(fs.peek()) == 0)
79  {
80  break;
81  }
82 
83  fs.ignore(1);
84  }
85 }
86 } // namespace
87 
88 #ifndef BENCHMARK_EXAMPLES
89 int run_example(int argc, char **argv, std::unique_ptr<Example> example)
90 {
91  std::cout << "\n"
92  << argv[0] << "\n\n";
93 
94  try
95  {
96  bool status = example->do_setup(argc, argv);
97  if(!status)
98  {
99  return 1;
100  }
101  example->do_run();
102  example->do_teardown();
103 
104  std::cout << "\nTest passed\n";
105  return 0;
106  }
107 #ifdef ARM_COMPUTE_CL
108  catch(cl::Error &err)
109  {
110  std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
111  std::cerr << std::endl
112  << "ERROR " << err.what() << "(" << err.err() << ")" << std::endl;
113  std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
114  }
115 #endif /* ARM_COMPUTE_CL */
116  catch(std::runtime_error &err)
117  {
118  std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
119  std::cerr << std::endl
120  << "ERROR " << err.what() << " " << (errno ? strerror(errno) : "") << std::endl;
121  std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
122  }
123 
124  std::cout << "\nTest FAILED\n";
125 
126  return -1;
127 }
128 #endif /* BENCHMARK_EXAMPLES */
129 
130 void draw_detection_rectangle(ITensor *tensor, const DetectionWindow &rect, uint8_t r, uint8_t g, uint8_t b)
131 {
133 
134  uint8_t *top = tensor->info()->offset_element_in_bytes(Coordinates(rect.x, rect.y)) + tensor->buffer();
135  uint8_t *bottom = tensor->info()->offset_element_in_bytes(Coordinates(rect.x, rect.y + rect.height)) + tensor->buffer();
136  uint8_t *left = top;
137  uint8_t *right = tensor->info()->offset_element_in_bytes(Coordinates(rect.x + rect.width, rect.y)) + tensor->buffer();
138  size_t stride = tensor->info()->strides_in_bytes()[Window::DimY];
139 
140  for(size_t x = 0; x < rect.width; ++x)
141  {
142  top[0] = r;
143  top[1] = g;
144  top[2] = b;
145  bottom[0] = r;
146  bottom[1] = g;
147  bottom[2] = b;
148 
149  top += 3;
150  bottom += 3;
151  }
152 
153  for(size_t y = 0; y < rect.height; ++y)
154  {
155  left[0] = r;
156  left[1] = g;
157  left[2] = b;
158  right[0] = r;
159  right[1] = g;
160  right[2] = b;
161 
162  left += stride;
163  right += stride;
164  }
165 }
166 
167 ImageType get_image_type_from_file(const std::string &filename)
168 {
170 
171  try
172  {
173  // Open file
174  std::ifstream fs;
175  fs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
176  fs.open(filename, std::ios::in | std::ios::binary);
177 
178  // Identify type from magic number
179  std::array<unsigned char, 2> magic_number{ { 0 } };
180  fs >> magic_number[0] >> magic_number[1];
181 
182  // PPM check
183  if(static_cast<char>(magic_number[0]) == 'P' && static_cast<char>(magic_number[1]) == '6')
184  {
185  type = ImageType::PPM;
186  }
187  else if(magic_number[0] == 0xFF && magic_number[1] == 0xD8)
188  {
189  type = ImageType::JPEG;
190  }
191 
192  fs.close();
193  }
194  catch(std::runtime_error &e)
195  {
196  ARM_COMPUTE_ERROR_VAR("Accessing %s: %s", filename.c_str(), e.what());
197  }
198 
199  return type;
200 }
201 
202 std::tuple<unsigned int, unsigned int, int> parse_ppm_header(std::ifstream &fs)
203 {
204  // Check the PPM magic number is valid
205  std::array<char, 2> magic_number{ { 0 } };
206  fs >> magic_number[0] >> magic_number[1];
207  ARM_COMPUTE_ERROR_ON_MSG(magic_number[0] != 'P' || magic_number[1] != '6', "Invalid file type");
208  ARM_COMPUTE_UNUSED(magic_number);
209 
210  discard_comments_and_spaces(fs);
211 
212  unsigned int width = 0;
213  fs >> width;
214 
215  discard_comments_and_spaces(fs);
216 
217  unsigned int height = 0;
218  fs >> height;
219 
220  discard_comments_and_spaces(fs);
221 
222  int max_val = 0;
223  fs >> max_val;
224 
225  discard_comments(fs);
226 
227  ARM_COMPUTE_ERROR_ON_MSG(isspace(fs.peek()) == 0, "Invalid PPM header");
228  fs.ignore(1);
229 
230  return std::make_tuple(width, height, max_val);
231 }
232 
233 std::tuple<std::vector<unsigned long>, bool, std::string> parse_npy_header(std::ifstream &fs) //NOLINT
234 {
235  std::vector<unsigned long> shape; // NOLINT
236 
237  // Read header
238  std::string header = npy::read_header(fs);
239 
240  // Parse header
241  bool fortran_order = false;
242  std::string typestr;
243  npy::parse_header(header, typestr, fortran_order, shape);
244 
245  std::reverse(shape.begin(), shape.end());
246 
247  return std::make_tuple(shape, fortran_order, typestr);
248 }
249 
250 /** This function returns the amount of memory free reading from /proc/meminfo
251  *
252  * @return The free memory in kB
253  */
255 {
256  std::string line_attribute;
257  std::ifstream file_meminfo("/proc/meminfo");
258 
259  if(file_meminfo.is_open())
260  {
261  while(!(file_meminfo >> line_attribute).fail())
262  {
263  //Test if is the line containing MemFree
264  if(line_attribute == "MemFree:")
265  {
266  uint64_t mem_available;
267  if(!(file_meminfo >> mem_available).fail())
268  {
269  return mem_available;
270  }
271  else
272  {
273  return 0;
274  }
275  }
276  // if it's not MemFree ignore rest of the line
277  file_meminfo.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
278  }
279  }
280  // Nothing found or an error during opening the file
281  return 0;
282 }
283 } // namespace utils
284 } // namespace arm_compute
SimpleTensor< T > reverse(const SimpleTensor< T > &src, const SimpleTensor< uint32_t > &axis)
Definition: Reverse.cpp:38
int run_example(int argc, char **argv, std::unique_ptr< Example > example)
Run an example and handle the potential exceptions it throws.
Definition: RunExample.cpp:94
uint64_t get_mem_free_from_meminfo()
This function returns the amount of memory free reading from /proc/meminfo.
Definition: Utils.cpp:254
uint16_t x
Top-left x coordinate.
Definition: Types.h:517
virtual int32_t offset_element_in_bytes(const Coordinates &pos) const =0
The offset in bytes from the beginning of the memory allocation to access the element at position (x...
SimpleTensor< float > b
Definition: DFT.cpp:157
#define ARM_COMPUTE_ERROR_VAR(msg,...)
Print the given message then throw an std::runtime_error.
Definition: Error.h:346
Manages all the OpenCL kernels compilation and caching, provides accessors for the OpenCL Context...
#define ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(t,...)
Definition: Validate.h:639
decltype(strategy::transforms) typedef type
Interface for CPU tensor.
Definition: ITensor.h:36
Copyright (c) 2017-2021 Arm Limited.
3 channels, 1 U8 per channel
Interface to enqueue OpenCL kernels and get/set the OpenCL CommandQueue and ICLTuner.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
uint16_t width
Width of the detection window.
Definition: Types.h:519
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
Coordinates of an item.
Definition: Coordinates.h:37
virtual uint8_t * buffer() const =0
Interface to be implemented by the child class to return a pointer to CPU memory. ...
std::tuple< std::vector< unsigned long >, bool, std::string > parse_npy_header(std::ifstream &fs)
Parse the npy header from an input file stream.
Definition: Utils.cpp:233
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor&#39;s metadata.
uint16_t height
Height of the detection window.
Definition: Types.h:520
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
Detection window used for the object detection.
Definition: Types.h:515
void draw_detection_rectangle(ITensor *tensor, const DetectionWindow &rect, uint8_t r, uint8_t g, uint8_t b)
Draw a RGB rectangular window for the detected object.
Definition: Utils.cpp:130
ImageType
Supported image types.
Definition: Utils.h:63
uint16_t y
Top-left y coordinate.
Definition: Types.h:518
std::tuple< unsigned int, unsigned int, int > parse_ppm_header(std::ifstream &fs)
Parse the ppm header from an input file stream.
Definition: Utils.cpp:202
ImageType get_image_type_from_file(const std::string &filename)
Gets image type given a file.
Definition: Utils.cpp:167
virtual const Strides & strides_in_bytes() const =0
The strides in bytes for accessing each dimension of the tensor.
void header(TokenStream &in, bool &valid)
Definition: MLGOParser.cpp:481