blob: 754e7d07347c1a34734a99b2cf258d228a8240a8 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2019 Arm Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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
Pablo Tellocf9c8432019-07-22 17:36:03 +010026#ifdef ARM_COMPUTE_CL
Pablo Tellodb8485a2019-09-24 11:03:47 +010027#include "arm_compute/core/CL/CLKernelLibrary.h"
Pablo Tellodb9116f2019-07-11 16:50:37 +010028#include "arm_compute/runtime/CL/CLScheduler.h"
Pablo Tellocf9c8432019-07-22 17:36:03 +010029#endif /* ARM_COMPUTE_CL */
Pablo Tellodb9116f2019-07-11 16:50:37 +010030
Anthony Barbier6ff3b192017-09-04 18:44:23 +010031#include <cctype>
32#include <cerrno>
33#include <iomanip>
34#include <string>
35
Anthony Barbier1c28ab42018-08-29 11:22:33 +010036#pragma GCC diagnostic push
37#pragma GCC diagnostic ignored "-Wswitch-default"
Michalis Spyrou6bff1952019-10-02 17:22:11 +010038#pragma GCC diagnostic ignored "-Wunused-parameter"
Michalis Spyroufae513c2019-10-16 17:41:33 +010039#pragma GCC diagnostic ignored "-Wstrict-overflow"
Anthony Barbier1c28ab42018-08-29 11:22:33 +010040#define STB_IMAGE_IMPLEMENTATION
41#include "stb/stb_image.h"
42#pragma GCC diagnostic pop
43
Anthony Barbier6ff3b192017-09-04 18:44:23 +010044namespace arm_compute
45{
46namespace utils
47{
48namespace
49{
50/* Advance the iterator to the first character which is not a comment
51 *
52 * @param[in,out] fs Stream to drop comments from
53 */
54void discard_comments(std::ifstream &fs)
55{
56 while(fs.peek() == '#')
57 {
58 fs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
59 }
60}
61
62/* Advance the string iterator to the next character which is neither a space or a comment
63 *
64 * @param[in,out] fs Stream to drop comments from
65 */
66void discard_comments_and_spaces(std::ifstream &fs)
67{
68 while(true)
69 {
70 discard_comments(fs);
71
72 if(isspace(fs.peek()) == 0)
73 {
74 break;
75 }
76
77 fs.ignore(1);
78 }
79}
80} // namespace
81
Anthony Barbier6db0ff52018-01-05 10:59:12 +000082#ifndef BENCHMARK_EXAMPLES
Anthony Barbier9fb0cac2018-04-20 15:46:21 +010083int run_example(int argc, char **argv, std::unique_ptr<Example> example)
Anthony Barbier6db0ff52018-01-05 10:59:12 +000084{
85 std::cout << "\n"
86 << argv[0] << "\n\n";
87
88 try
89 {
Georgios Pinitas12be7ab2018-07-03 12:06:23 +010090 bool status = example->do_setup(argc, argv);
91 if(!status)
92 {
93 return 1;
94 }
Anthony Barbier9fb0cac2018-04-20 15:46:21 +010095 example->do_run();
96 example->do_teardown();
Anthony Barbier6db0ff52018-01-05 10:59:12 +000097
98 std::cout << "\nTest passed\n";
99 return 0;
100 }
101#ifdef ARM_COMPUTE_CL
102 catch(cl::Error &err)
103 {
104 std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
105 std::cerr << std::endl
106 << "ERROR " << err.what() << "(" << err.err() << ")" << std::endl;
107 std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
108 }
109#endif /* ARM_COMPUTE_CL */
110 catch(std::runtime_error &err)
111 {
112 std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
113 std::cerr << std::endl
114 << "ERROR " << err.what() << " " << (errno ? strerror(errno) : "") << std::endl;
115 std::cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
116 }
117
118 std::cout << "\nTest FAILED\n";
119
120 return -1;
121}
122#endif /* BENCHMARK_EXAMPLES */
123
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100124void draw_detection_rectangle(ITensor *tensor, const DetectionWindow &rect, uint8_t r, uint8_t g, uint8_t b)
125{
126 ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(tensor, Format::RGB888);
127
128 uint8_t *top = tensor->info()->offset_element_in_bytes(Coordinates(rect.x, rect.y)) + tensor->buffer();
129 uint8_t *bottom = tensor->info()->offset_element_in_bytes(Coordinates(rect.x, rect.y + rect.height)) + tensor->buffer();
130 uint8_t *left = top;
131 uint8_t *right = tensor->info()->offset_element_in_bytes(Coordinates(rect.x + rect.width, rect.y)) + tensor->buffer();
132 size_t stride = tensor->info()->strides_in_bytes()[Window::DimY];
133
134 for(size_t x = 0; x < rect.width; ++x)
135 {
136 top[0] = r;
137 top[1] = g;
138 top[2] = b;
139 bottom[0] = r;
140 bottom[1] = g;
141 bottom[2] = b;
142
143 top += 3;
144 bottom += 3;
145 }
146
147 for(size_t y = 0; y < rect.height; ++y)
148 {
149 left[0] = r;
150 left[1] = g;
151 left[2] = b;
152 right[0] = r;
153 right[1] = g;
154 right[2] = b;
155
156 left += stride;
157 right += stride;
158 }
159}
160
Georgios Pinitas12be7ab2018-07-03 12:06:23 +0100161ImageType get_image_type_from_file(const std::string &filename)
162{
163 ImageType type = ImageType::UNKNOWN;
164
165 try
166 {
167 // Open file
168 std::ifstream fs;
169 fs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
170 fs.open(filename, std::ios::in | std::ios::binary);
171
172 // Identify type from magic number
173 std::array<unsigned char, 2> magic_number{ { 0 } };
174 fs >> magic_number[0] >> magic_number[1];
175
176 // PPM check
177 if(static_cast<char>(magic_number[0]) == 'P' && static_cast<char>(magic_number[1]) == '6')
178 {
179 type = ImageType::PPM;
180 }
181 else if(magic_number[0] == 0xFF && magic_number[1] == 0xD8)
182 {
183 type = ImageType::JPEG;
184 }
185
186 fs.close();
187 }
188 catch(std::runtime_error &e)
189 {
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100190 ARM_COMPUTE_ERROR_VAR("Accessing %s: %s", filename.c_str(), e.what());
Georgios Pinitas12be7ab2018-07-03 12:06:23 +0100191 }
192
193 return type;
194}
195
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100196std::tuple<unsigned int, unsigned int, int> parse_ppm_header(std::ifstream &fs)
197{
198 // Check the PPM magic number is valid
199 std::array<char, 2> magic_number{ { 0 } };
200 fs >> magic_number[0] >> magic_number[1];
201 ARM_COMPUTE_ERROR_ON_MSG(magic_number[0] != 'P' || magic_number[1] != '6', "Invalid file type");
202 ARM_COMPUTE_UNUSED(magic_number);
203
204 discard_comments_and_spaces(fs);
205
206 unsigned int width = 0;
207 fs >> width;
208
209 discard_comments_and_spaces(fs);
210
211 unsigned int height = 0;
212 fs >> height;
213
214 discard_comments_and_spaces(fs);
215
216 int max_val = 0;
217 fs >> max_val;
218
219 discard_comments(fs);
220
221 ARM_COMPUTE_ERROR_ON_MSG(isspace(fs.peek()) == 0, "Invalid PPM header");
222 fs.ignore(1);
223
224 return std::make_tuple(width, height, max_val);
225}
Giorgio Arenacf3935f2017-10-26 17:14:13 +0100226
227std::tuple<std::vector<unsigned long>, bool, std::string> parse_npy_header(std::ifstream &fs) //NOLINT
228{
229 std::vector<unsigned long> shape; // NOLINT
230
Giorgio Arenacf3935f2017-10-26 17:14:13 +0100231 // Read header
Anthony Barbier87f21cd2017-11-10 16:27:32 +0000232 std::string header = npy::read_header(fs);
Giorgio Arenacf3935f2017-10-26 17:14:13 +0100233
234 // Parse header
235 bool fortran_order = false;
236 std::string typestr;
Anthony Barbier87f21cd2017-11-10 16:27:32 +0000237 npy::parse_header(header, typestr, fortran_order, shape);
Giorgio Arenacf3935f2017-10-26 17:14:13 +0100238
Michalis Spyrou39412952018-08-14 17:06:16 +0100239 std::reverse(shape.begin(), shape.end());
Giorgio Arenacf3935f2017-10-26 17:14:13 +0100240
241 return std::make_tuple(shape, fortran_order, typestr);
242}
Gian Marco5ca74092018-02-08 16:21:54 +0000243
244/** This function returns the amount of memory free reading from /proc/meminfo
245 *
246 * @return The free memory in kB
247 */
248uint64_t get_mem_free_from_meminfo()
249{
250 std::string line_attribute;
251 std::ifstream file_meminfo("/proc/meminfo");
252
253 if(file_meminfo.is_open())
254 {
255 while(!(file_meminfo >> line_attribute).fail())
256 {
257 //Test if is the line containing MemFree
258 if(line_attribute == "MemFree:")
259 {
260 uint64_t mem_available;
261 if(!(file_meminfo >> mem_available).fail())
262 {
263 return mem_available;
264 }
265 else
266 {
267 return 0;
268 }
269 }
270 // if it's not MemFree ignore rest of the line
271 file_meminfo.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
272 }
273 }
274 // Nothing found or an error during opening the file
275 return 0;
276}
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100277} // namespace utils
278} // namespace arm_compute