From 44ec2e7c1edd57eb2fb2674a28452aac02bd8c0a Mon Sep 17 00:00:00 2001 From: Gian Marco Date: Thu, 19 Oct 2017 14:13:38 +0100 Subject: COMPMID-639 - Add PPMAccessor and TopNPredictionsAccessor in graph_utils Change-Id: I40c3e2dfcde10c65ed9c86f9283a53f9e679d4fa Reviewed-on: http://mpd-gerrit.cambridge.arm.com/92437 Reviewed-by: Anthony Barbier Tested-by: Kaizen --- utils/GraphUtils.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 11 deletions(-) (limited to 'utils/GraphUtils.cpp') diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp index bdd831075d..bcfc0f7994 100644 --- a/utils/GraphUtils.cpp +++ b/utils/GraphUtils.cpp @@ -34,8 +34,10 @@ #include "arm_compute/core/PixelValue.h" #include "libnpy/npy.hpp" +#include +#include +#include #include -#include using namespace arm_compute::graph_utils; @@ -48,16 +50,8 @@ bool PPMWriter::access_tensor(ITensor &tensor) { std::stringstream ss; ss << _name << _iterator << ".ppm"; - if(dynamic_cast(&tensor) != nullptr) - { - arm_compute::utils::save_to_ppm(dynamic_cast(tensor), ss.str()); - } -#ifdef ARM_COMPUTE_CL - else if(dynamic_cast(&tensor) != nullptr) - { - arm_compute::utils::save_to_ppm(dynamic_cast(tensor), ss.str()); - } -#endif /* ARM_COMPUTE_CL */ + + arm_compute::utils::save_to_ppm(tensor, ss.str()); _iterator++; if(_maximum == 0) @@ -87,6 +81,101 @@ bool DummyAccessor::access_tensor(ITensor &tensor) return ret; } +PPMAccessor::PPMAccessor(const std::string &ppm_path, bool bgr, float mean_r, float mean_g, float mean_b) + : _ppm_path(ppm_path), _bgr(bgr), _mean_r(mean_r), _mean_g(mean_g), _mean_b(mean_b) +{ +} + +bool PPMAccessor::access_tensor(ITensor &tensor) +{ + utils::PPMLoader ppm; + const float mean[3] = + { + _bgr ? _mean_b : _mean_r, + _mean_g, + _bgr ? _mean_r : _mean_b + }; + + // Open PPM file + ppm.open(_ppm_path); + + // Fill the tensor with the PPM content (BGR) + ppm.fill_planar_tensor(tensor, _bgr); + + // Subtract the mean value from each channel + Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const Coordinates & id) + { + const float value = *reinterpret_cast(tensor.ptr_to_element(id)) - mean[id.z()]; + *reinterpret_cast(tensor.ptr_to_element(id)) = value; + }); + + return true; +} + +TopNPredictionsAccessor::TopNPredictionsAccessor(const std::string &labels_path, size_t top_n, std::ostream &output_stream) + : _labels(), _output_stream(output_stream), _top_n(top_n) +{ + _labels.clear(); + + std::ifstream ifs; + + try + { + ifs.exceptions(std::ifstream::badbit); + ifs.open(labels_path, std::ios::in | std::ios::binary); + + for(std::string line; !std::getline(ifs, line).fail();) + { + _labels.emplace_back(line); + } + } + catch(const std::ifstream::failure &e) + { + ARM_COMPUTE_ERROR("Accessing %s: %s", labels_path.c_str(), e.what()); + } +} + +bool TopNPredictionsAccessor::access_tensor(ITensor &tensor) +{ + ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&tensor, 1, DataType::F32); + ARM_COMPUTE_ERROR_ON(_labels.size() != tensor.info()->dimension(0)); + + // Get the predicted class + std::vector classes_prob; + std::vector index; + + const auto output_net = reinterpret_cast(tensor.buffer() + tensor.info()->offset_first_element_in_bytes()); + const size_t num_classes = tensor.info()->dimension(0); + + classes_prob.resize(num_classes); + index.resize(num_classes); + + std::copy(output_net, output_net + num_classes, classes_prob.begin()); + + // Sort results + std::iota(std::begin(index), std::end(index), static_cast(0)); + std::sort(std::begin(index), std::end(index), + [&](size_t a, size_t b) + { + return classes_prob[a] > classes_prob[b]; + }); + + _output_stream << "---------- Top " << _top_n << " predictions ----------" << std::endl + << std::endl; + for(size_t i = 0; i < _top_n; ++i) + { + _output_stream << std::fixed << std::setprecision(4) + << classes_prob[index.at(i)] + << " - [id = " << index.at(i) << "]" + << ", " << _labels[index.at(i)] << std::endl; + } + + return false; +} + RandomAccessor::RandomAccessor(PixelValue lower, PixelValue upper, std::random_device::result_type seed) : _lower(lower), _upper(upper), _seed(seed) { -- cgit v1.2.1