COMPMID-1328 Add support for BoxWithNMSLimit operator in CPP

Change-Id: I5aae537372bf797fbb2a2bae81038f8963b041a9
diff --git a/arm_compute/core/CPP/CPPKernels.h b/arm_compute/core/CPP/CPPKernels.h
index bf24a94..39b77cd 100644
--- a/arm_compute/core/CPP/CPPKernels.h
+++ b/arm_compute/core/CPP/CPPKernels.h
@@ -25,6 +25,7 @@
 #define __ARM_COMPUTE_CPPKERNELS_H__
 
 /* Header regrouping all the CPP kernels */
+#include "arm_compute/core/CPP/kernels/CPPBoxWithNonMaximaSuppressionLimitKernel.h"
 #include "arm_compute/core/CPP/kernels/CPPCornerCandidatesKernel.h"
 #include "arm_compute/core/CPP/kernels/CPPDetectionWindowNonMaximaSuppressionKernel.h"
 #include "arm_compute/core/CPP/kernels/CPPFlipWeightsKernel.h"
diff --git a/arm_compute/core/CPP/kernels/CPPBoxWithNonMaximaSuppressionLimitKernel.h b/arm_compute/core/CPP/kernels/CPPBoxWithNonMaximaSuppressionLimitKernel.h
new file mode 100644
index 0000000..a1adca3
--- /dev/null
+++ b/arm_compute/core/CPP/kernels/CPPBoxWithNonMaximaSuppressionLimitKernel.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_CPPBOXWITHNONMAXIMASUPPRESSIONLIMITKERNEL_H__
+#define __ARM_COMPUTE_CPPBOXWITHNONMAXIMASUPPRESSIONLIMITKERNEL_H__
+
+#include "arm_compute/core/IArray.h"
+#include "arm_compute/core/IHOG.h"
+#include "arm_compute/core/NEON/INEKernel.h"
+#include "arm_compute/core/Types.h"
+
+namespace arm_compute
+{
+class ITensor;
+
+/** CPP kernel to perform computation of BoxWithNonMaximaSuppressionLimit */
+class CPPBoxWithNonMaximaSuppressionLimitKernel : public ICPPKernel
+{
+public:
+    const char *name() const override
+    {
+        return "CPPBoxWithNonMaximaSuppressionLimitKernel";
+    }
+    /** Default constructor */
+    CPPBoxWithNonMaximaSuppressionLimitKernel();
+    /** Prevent instances of this class from being copied (As this class contains pointers) */
+    CPPBoxWithNonMaximaSuppressionLimitKernel(const CPPBoxWithNonMaximaSuppressionLimitKernel &) = delete;
+    /** Prevent instances of this class from being copied (As this class contains pointers) */
+    CPPBoxWithNonMaximaSuppressionLimitKernel &operator=(const CPPBoxWithNonMaximaSuppressionLimitKernel &) = delete;
+    /** Allow instances of this class to be moved */
+    CPPBoxWithNonMaximaSuppressionLimitKernel(CPPBoxWithNonMaximaSuppressionLimitKernel &&) = default;
+    /** Allow instances of this class to be moved */
+    CPPBoxWithNonMaximaSuppressionLimitKernel &operator=(CPPBoxWithNonMaximaSuppressionLimitKernel &&) = default;
+    /** Initialise the kernel's input and output tensors.
+     *
+     * @param[in]  scores_in        The scores input tensor of size [num_classes, count]. Data types supported: F16/F32
+     * @param[in]  boxes_in         The boxes input tensor of size [num_classes * 4, count]. Data types supported: Same as @p scores_in
+     * @param[in]  batch_splits_in  The batch splits input tensor of size [batch_size]. Data types supported: Same as @p scores_in
+     *                              @note Can be a nullptr. If not a nullptr, @p scores_in and @p boxes_in have items from multiple images.
+     * @param[out] scores_out       The scores output tensor of size [N]. Data types supported: Same as @p scores_in
+     * @param[out] boxes_out        The boxes output tensor of size [4, N]. Data types supported: Same as @p scores_in
+     * @param[out] classes          The classes output tensor of size [N]. Data types supported: Same as @p scores_in
+     * @param[out] batch_splits_out (Optional) The batch splits output tensor [batch_size]. Data types supported: Same as @p scores_in
+     * @param[out] keeps            (Optional) The keeps output tensor of size [N]. Data types supported: Same as@p scores_in
+     * @param[out] keeps_size       (Optional) Number of filtered indices per class tensor of size [num_classes]. Data types supported: Same as @p scores_in
+     * @param[in]  info             (Optional) BoxNMSLimitInfo information.
+     */
+    void configure(const ITensor *scores_in, const ITensor *boxes_in, const ITensor *batch_splits_in, ITensor *scores_out, ITensor *boxes_out, ITensor *classes,
+                   ITensor *batch_splits_out = nullptr, ITensor *keeps = nullptr, ITensor *keeps_size = nullptr, const BoxNMSLimitInfo info = BoxNMSLimitInfo());
+
+    // Inherited methods overridden:
+    void run(const Window &window, const ThreadInfo &info) override;
+    bool is_parallelisable() const override;
+
+    template <typename T>
+    void run_nmslimit();
+
+private:
+    const ITensor *_scores_in;
+    const ITensor *_boxes_in;
+    const ITensor *_batch_splits_in;
+    ITensor        *_scores_out;
+    ITensor        *_boxes_out;
+    ITensor        *_classes;
+    ITensor        *_batch_splits_out;
+    ITensor        *_keeps;
+    ITensor        *_keeps_size;
+    BoxNMSLimitInfo _info;
+};
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_CPPBOXWITHNONMAXIMASUPPRESSIONLIMITKERNEL_H__ */
diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h
index 134b8e2..cb1a212 100644
--- a/arm_compute/core/Types.h
+++ b/arm_compute/core/Types.h
@@ -574,6 +574,82 @@
     L2   /**< L2 Pooling */
 };
 
