32 #pragma GCC diagnostic push 33 #pragma GCC diagnostic ignored "-Wunused-parameter" 35 #pragma GCC diagnostic pop 36 #include "utils/Utils.h" 53 if(
shape.num_dimensions() > 2)
61 return std::make_pair(permuted_shape, perm);
66 : _min_range(min_range), _max_range(max_range)
73 preprocess_typed<float>(tensor);
77 preprocess_typed<half>(tensor);
86 void TFPreproccessor::preprocess_typed(
ITensor &tensor)
91 const float range = _max_range - _min_range;
95 float res = value / 255.f;
96 res = res *
range + _min_range;
102 : _mean(mean), _bgr(bgr), _scale(
scale)
114 preprocess_typed<float>(tensor);
118 preprocess_typed<half>(tensor);
126 template <
typename T>
127 void CaffePreproccessor::preprocess_typed(
ITensor &tensor)
135 const T value = *reinterpret_cast<T *>(tensor.
ptr_to_element(
id)) - T(_mean[
id[channel_idx]]);
136 *reinterpret_cast<T *>(tensor.
ptr_to_element(
id)) = value * T(_scale);
141 : _name(std::move(
name)), _iterator(0), _maximum(maximum)
147 std::stringstream
ss;
148 ss << _name << _iterator <<
".ppm";
157 return _iterator < _maximum;
161 : _iterator(0), _maximum(maximum)
168 bool ret = _maximum == 0 || _iterator < _maximum;
169 if(_iterator == _maximum)
181 : _npy_tensor(), _filename(std::move(npy_path)), _output_stream(output_stream)
194 template <
typename T>
195 void NumPyAccessor::access_numpy_tensor(
ITensor &tensor, T tolerance)
198 int num_mismatches = utils::compare_tensor<T>(tensor, _npy_tensor, tolerance);
199 float percentage_mismatches = static_cast<float>(num_mismatches) / num_elements;
201 _output_stream <<
"Results: " << 100.f - (percentage_mismatches * 100) <<
" % matches with the provided output[" << _filename <<
"]." << std::endl;
202 _output_stream <<
" " << num_elements - num_mismatches <<
" out of " << num_elements <<
" matches with the provided output[" << _filename <<
"]." << std::endl
214 access_numpy_tensor<qasymm8_t>(tensor, 0);
217 access_numpy_tensor<float>(tensor, 0.0001f);
226 #ifdef ARM_COMPUTE_ASSERTS_ENABLED 228 : _output_stream(output_stream), _io_fmt(io_fmt)
234 tensor.
print(_output_stream, _io_fmt);
240 : _npy_name(std::move(npy_name)), _is_fortran(is_fortran)
254 : _already_loaded(false), _filename(std::move(filename)), _bgr(bgr), _preprocessor(std::move(preprocessor))
266 image_loader->open(_filename);
278 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu32
",%" PRIu32
"].",
279 image_loader->width(), image_loader->height(), permuted_shape.
x(), permuted_shape.
y());
282 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu64
",%" PRIu64
"].",
283 image_loader->width(), image_loader->height(),
284 static_cast<uint64_t>(permuted_shape.
x()), static_cast<uint64_t>(permuted_shape.
y()));
288 image_loader->fill_planar_tensor(tensor, _bgr);
293 _preprocessor->preprocess(tensor);
297 _already_loaded = !_already_loaded;
298 return _already_loaded;
302 std::string images_path,
303 std::unique_ptr<IPreprocessor> preprocessor,
307 std::ostream &output_stream)
308 : _path(std::move(images_path)), _images(), _preprocessor(std::move(preprocessor)), _bgr(bgr), _offset(0), _output_stream(output_stream)
315 ifs.exceptions(std::ifstream::badbit);
316 ifs.open(image_list, std::ios::in | std::ios::binary);
319 unsigned int counter = 0;
320 for(std::string line; !std::getline(ifs, line).fail() && counter <=
end; ++counter)
325 std::stringstream linestream(line);
326 std::string image_name;
328 linestream >> image_name;
329 _images.emplace_back(std::move(image_name));
333 catch(
const std::ifstream::failure &e)
341 bool ret = _offset < _images.size();
347 std::string image_name = _path + _images[_offset++];
348 jpeg.
open(image_name);
349 _output_stream <<
"[" << _offset <<
"/" << _images.size() <<
"] Validating " << image_name << std::endl;
356 std::tie(permuted_shape, perm) = compute_permutation_parameters(tensor.
info()->
tensor_shape(),
362 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu32
",%" PRIu32
"].",
363 jpeg.
width(), jpeg.
height(), permuted_shape.
x(), permuted_shape.
y());
366 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu64
",%" PRIu64
"].",
368 static_cast<uint64_t>(permuted_shape.
x()), static_cast<uint64_t>(permuted_shape.
y()));
377 _preprocessor->preprocess(tensor);
385 std::ostream &output_stream,
388 : _results(), _output_stream(output_stream), _offset(0), _positive_samples_top1(0), _positive_samples_top5(0)
395 ifs.exceptions(std::ifstream::badbit);
396 ifs.open(image_list, std::ios::in | std::ios::binary);
399 unsigned int counter = 0;
400 for(std::string line; !std::getline(ifs, line).fail() && counter <=
end; ++counter)
405 std::stringstream linestream(line);
406 std::string image_name;
409 linestream >> image_name >> result;
410 _results.emplace_back(result);
414 catch(
const std::ifstream::failure &e)
423 _positive_samples_top1 = 0;
424 _positive_samples_top5 = 0;
429 bool ret = _offset < _results.size();
433 std::vector<size_t> tensor_results;
437 tensor_results = access_predictions_tensor<uint8_t>(tensor);
440 tensor_results = access_predictions_tensor<half>(tensor);
443 tensor_results = access_predictions_tensor<float>(tensor);
450 size_t correct_label = _results[_offset++];
452 aggregate_sample(tensor_results, _positive_samples_top1, 1, correct_label);
453 aggregate_sample(tensor_results, _positive_samples_top5, 5, correct_label);
457 if(_offset >= _results.size())
459 report_top_n(1, _results.size(), _positive_samples_top1);
460 report_top_n(5, _results.size(), _positive_samples_top5);
466 template <
typename T>
467 std::vector<size_t> ValidationOutputAccessor::access_predictions_tensor(
arm_compute::ITensor &tensor)
470 std::vector<size_t> index;
475 index.resize(num_classes);
478 std::iota(std::begin(index),
std::end(index), static_cast<size_t>(0));
479 std::sort(std::begin(index),
std::end(index),
480 [&](
size_t a,
size_t b)
482 return output_net[a] > output_net[
b];
488 void ValidationOutputAccessor::aggregate_sample(
const std::vector<size_t> &res,
size_t &positive_samples,
size_t top_n,
size_t correct_label)
490 auto is_valid_label = [correct_label](
size_t label)
492 return label == correct_label;
495 if(std::any_of(std::begin(res), std::begin(res) + top_n, is_valid_label))
501 void ValidationOutputAccessor::report_top_n(
size_t top_n,
size_t total_samples,
size_t positive_samples)
503 size_t negative_samples = total_samples - positive_samples;
504 float accuracy = positive_samples / static_cast<float>(total_samples);
506 _output_stream <<
"----------Top " << top_n <<
" accuracy ----------" << std::endl
508 _output_stream <<
"Positive samples : " << positive_samples << std::endl;
509 _output_stream <<
"Negative samples : " << negative_samples << std::endl;
510 _output_stream <<
"Accuracy : " << accuracy << std::endl;
514 : _labels(), _tensor_shapes(std::move(imgs_tensor_shapes)), _output_stream(output_stream)
522 ifs.exceptions(std::ifstream::badbit);
523 ifs.open(labels_path, std::ios::in | std::ios::binary);
525 for(std::string line; !std::getline(ifs, line).fail();)
527 _labels.emplace_back(line);
530 catch(
const std::ifstream::failure &e)
536 template <
typename T>
537 void DetectionOutputAccessor::access_predictions_tensor(
ITensor &tensor)
542 if(num_detection > 0)
544 _output_stream <<
"---------------------- Detections ----------------------" << std::endl
547 _output_stream << std::left << std::setprecision(4) << std::setw(8) <<
"Image | " << std::setw(8) <<
"Label | " << std::setw(12) <<
"Confidence | " 548 <<
"[ xmin, ymin, xmax, ymax ]" << std::endl;
550 for(
size_t i = 0; i < num_detection; ++i)
552 auto im = static_cast<const int>(output_prt[i * 7]);
553 _output_stream << std::setw(8) << im << std::setw(8)
554 << _labels[output_prt[i * 7 + 1]] << std::setw(12) << output_prt[i * 7 + 2]
555 <<
" [" << (output_prt[i * 7 + 3] * _tensor_shapes[im].x())
556 <<
", " << (output_prt[i * 7 + 4] * _tensor_shapes[im].y())
557 <<
", " << (output_prt[i * 7 + 5] * _tensor_shapes[im].x())
558 <<
", " << (output_prt[i * 7 + 6] * _tensor_shapes[im].y())
564 _output_stream <<
"No detection found." << std::endl;
575 access_predictions_tensor<float>(tensor);
585 : _labels(), _output_stream(output_stream), _top_n(top_n)
593 ifs.exceptions(std::ifstream::badbit);
594 ifs.open(labels_path, std::ios::in | std::ios::binary);
596 for(std::string line; !std::getline(ifs, line).fail();)
598 _labels.emplace_back(line);
601 catch(
const std::ifstream::failure &e)
607 template <
typename T>
608 void TopNPredictionsAccessor::access_predictions_tensor(
ITensor &tensor)
611 std::vector<T> classes_prob;
612 std::vector<size_t> index;
617 classes_prob.resize(num_classes);
618 index.resize(num_classes);
620 std::copy(output_net, output_net + num_classes, classes_prob.begin());
623 std::iota(std::begin(index),
std::end(index), static_cast<size_t>(0));
624 std::sort(std::begin(index),
std::end(index),
625 [&](
size_t a,
size_t b)
627 return classes_prob[a] > classes_prob[
b];
630 _output_stream <<
"---------- Top " << _top_n <<
" predictions ----------" << std::endl
632 for(
size_t i = 0; i < _top_n; ++i)
634 _output_stream << std::fixed << std::setprecision(4)
635 << +classes_prob[index.at(i)]
636 <<
" - [id = " << index.at(i) <<
"]" 637 <<
", " << _labels[index.at(i)] << std::endl;
649 access_predictions_tensor<uint8_t>(tensor);
652 access_predictions_tensor<float>(tensor);
662 : _lower(lower), _upper(upper), _seed(seed)
666 template <
typename T,
typename D>
669 std::mt19937 gen(_seed);
671 if(tensor.
info()->
padding().
empty() && (dynamic_cast<SubTensor *>(&tensor) ==
nullptr))
676 *reinterpret_cast<T *>(tensor.
buffer() +
offset) = value;
700 std::uniform_int_distribution<uint8_t> distribution_u8(_lower.
get<uint8_t>(), _upper.
get<uint8_t>());
701 fill<uint8_t>(tensor, distribution_u8);
706 std::uniform_int_distribution<int8_t> distribution_s8(_lower.
get<int8_t>(), _upper.
get<int8_t>());
707 fill<int8_t>(tensor, distribution_s8);
712 std::uniform_int_distribution<uint16_t> distribution_u16(_lower.
get<uint16_t>(), _upper.
get<uint16_t>());
713 fill<uint16_t>(tensor, distribution_u16);
718 std::uniform_int_distribution<int16_t> distribution_s16(_lower.
get<int16_t>(), _upper.
get<int16_t>());
719 fill<int16_t>(tensor, distribution_s16);
724 std::uniform_int_distribution<uint32_t> distribution_u32(_lower.
get<uint32_t>(), _upper.
get<uint32_t>());
725 fill<uint32_t>(tensor, distribution_u32);
730 std::uniform_int_distribution<int32_t> distribution_s32(_lower.
get<int32_t>(), _upper.
get<int32_t>());
731 fill<int32_t>(tensor, distribution_s32);
736 std::uniform_int_distribution<uint64_t> distribution_u64(_lower.
get<uint64_t>(), _upper.
get<uint64_t>());
737 fill<uint64_t>(tensor, distribution_u64);
742 std::uniform_int_distribution<int64_t> distribution_s64(_lower.
get<int64_t>(), _upper.
get<int64_t>());
743 fill<int64_t>(tensor, distribution_s64);
749 fill<half>(tensor, distribution_f16);
754 std::uniform_real_distribution<float> distribution_f32(_lower.
get<
float>(), _upper.
get<
float>());
755 fill<float>(tensor, distribution_f32);
760 std::uniform_real_distribution<double> distribution_f64(_lower.
get<
double>(), _upper.
get<
double>());
761 fill<double>(tensor, distribution_f64);
771 : _already_loaded(false), _filename(std::move(filename)), _file_layout(file_layout)
780 loader.
open(_filename, _file_layout);
784 _already_loaded = !_already_loaded;
785 return _already_loaded;
SaveNumPyAccessor(const std::string npy_name, const bool is_fortran=false)
Constructor.
ImageAccessor(std::string filename, bool bgr=true, std::unique_ptr< IPreprocessor > preprocessor=nullptr)
Constructor.
__global uchar * offset(const Image *img, int x, int y)
Get the pointer position of a Image.
void save_to_ppm(T &tensor, const std::string &ppm_filename)
Template helper function to save a tensor image to a PPM file.
Class describing the value of a pixel for any image format.
Class to load the content of a JPEG file into an Image.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
uint8_t * ptr_to_element(const Coordinates &id) const
Return a pointer to the element at the passed coordinates.
void init(const TensorAllocator &allocator, const Coordinates &coords, TensorInfo &sub_info)
Shares the same backing memory with another tensor allocator, while the tensor info might be differen...
TensorShape shape
Shape of the valid region.
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
1 channel, 1 U8 per channel
void get(uint8_t &v) const
Interpret the pixel value as a U8.
#define ARM_COMPUTE_EXIT_ON_MSG_VAR(cond, msg,...)
If the condition is true, the given message is printed and program exits.
virtual DataType data_type() const =0
Data type used for each element of the tensor.
void fill_tensor(T &tensor)
Fill a tensor with the content of the currently open NPY file.
1 channel, 1 F32 per channel
Strides PermutationVector
Permutation vector.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
#define ARM_COMPUTE_ERROR_VAR(msg,...)
Print the given message then throw an std::runtime_error.
std::stringstream ss(mlgo_str)
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
const DataLayout data_layout
ValidationOutputAccessor(const std::string &image_list, std::ostream &output_stream=std::cout, unsigned int start=0, unsigned int end=0)
Default Constructor.
static std::unique_ptr< IImageLoader > create(const std::string &filename)
Create an image loader depending on the image type.
1 channel, 1 U16 per channel
void preprocess(ITensor &tensor) override
Preprocess the given tensor.
RandomAccessor(PixelValue lower, PixelValue upper, const std::random_device::result_type seed=0)
Constructor.
SimpleTensor< T > copy(const SimpleTensor< T > &src, const TensorShape &output_shape)
void fill_planar_tensor(T &tensor, bool bgr=false)
Fill a tensor with 3 planes (one for each channel) with the content of the currently open image file.
Interface for CPU tensor.
void use_tensor_dimensions(const TensorShape &shape, size_t first_dimension=Window::DimX)
Use the tensor's dimensions to fill the window dimensions.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
1 channel, 1 F16 per channel
virtual ValidRegion valid_region() const =0
Valid region of the tensor.
TensorAllocator * allocator()
Return a pointer to the tensor's allocator.
ITensorInfo * info() const override
Interface to be implemented by the child class to return the tensor's metadata.
void permute(Dimensions< T > &dimensions, const PermutationVector &perm)
Permutes given Dimensions according to a permutation vector.
1 channel, 1 S32 per channel
T x() const
Alias to access the size of the first dimension.
Numpy Binary loader class.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
#define ARM_COMPUTE_EXIT_ON_MSG(cond, msg)
If the condition is true, the given message is printed and program exits.
DetectionOutputAccessor(const std::string &labels_path, std::vector< TensorShape > &imgs_tensor_shapes, std::ostream &output_stream=std::cout)
Constructor.
void save_to_npy(T &tensor, const std::string &npy_filename, bool fortran_order)
Template helper function to save a tensor image to a NPY file.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
1 channel, 1 U32 per channel
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
SimpleTensor< T > range(SimpleTensor< T > &dst, float start, const size_t num_of_elements, float step)
quantized, asymmetric fixed-point 8-bit number unsigned
unsigned int width() const
Return the width of the currently open image file.
virtual uint8_t * buffer() const =0
Interface to be implemented by the child class to return a pointer to CPU memory.
void allocate() override
Allocate size specified by TensorInfo of CPU memory.
size_t total_size() const
Collapses all dimensions to a single linear total size.
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
virtual size_t element_size() const =0
Element size in bytes calculated as data_size() * num_channels()
void end(TokenStream &in, bool &valid)
virtual PaddingSize padding() const =0
Padding of tensor.
std::uniform_real_distribution< float > distribution(-5.f, 5.f)
NumPyAccessor(std::string npy_path, TensorShape shape, DataType data_type, DataLayout data_layout=DataLayout::NCHW, std::ostream &output_stream=std::cout)
Constructor.
1 channel, 1 S16 per channel
TopNPredictionsAccessor(const std::string &labels_path, size_t top_n=5, std::ostream &output_stream=std::cout)
Constructor.
Num samples, channels, height, width.
#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Strides of an item in bytes.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
virtual size_t offset_first_element_in_bytes() const =0
The offset from the beginning of the memory allocation to the first element of the tensor.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
void preprocess(ITensor &tensor) override
Preprocess the given tensor.
virtual size_t total_size() const =0
Returns the total size of the tensor in bytes.
constexpr bool empty() const
Check if the entire border is zero.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
Num samples, height, width, channels.
TFPreproccessor(float min_range=-1.f, float max_range=1.f)
Constructor.
void open(const std::string &npy_filename, DataLayout file_layout=DataLayout::NCHW)
Open a NPY file and reads its metadata.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
void reset()
Reset accessor state.
Store the tensor's metadata.
DummyAccessor(unsigned int maximum=1)
Constructor.
void execute_window_loop(const Window &w, L &&lambda_function, Ts &&... iterators)
Iterate through the passed window, automatically adjusting the iterators and calling the lambda_funct...
void print(std::ostream &s, IOFormatInfo io_fmt=IOFormatInfo()) const
Print a tensor to a given stream using user defined formatting information.
T y() const
Alias to access the size of the second dimension.
PPMWriter(std::string name, unsigned int maximum=1)
Constructor.
bool access_tensor(ITensor &tensor) override
Interface to be implemented to access a given tensor.
64-bit floating-point number
size_t get_data_layout_dimension_index(const DataLayout data_layout, const DataLayoutDimension data_layout_dimension)
Get the index of the given dimension.
PrintAccessor(std::ostream &output_stream=std::cout, IOFormatInfo io_fmt=IOFormatInfo())
Constructor.
DataType
Available data types.
void swap(Window &lhs, Window &rhs)
NumPyBinLoader(std::string filename, DataLayout file_layout=DataLayout::NCHW)
Default Constructor.
unsigned int height() const
Return the height of the currently open image file.
DataLayout
[DataLayout enum definition]
Describe a multidimensional execution window.
CaffePreproccessor(std::array< float, 3 > mean=std::array< float, 3 > { { 0, 0, 0 } }, bool bgr=true, float scale=1.f)
Default Constructor.
void open(const std::string &filename) override
Open an image file and reads its metadata (Width, height)
virtual DataLayout data_layout() const =0
Get the data layout of the tensor.