arm_compute v18.08
diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h
index 5977083..3b09c6b 100644
--- a/utils/GraphUtils.h
+++ b/utils/GraphUtils.h
@@ -25,12 +25,15 @@
#define __ARM_COMPUTE_GRAPH_UTILS_H__
#include "arm_compute/core/PixelValue.h"
+#include "arm_compute/core/Utils.h"
#include "arm_compute/core/utils/misc/Utility.h"
#include "arm_compute/graph/Graph.h"
#include "arm_compute/graph/ITensorAccessor.h"
#include "arm_compute/graph/Types.h"
#include "arm_compute/runtime/Tensor.h"
+#include "utils/CommonGraphOptions.h"
+
#include <array>
#include <random>
#include <string>
@@ -150,29 +153,122 @@
std::ostream &_output_stream;
};
-/** PPM accessor class */
-class PPMAccessor final : public graph::ITensorAccessor
+/** Image accessor class */
+class ImageAccessor final : public graph::ITensorAccessor
{
public:
/** Constructor
*
- * @param[in] ppm_path Path to PPM file
- * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false)
- * @param[in] preprocessor (Optional) PPM pre-processing object
+ * @param[in] filename Image file
+ * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false - RGB format)
+ * @param[in] preprocessor (Optional) Image pre-processing object
*/
- PPMAccessor(std::string ppm_path, bool bgr = true, std::unique_ptr<IPreprocessor> preprocessor = nullptr);
+ ImageAccessor(std::string filename, bool bgr = true, std::unique_ptr<IPreprocessor> preprocessor = nullptr);
/** Allow instances of this class to be move constructed */
- PPMAccessor(PPMAccessor &&) = default;
+ ImageAccessor(ImageAccessor &&) = default;
// Inherited methods overriden:
bool access_tensor(ITensor &tensor) override;
private:
- const std::string _ppm_path;
+ bool _already_loaded;
+ const std::string _filename;
const bool _bgr;
std::unique_ptr<IPreprocessor> _preprocessor;
};
+/** Input Accessor used for network validation */
+class ValidationInputAccessor final : public graph::ITensorAccessor
+{
+public:
+ /** Constructor
+ *
+ * @param[in] image_list File containing all the images to validate
+ * @param[in] images_path Path to images.
+ * @param[in] bgr (Optional) Fill the first plane with blue channel (default = false - RGB format)
+ * @param[in] preprocessor (Optional) Image pre-processing object (default = nullptr)
+ * @param[in] start (Optional) Start range
+ * @param[in] end (Optional) End range
+ * @param[out] output_stream (Optional) Output stream
+ *
+ * @note Range is defined as [start, end]
+ */
+ ValidationInputAccessor(const std::string &image_list,
+ std::string images_path,
+ std::unique_ptr<IPreprocessor> preprocessor = nullptr,
+ bool bgr = true,
+ unsigned int start = 0,
+ unsigned int end = 0,
+ std::ostream &output_stream = std::cout);
+
+ // Inherited methods overriden:
+ bool access_tensor(ITensor &tensor) override;
+
+private:
+ std::string _path;
+ std::vector<std::string> _images;
+ std::unique_ptr<IPreprocessor> _preprocessor;
+ bool _bgr;
+ size_t _offset;
+ std::ostream &_output_stream;
+};
+
+/** Output Accessor used for network validation */
+class ValidationOutputAccessor final : public graph::ITensorAccessor
+{
+public:
+ /** Default Constructor
+ *
+ * @param[in] image_list File containing all the images and labels results
+ * @param[out] output_stream (Optional) Output stream (Defaults to the standard output stream)
+ * @param[in] start (Optional) Start range
+ * @param[in] end (Optional) End range
+ *
+ * @note Range is defined as [start, end]
+ */
+ ValidationOutputAccessor(const std::string &image_list,
+ std::ostream &output_stream = std::cout,
+ unsigned int start = 0,
+ unsigned int end = 0);
+ /** Reset accessor state */
+ void reset();
+
+ // Inherited methods overriden:
+ bool access_tensor(ITensor &tensor) override;
+
+private:
+ /** Access predictions of the tensor
+ *
+ * @tparam T Tensor elements type
+ *
+ * @param[in] tensor Tensor to read the predictions from
+ */
+ template <typename T>
+ std::vector<size_t> access_predictions_tensor(ITensor &tensor);
+ /** Aggregates the results of a sample
+ *
+ * @param[in] res Vector containing the results of a graph
+ * @param[in,out] positive_samples Positive samples to be updated
+ * @param[in] top_n Top n accuracy to measure
+ * @param[in] correct_label Correct label of the current sample
+ */
+ void aggregate_sample(const std::vector<size_t> &res, size_t &positive_samples, size_t top_n, size_t correct_label);
+ /** Reports top N accuracy
+ *
+ * @param[in] top_n Top N accuracy that is being reported
+ * @param[in] total_samples Total number of samples
+ * @param[in] positive_samples Positive samples
+ */
+ void report_top_n(size_t top_n, size_t total_samples, size_t positive_samples);
+
+private:
+ std::vector<int> _results;
+ std::ostream &_output_stream;
+ size_t _offset;
+ size_t _positive_samples_top1;
+ size_t _positive_samples_top5;
+};
+
/** Result accessor class */
class TopNPredictionsAccessor final : public graph::ITensorAccessor
{
@@ -245,6 +341,7 @@
bool access_tensor(ITensor &tensor) override;
private:
+ bool _already_loaded;
const std::string _filename;
const DataLayout _file_layout;
};
@@ -286,56 +383,79 @@
}
}
-/** Generates appropriate input accessor according to the specified ppm_path
+/** Generates appropriate input accessor according to the specified graph parameters
*
- * @note If ppm_path is empty will generate a DummyAccessor else will generate a PPMAccessor
- *
- * @param[in] ppm_path Path to PPM file
- * @param[in] preprocessor Preproccessor object
- * @param[in] bgr (Optional) Fill the first plane with blue channel (default = true)
+ * @param[in] graph_parameters Graph parameters
+ * @param[in] preprocessor (Optional) Preproccessor object
+ * @param[in] bgr (Optional) Fill the first plane with blue channel (default = true)
*
* @return An appropriate tensor accessor
*/
-inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::string &ppm_path,
- std::unique_ptr<IPreprocessor> preprocessor = nullptr,
- bool bgr = true)
+inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
+ std::unique_ptr<IPreprocessor> preprocessor = nullptr,
+ bool bgr = true)
{
- if(ppm_path.empty())
+ if(!graph_parameters.validation_file.empty())
{
- return arm_compute::support::cpp14::make_unique<DummyAccessor>();
+ return arm_compute::support::cpp14::make_unique<ValidationInputAccessor>(graph_parameters.validation_file,
+ graph_parameters.validation_path,
+ std::move(preprocessor),
+ bgr,
+ graph_parameters.validation_range_start,
+ graph_parameters.validation_range_end);
}
else
{
- if(arm_compute::utility::endswith(ppm_path, ".npy"))
+ const std::string &image_file = graph_parameters.image;
+ const std::string &image_file_lower = lower_string(image_file);
+ if(arm_compute::utility::endswith(image_file_lower, ".npy"))
{
- return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(ppm_path);
+ return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(image_file);
+ }
+ else if(arm_compute::utility::endswith(image_file_lower, ".jpeg")
+ || arm_compute::utility::endswith(image_file_lower, ".jpg")
+ || arm_compute::utility::endswith(image_file_lower, ".ppm"))
+ {
+ return arm_compute::support::cpp14::make_unique<ImageAccessor>(image_file, bgr, std::move(preprocessor));
}
else
{
- return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, bgr, std::move(preprocessor));
+ return arm_compute::support::cpp14::make_unique<DummyAccessor>();
}
}
}
-/** Generates appropriate output accessor according to the specified labels_path
+/** Generates appropriate output accessor according to the specified graph parameters
*
- * @note If labels_path is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
+ * @note If the output accessor is requested to validate the graph then ValidationOutputAccessor is generated
+ * else if output_accessor_file is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
*
- * @param[in] labels_path Path to labels text file
- * @param[in] top_n (Optional) Number of output classes to print
- * @param[out] output_stream (Optional) Output stream
+ * @param[in] graph_parameters Graph parameters
+ * @param[in] top_n (Optional) Number of output classes to print (default = 5)
+ * @param[in] is_validation (Optional) Validation flag (default = false)
+ * @param[out] output_stream (Optional) Output stream (default = std::cout)
*
* @return An appropriate tensor accessor
*/
-inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const std::string &labels_path, size_t top_n = 5, std::ostream &output_stream = std::cout)
+inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
+ size_t top_n = 5,
+ bool is_validation = false,
+ std::ostream &output_stream = std::cout)
{
- if(labels_path.empty())
+ if(!graph_parameters.validation_file.empty())
+ {
+ return arm_compute::support::cpp14::make_unique<ValidationOutputAccessor>(graph_parameters.validation_file,
+ output_stream,
+ graph_parameters.validation_range_start,
+ graph_parameters.validation_range_end);
+ }
+ else if(graph_parameters.labels.empty())
{
return arm_compute::support::cpp14::make_unique<DummyAccessor>(0);
}
else
{
- return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(labels_path, top_n, output_stream);
+ return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(graph_parameters.labels, top_n, output_stream);
}
}
/** Generates appropriate npy output accessor according to the specified npy_path
@@ -361,6 +481,24 @@
}
}
+/** Permutes a given tensor shape given the input and output data layout
+ *
+ * @param[in] tensor_shape Tensor shape to permute
+ * @param[in] in_data_layout Input tensor shape data layout
+ * @param[in] out_data_layout Output tensor shape data layout
+ *
+ * @return Permuted tensor shape
+ */
+inline TensorShape permute_shape(TensorShape tensor_shape, DataLayout in_data_layout, DataLayout out_data_layout)
+{
+ if(in_data_layout != out_data_layout)
+ {
+ arm_compute::PermutationVector perm_vec = (in_data_layout == DataLayout::NCHW) ? arm_compute::PermutationVector(2U, 0U, 1U) : arm_compute::PermutationVector(1U, 2U, 0U);
+ arm_compute::permute(tensor_shape, perm_vec);
+ }
+ return tensor_shape;
+}
+
/** Utility function to return the TargetHint
*
* @param[in] target Integer value which expresses the selected target. Must be 0 for NEON or 1 for OpenCL or 2 (OpenCL with Tuner)