31 #pragma GCC diagnostic push 32 #pragma GCC diagnostic ignored "-Wunused-parameter" 33 #include "libnpy/npy.hpp" 34 #pragma GCC diagnostic pop 44 #include <unordered_map> 53 template <typename T, typename std::enable_if<std::is_integral<T>::value,
int>
::type = 0>
54 void rgb_to_luminance(
const RawTensor &
src, RawTensor &
dst)
57 ARM_COMPUTE_ERROR_ON_MSG(src.num_elements() != dst.num_elements(),
"Input and output images must have equal dimensions");
59 const size_t num_elements = dst.num_elements();
63 for(
size_t i = 0, j = 0; j < num_elements; i += 3, ++j)
65 reinterpret_cast<T *
>(dst.data())[j] = 0.2126f * src.data()[i] + 0.7152f * src.data()[i + 1] + 0.0722f * src.data()[i + 2];
69 void extract_r_from_rgb(
const RawTensor &src, RawTensor &dst)
73 const size_t num_elements = dst.num_elements();
75 for(
size_t i = 0, j = 0; j < num_elements; i += 3, ++j)
77 dst.data()[j] = src.data()[i];
81 void extract_g_from_rgb(
const RawTensor &src, RawTensor &dst)
85 const size_t num_elements = dst.num_elements();
87 for(
size_t i = 1, j = 0; j < num_elements; i += 3, ++j)
89 dst.data()[j] = src.data()[i];
93 void extract_b_from_rgb(
const RawTensor &src, RawTensor &dst)
97 const size_t num_elements = dst.num_elements();
99 for(
size_t i = 2, j = 0; j < num_elements; i += 3, ++j)
101 dst.data()[j] = src.data()[i];
105 void discard_comments(std::ifstream &fs)
107 while(fs.peek() ==
'#')
109 fs.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
113 void discard_comments_and_spaces(std::ifstream &fs)
117 discard_comments(fs);
119 if(isspace(fs.peek()) == 0)
128 std::tuple<unsigned int, unsigned int, int> parse_netpbm_format_header(std::ifstream &fs,
char number)
131 std::array<char, 2> magic_number{ { 0 } };
132 fs >> magic_number[0] >> magic_number[1];
134 if(magic_number[0] !=
'P' || magic_number[1] != number)
136 throw std::runtime_error(
"File type magic number not supported");
139 discard_comments_and_spaces(fs);
141 unsigned int width = 0;
144 discard_comments_and_spaces(fs);
146 unsigned int height = 0;
149 discard_comments_and_spaces(fs);
156 throw std::runtime_error(
"Cannot read image dimensions");
161 throw std::runtime_error(
"RawTensor doesn't have 8-bit values");
164 discard_comments(fs);
166 if(isspace(fs.peek()) == 0)
168 throw std::runtime_error(
"Invalid image header");
173 return std::make_tuple(width, height, max_value);
176 std::tuple<unsigned int, unsigned int, int>
parse_ppm_header(std::ifstream &fs)
178 return parse_netpbm_format_header(fs,
'6');
181 std::tuple<unsigned int, unsigned int, int> parse_pgm_header(std::ifstream &fs)
183 return parse_netpbm_format_header(fs,
'5');
186 void check_image_size(std::ifstream &fs,
size_t raw_size)
188 const size_t current_position = fs.tellg();
190 const size_t end_position = fs.tellg();
191 fs.seekg(current_position, std::ios_base::beg);
193 if((end_position - current_position) < raw_size)
195 throw std::runtime_error(
"Not enough data in file");
199 void read_image_buffer(std::ifstream &fs, RawTensor &raw)
201 fs.read(reinterpret_cast<std::fstream::char_type *>(raw.data()), raw.size());
205 throw std::runtime_error(
"Failure while reading image buffer");
209 RawTensor load_ppm(
const std::string &
path)
211 std::ifstream file(path, std::ios::in | std::ios::binary);
215 throw framework::FileNotFound(
"Could not load PPM image: " + path);
218 unsigned int width = 0;
219 unsigned int height = 0;
225 check_image_size(file, raw.size());
226 read_image_buffer(file, raw);
231 RawTensor load_pgm(
const std::string &path)
233 std::ifstream file(path, std::ios::in | std::ios::binary);
237 throw framework::FileNotFound(
"Could not load PGM image: " + path);
240 unsigned int width = 0;
241 unsigned int height = 0;
243 std::tie(width, height, std::ignore) = parse_pgm_header(file);
245 RawTensor raw(TensorShape(width, height),
Format::U8);
247 check_image_size(file, raw.size());
248 read_image_buffer(file, raw);
255 : _library_path(
std::move(path)),
262 return _library_path;
288 const AssetsLibrary::Loader &AssetsLibrary::get_loader(
const std::string &extension)
const 290 static std::unordered_map<std::string, Loader> loaders =
296 const auto it = loaders.find(extension);
298 if(it != loaders.end())
304 throw std::invalid_argument(
"Cannot load image with extension '" + extension +
"'");
308 const AssetsLibrary::Converter &AssetsLibrary::get_converter(
Format src,
Format dst)
const 310 static std::map<std::pair<Format, Format>, Converter> converters =
318 const auto it = converters.find(std::make_pair(src, dst));
320 if(it != converters.end())
326 std::stringstream msg;
327 msg <<
"Cannot convert from format '" << src <<
"' to format '" << dst <<
"'\n";
328 throw std::invalid_argument(msg.str());
332 const AssetsLibrary::Converter &AssetsLibrary::get_converter(
DataType src,
Format dst)
const 334 static std::map<std::pair<DataType, Format>, Converter> converters = {};
336 const auto it = converters.find(std::make_pair(src, dst));
338 if(it != converters.end())
344 std::stringstream msg;
345 msg <<
"Cannot convert from data type '" << src <<
"' to format '" << dst <<
"'\n";
346 throw std::invalid_argument(msg.str());
350 const AssetsLibrary::Converter &AssetsLibrary::get_converter(
DataType src,
DataType dst)
const 352 static std::map<std::pair<DataType, DataType>, Converter> converters = {};
354 const auto it = converters.find(std::make_pair(src, dst));
356 if(it != converters.end())
362 std::stringstream msg;
363 msg <<
"Cannot convert from data type '" << src <<
"' to data type '" << dst <<
"'\n";
364 throw std::invalid_argument(msg.str());
368 const AssetsLibrary::Converter &AssetsLibrary::get_converter(
Format src,
DataType dst)
const 370 static std::map<std::pair<Format, DataType>, Converter> converters = {};
372 const auto it = converters.find(std::make_pair(src, dst));
374 if(it != converters.end())
380 std::stringstream msg;
381 msg <<
"Cannot convert from format '" << src <<
"' to data type '" << dst <<
"'\n";
382 throw std::invalid_argument(msg.str());
386 const AssetsLibrary::Extractor &AssetsLibrary::get_extractor(
Format format,
Channel channel)
const 388 static std::map<std::pair<Format, Channel>, Extractor> extractors =
395 const auto it = extractors.find(std::make_pair(format, channel));
397 if(it != extractors.end())
403 std::stringstream msg;
404 msg <<
"Cannot extract channel '" << channel <<
"' from format '" << format <<
"'\n";
405 throw std::invalid_argument(msg.str());
409 RawTensor AssetsLibrary::load_image(
const std::string &
name)
const 412 const std::string image_path = (
"\\images\\");
414 const std::string image_path = (
"/images/");
417 const std::string path = _library_path + image_path +
name;
418 const std::string extension = path.substr(path.find_last_of(
'.') + 1);
419 return (*get_loader(extension))(path);
422 const RawTensor &AssetsLibrary::find_or_create_raw_tensor(
const std::string &name,
Format format)
const 424 std::lock_guard<arm_compute::Mutex> guard(_format_lock);
426 const RawTensor *ptr = _cache.
find(std::forward_as_tuple(name, format));
435 if(raw.
format() != format)
439 (*get_converter(raw.
format(), format))(raw,
dst);
440 raw = std::move(dst);
443 return _cache.
add(std::forward_as_tuple(name, format), std::move(raw));
446 const RawTensor &AssetsLibrary::find_or_create_raw_tensor(
const std::string &name,
Format format,
Channel channel)
const 448 std::lock_guard<arm_compute::Mutex> guard(_channel_lock);
450 const RawTensor *ptr = _cache.
find(std::forward_as_tuple(name, format, channel));
461 (*get_extractor(format, channel))(src, dst);
463 return _cache.
add(std::forward_as_tuple(name, format, channel), std::move(dst));
468 return load_image(name).
shape();
492 return find_or_create_raw_tensor(name, format);
497 return RawTensor(find_or_create_raw_tensor(name, format));
512 return find_or_create_raw_tensor(name, format, channel);
517 return RawTensor(find_or_create_raw_tensor(name, format, channel));
527 std::string
header = npy::read_header(stream);
530 std::vector<unsigned long>
shape;
531 bool fortran_order =
false;
533 npy::parse_header(header, typestr, fortran_order, shape);
542 for(
size_t i = 0; i < shape.size(); ++i)
549 for(
size_t i = 0; i < shape.size(); ++i)
Subclass of SimpleTensor using uint8_t as value type.
size_t size() const override
Total size of the tensor in bytes.
std::string path() const
Path to assets directory used to initialise library.
Format get_format_for_channel(Channel channel)
Look up the format corresponding to a channel.
1 channel, 1 U8 per channel
Format format() const override
Image format of the tensor.
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
void validate_npy_header(std::ifstream &stream, const std::string &expect_typestr, const TensorShape &expect_shape)
1 channel, 1 U16 per channel
TensorShape shape() const override
Shape of the tensor.
decltype(strategy::transforms) typedef type
TensorShape get_image_shape(const std::string &name)
Provides a tensor shape for the specified image.
const RawTensor & get(const std::string &name) const
Provides a constant raw tensor for the specified image.
SimpleTensor< float > src
Copyright (c) 2017-2021 Arm Limited.
3 channels, 1 U8 per channel
Format get_channel_format(Channel channel)
Return the format of a channel.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
1 channel, 1 U32 per channel
Channel
Available channels.
Format
Image colour formats.
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
void fill(T &&tensor, D &&distribution, std::random_device::result_type seed_offset) const
Fills the specified tensor with random values drawn from distribution.
void end(TokenStream &in, bool &valid)
1 channel, 1 S16 per channel
RawTensor & add(std::tuple< const std::string &, Format > key, RawTensor raw)
Add the given tensor to the cache.
RawTensor * find(std::tuple< const std::string &, Format > key)
Search the cache for a tensor of created from the specified image and format.
unsigned int num_dimensions() const
Returns the effective dimensionality of the tensor.
std::tuple< unsigned int, unsigned int, int > parse_ppm_header(std::ifstream &fs)
Parse the ppm header from an input file stream.
DataType
Available data types.
void header(TokenStream &in, bool &valid)
AssetsLibrary(std::string path, std::random_device::result_type seed)
Initialises the library with a path to the assets directory.
std::random_device::result_type seed() const
Seed that is used to fill tensors with random values.
const T * data() const
Constant pointer to the underlying buffer.