arm_compute v19.02

Change-Id: I853a3ecf38f206da13c1b03640c8adf73c20477c
diff --git a/utils/GraphUtils.cpp b/utils/GraphUtils.cpp
index 2f1df7a..ab2c753 100644
--- a/utils/GraphUtils.cpp
+++ b/utils/GraphUtils.cpp
@@ -420,6 +420,77 @@
     _output_stream << "Accuracy : " << accuracy << std::endl;
 }
 
+DetectionOutputAccessor::DetectionOutputAccessor(const std::string &labels_path, std::vector<TensorShape> &imgs_tensor_shapes, std::ostream &output_stream)
+    : _labels(), _tensor_shapes(std::move(imgs_tensor_shapes)), _output_stream(output_stream)
+{
+    _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());
+    }
+}
+
+template <typename T>
+void DetectionOutputAccessor::access_predictions_tensor(ITensor &tensor)
+{
+    const size_t num_detection = tensor.info()->valid_region().shape.y();
+    const auto   output_prt    = reinterpret_cast<T *>(tensor.buffer() + tensor.info()->offset_first_element_in_bytes());
+
+    if(num_detection > 0)
+    {
+        _output_stream << "---------------------- Detections ----------------------" << std::endl
+                       << std::endl;
+
+        _output_stream << std::left << std::setprecision(4) << std::setw(8) << "Image | " << std::setw(8) << "Label | " << std::setw(12) << "Confidence | "
+                       << "[ xmin, ymin, xmax, ymax ]" << std::endl;
+
+        for(size_t i = 0; i < num_detection; ++i)
+        {
+            auto im = static_cast<const int>(output_prt[i * 7]);
+            _output_stream << std::setw(8) << im << std::setw(8)
+                           << _labels[output_prt[i * 7 + 1]] << std::setw(12) << output_prt[i * 7 + 2]
+                           << " [" << (output_prt[i * 7 + 3] * _tensor_shapes[im].x())
+                           << ", " << (output_prt[i * 7 + 4] * _tensor_shapes[im].y())
+                           << ", " << (output_prt[i * 7 + 5] * _tensor_shapes[im].x())
+                           << ", " << (output_prt[i * 7 + 6] * _tensor_shapes[im].y())
+                           << "]" << std::endl;
+        }
+    }
+    else
+    {
+        _output_stream << "No detection found." << std::endl;
+    }
+}
+
+bool DetectionOutputAccessor::access_tensor(ITensor &tensor)
+{
+    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&tensor, 1, DataType::F32);
+
+    switch(tensor.info()->data_type())
+    {
+        case DataType::F32:
+            access_predictions_tensor<float>(tensor);
+            break;
+        default:
+            ARM_COMPUTE_ERROR("NOT SUPPORTED!");
+    }
+
+    return false;
+}
+
 TopNPredictionsAccessor::TopNPredictionsAccessor(const std::string &labels_path, size_t top_n, std::ostream &output_stream)
     : _labels(), _output_stream(output_stream), _top_n(top_n)
 {
diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h
index d7f24af..131378e 100644
--- a/utils/GraphUtils.h
+++ b/utils/GraphUtils.h
@@ -283,6 +283,36 @@
     size_t           _positive_samples_top5;
 };
 
+/** Detection output accessor class */
+class DetectionOutputAccessor final : public graph::ITensorAccessor
+{
+public:
+    /** Constructor
+     *
+     * @param[in]  labels_path        Path to labels text file.
+     * @param[in]  imgs_tensor_shapes Network input images tensor shapes.
+     * @param[out] output_stream      (Optional) Output stream
+     */
+    DetectionOutputAccessor(const std::string &labels_path, std::vector<TensorShape> &imgs_tensor_shapes, std::ostream &output_stream = std::cout);
+    /** Allow instances of this class to be move constructed */
+    DetectionOutputAccessor(DetectionOutputAccessor &&) = default;
+    /** Prevent instances of this class from being copied (As this class contains pointers) */
+    DetectionOutputAccessor(const DetectionOutputAccessor &) = delete;
+    /** Prevent instances of this class from being copied (As this class contains pointers) */
+    DetectionOutputAccessor &operator=(const DetectionOutputAccessor &) = delete;
+
+    // Inherited methods overriden:
+    bool access_tensor(ITensor &tensor) override;
+
+private:
+    template <typename T>
+    void access_predictions_tensor(ITensor &tensor);
+
+    std::vector<std::string> _labels;
+    std::vector<TensorShape> _tensor_shapes;
+    std::ostream            &_output_stream;
+};
+
 /** Result accessor class */
 class TopNPredictionsAccessor final : public graph::ITensorAccessor
 {
@@ -472,6 +502,39 @@
         return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(graph_parameters.labels, top_n, output_stream);
     }
 }