+/** Available non maxima suppression types */
+enum class NMSType
+{
+    LINEAR,   /**< Linear NMS */
+    GAUSSIAN, /**< Gaussian NMS */
+    ORIGINAL  /**< Original NMS */
+};
+
+/** BoxWithNonMaximaSuppressionLimit Information class */
+class BoxNMSLimitInfo final
+{
+public:
+    /** Constructor
+     *
+     * @param[in] score_thresh             (Optional) Score threshold.
+     * @param[in] nms                      (Optional) NMS value
+     * @param[in] detections               (Optional) Number of detections
+     * @param[in] soft_nms_enabled         (Optional) Enable SoftNMS
+     * @param[in] soft_nms_method          (Optional) Soft NMS method
+     * @param[in] soft_nms_sigma           (Optional) Soft NMS sigma value
+     * @param[in] soft_nms_min_score_thres (Optional) Soft NMS minimum score threshold
+     */
+    BoxNMSLimitInfo(float score_thresh = 0.05f, float nms = 0.3f,
+                    int detections = 100, bool soft_nms_enabled = false,
+                    NMSType soft_nms_method = NMSType::LINEAR,
+                    float soft_nms_sigma = 0.5f, float soft_nms_min_score_thres = 0.001f)
+        : _score_thresh(score_thresh), _nms(nms), _detections_per_im(detections), _soft_nms_enabled(soft_nms_enabled), _soft_nms_method(soft_nms_method), _soft_nms_sigma(soft_nms_sigma),
+          _soft_nms_min_score_thres(soft_nms_min_score_thres)
+    {
+    }
+    /** Get the score threshold */
+    float score_thresh() const
+    {
+        return _score_thresh;
+    }
+    /** Get the NMS */
+    float nms() const
+    {
+        return _nms;
+    }
+    /** Get the number of detections */
+    int detections_per_im() const
+    {
+        return _detections_per_im;
+    }
+    /** Check if soft NMS is enabled */
+    bool soft_nms_enabled() const
+    {
+        return _soft_nms_enabled;
+    }
+    /** Get soft NMS method */
+    NMSType soft_nms_method() const
+    {
+        return _soft_nms_method;
+    }
+    /** Get soft NMS sigma */
+    float soft_nms_sigma() const
+    {
+        return _soft_nms_sigma;
+    }
+    /** Get soft nms min score threshold */
+    float soft_nms_min_score_thres() const
+    {
+        return _soft_nms_min_score_thres;
+    }
+
+private:
+    float   _score_thresh;
+    float   _nms;
+    int     _detections_per_im;
+    bool    _soft_nms_enabled;
+    NMSType _soft_nms_method;
+    float   _soft_nms_sigma;
+    float   _soft_nms_min_score_thres;
+};
+
 /** Padding and stride information class */
 class PadStrideInfo
 {