+/** Generates appropriate output accessor according to the specified graph parameters
+ *
+ * @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]  graph_parameters Graph parameters
+ * @param[in]  tensor_shapes    Network input images tensor shapes.
+ * @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_detection_output_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
+                                                                             std::vector<TensorShape>                     tensor_shapes,
+                                                                             bool                                         is_validation = false,
+                                                                             std::ostream                                &output_stream = std::cout)
+{
+    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<DetectionOutputAccessor>(graph_parameters.labels, tensor_shapes, output_stream);
+    }
+}
 /** Generates appropriate npy output accessor according to the specified npy_path
  *
  * @note If npy_path is empty will generate a DummyAccessor else will generate a NpyAccessor
diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h
index d089a5b..f2cf606 100644
--- a/utils/TypePrinter.h
+++ b/utils/TypePrinter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -882,6 +882,24 @@
     return os;
 }
 
+/** Formatted output of the Multiples type.
+ *
+ * @param[out] os        Output stream.
+ * @param[in]  multiples Type to output.
+ *
+ * @return Modified output stream.
+ */
+inline ::std::ostream &operator<<(::std::ostream &os, const Multiples &multiples)
+{
+    os << "(";
+    for(size_t i = 0; i < multiples.size() - 1; i++)
+    {
+        os << multiples[i] << ", ";
+    }
+    os << multiples.back() << ")";
+    return os;
+}
+
 /** Formatted output of the InterpolationPolicy type.
  *
  * @param[out] os     Output stream.
@@ -1234,6 +1252,19 @@
     return str.str();
 }
 
+/** Formatted output of the Multiples type.
+ *
+ * @param[in] multiples Type to output.
+ *
+ * @return Formatted string.
+ */
+inline std::string to_string(const Multiples &multiples)
+{
+    std::stringstream str;
+    str << multiples;
+    return str.str();
+}
+
 /** Formatted output of the InterpolationPolicy type.
  *
  * @param[in] policy Type to output.
@@ -1291,6 +1322,55 @@
     return str.str();
 }
 
+/** Formatted output of the ArithmeticOperation type.
+ *
+ * @param[out] os Output stream.
+ * @param[in]  op Operation to output.
+ *
+ * @return Modified output stream.
+ */
+inline ::std::ostream &operator<<(::std::ostream &os, const ArithmeticOperation &op)
+{
+    switch(op)
+    {
+        case ArithmeticOperation::ADD:
+            os << "ADD";
+            break;
+        case ArithmeticOperation::SUB:
+            os << "SUB";
+            break;
+        case ArithmeticOperation::DIV:
+            os << "DIV";
+            break;
+        case ArithmeticOperation::MAX:
+            os << "MAX";
+            break;
+        case ArithmeticOperation::MIN:
+            os << "MIN";
+            break;
+        case ArithmeticOperation::SQUARED_DIFF:
+            os << "SQUARED_DIFF";
+            break;
+        default:
+            ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
+    }
+
+    return os;
+}
+
+/** Formatted output of the Arithmetic Operation
+ *
+ * @param[in] op Type to output.
+ *
+ * @return Formatted string.
+ */
+inline std::string to_string(const ArithmeticOperation &op)
+{
+    std::stringstream str;
+    str << op;
+    return str.str();
+}
+
 /** Formatted output of the Reduction Operations.
  *
  * @param[out] os Output stream.
@@ -1311,6 +1391,15 @@
         case ReductionOperation::MEAN_SUM:
             os << "MEAN_SUM";
             break;
+        case ReductionOperation::ARG_IDX_MAX:
+            os << "ARG_IDX_MAX";
+            break;
+        case ReductionOperation::ARG_IDX_MIN:
+            os << "ARG_IDX_MIN";
+            break;
+        case ReductionOperation::PROD:
+            os << "PROD";
+            break;
         default:
             ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
     }
@@ -1331,6 +1420,92 @@
     return str.str();
 }
 
+/** Formatted output of the Comparison Operations.
+ *
+ * @param[out] os Output stream.
+ * @param[in]  op Type to output.
+ *
+ * @return Modified output stream.
+ */
+inline ::std::ostream &operator<<(::std::ostream &os, const ComparisonOperation &op)
+{
+    switch(op)
+    {
+        case ComparisonOperation::Equal:
+            os << "Equal";
+            break;
+        case ComparisonOperation::NotEqual:
+            os << "NotEqual";
+            break;
+        case ComparisonOperation::Greater:
+            os << "Greater";
+            break;
+        case ComparisonOperation::GreaterEqual:
+            os << "GreaterEqual";
+            break;
+        case ComparisonOperation::Less:
+            os << "Less";
+            break;
+        case ComparisonOperation::LessEqual:
+            os << "LessEqual";
+            break;
+        default:
+            ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
+    }
+
+    return os;
+}
+
+/** Formatted output of the Elementwise unary Operations.
+ *
+ * @param[out] os Output stream.
+ * @param[in]  op Type to output.
+ *
+ * @return Modified output stream.
+ */
+inline ::std::ostream &operator<<(::std::ostream &os, const ElementWiseUnary &op)
+{
+    switch(op)
+    {
+        case ElementWiseUnary::RSQRT:
+            os << "RSQRT";
+            break;
+        case ElementWiseUnary::EXP:
+            os << "EXP";
+            break;
+        default:
+            ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
+    }
+
+    return os;
+}
+
+/** Formatted output of the Comparison Operations.
+ *
+ * @param[in] op Type to output.
+ *
+ * @return Formatted string.
+ */
+inline std::string to_string(const ComparisonOperation &op)
+{
+    std::stringstream str;
+    str << op;
+    return str.str();
+}
+
+/** Formatted output of the Elementwise unary Operations.
+ *
+ * @param[in] op Type to output.
+ *
+ * @return Formatted string.
+ */
+inline std::string to_string(const ElementWiseUnary &op)
+{
+    std::stringstream str;
+    str << op;
+    return str.str();
+}
+
 /** Formatted output of the Norm Type.
  *
  * @param[in] type Type to output.
@@ -1729,6 +1904,85 @@
     return os;
 }
 
+/** Formatted output of the DetectionOutputLayerCodeType type.
+ *
+ * @param[out] os             Output stream
+ * @param[in]  detection_code Type to output
+ *
+ * @return Modified output stream.
+ */
+inline ::std::ostream &operator<<(::std::ostream &os, const DetectionOutputLayerCodeType &detection_code)
+{
+    switch(detection_code)
+    {
+        case DetectionOutputLayerCodeType::CENTER_SIZE:
+            os << "CENTER_SIZE";
+            break;
+        case DetectionOutputLayerCodeType::CORNER:
+            os << "CORNER";
+            break;
+        case DetectionOutputLayerCodeType::CORNER_SIZE:
+            os << "CORNER_SIZE";
+            break;
+        case DetectionOutputLayerCodeType::TF_CENTER:
+            os << "TF_CENTER";
+            break;
+        default:
+            ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
+    }
+
+    return os;
+}
+/** Formatted output of the DetectionOutputLayerCodeType type.
+ *
+ * @param[in] detection_code Type to output
+ *
+ * @return Formatted string.
+ */
+inline std::string to_string(const DetectionOutputLayerCodeType &detection_code)
+{
+    std::stringstream str;
+    str << detection_code;
+    return str.str();
+}
+
+/** Formatted output of the DetectionOutputLayerInfo type.
+ *
+ * @param[out] os             Output stream
+ * @param[in]  detection_info Type to output
+ *
+ * @return Modified output stream.
+ */
+inline ::std::ostream &operator<<(::std::ostream &os, const DetectionOutputLayerInfo &detection_info)
+{
+    os << "{Classes=" << detection_info.num_classes() << ","
+       << "ShareLocation=" << detection_info.share_location() << ","
+       << "CodeType=" << detection_info.code_type() << ","
+       << "VarianceEncodedInTarget=" << detection_info.variance_encoded_in_target() << ","
+       << "KeepTopK=" << detection_info.keep_top_k() << ","
+       << "NMSThreshold=" << detection_info.nms_threshold() << ","
+       << "Eta=" << detection_info.eta() << ","
+       << "BackgroundLabelId=" << detection_info.background_label_id() << ","
+       << "ConfidenceThreshold=" << detection_info.confidence_threshold() << ","
+       << "TopK=" << detection_info.top_k() << ","
+       << "NumLocClasses=" << detection_info.num_loc_classes()
+       << "}";
+
+    return os;
+}
+
+/** Formatted output of the DetectionOutputLayerInfo type.
+ *
+ * @param[in] detection_info Type to output
+ *
+ * @return Formatted string.
+ */
+inline std::string to_string(const DetectionOutputLayerInfo &detection_info)
+{
+    std::stringstream str;
+    str << detection_info;
+    return str.str();
+}
 /** Formatted output of the DetectionWindow type.
  *
  * @param[in] detection_window Type to output
diff --git a/utils/Utils.h b/utils/Utils.h
index 8cac857..04ccc3e 100644
--- a/utils/Utils.h
+++ b/utils/Utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 ARM Limited.
+ * Copyright (c) 2016-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *