aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/CPP
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/CPP')
-rw-r--r--src/runtime/CPP/CPPScheduler.cpp133
-rw-r--r--src/runtime/CPP/SingleThreadScheduler.cpp17
-rw-r--r--src/runtime/CPP/functions/CPPBoxWithNonMaximaSuppressionLimit.cpp159
-rw-r--r--src/runtime/CPP/functions/CPPDetectionOutputLayer.cpp315
-rw-r--r--src/runtime/CPP/functions/CPPDetectionPostProcessLayer.cpp418
-rw-r--r--src/runtime/CPP/functions/CPPNonMaximumSuppression.cpp27
-rw-r--r--src/runtime/CPP/functions/CPPPermute.cpp6
-rw-r--r--src/runtime/CPP/functions/CPPTopKV.cpp11
-rw-r--r--src/runtime/CPP/functions/CPPUpsample.cpp6
9 files changed, 673 insertions, 419 deletions
diff --git a/src/runtime/CPP/CPPScheduler.cpp b/src/runtime/CPP/CPPScheduler.cpp
index f112d456c7..9fbdc3a4dd 100644
--- a/src/runtime/CPP/CPPScheduler.cpp
+++ b/src/runtime/CPP/CPPScheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2021 Arm Limited.
+ * Copyright (c) 2016-2023 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,6 +29,7 @@
#include "arm_compute/core/Log.h"
#include "arm_compute/core/Utils.h"
#include "arm_compute/core/utils/misc/Utility.h"
+
#include "support/Mutex.h"
#include <atomic>
@@ -53,8 +54,7 @@ public:
* @param[in] start First value that will be returned by the feeder
* @param[in] end End condition (The last value returned by get_next() will be end - 1)
*/
- explicit ThreadFeeder(unsigned int start = 0, unsigned int end = 0)
- : _atomic_counter(start), _end(end)
+ explicit ThreadFeeder(unsigned int start = 0, unsigned int end = 0) : _atomic_counter(start), _end(end)
{
}
/** Return the next element in the range if there is one.
@@ -89,8 +89,7 @@ void process_workloads(std::vector<IScheduler::Workload> &workloads, ThreadFeede
{
ARM_COMPUTE_ERROR_ON(workload_index >= workloads.size());
workloads[workload_index](info);
- }
- while(feeder.get_next(workload_index));
+ } while (feeder.get_next(workload_index));
}
/** Set thread affinity. Pin current thread to a particular core
@@ -99,17 +98,17 @@ void process_workloads(std::vector<IScheduler::Workload> &workloads, ThreadFeede
*/
void set_thread_affinity(int core_id)
{
- if(core_id < 0)
+ if (core_id < 0)
{
return;
}
-#if !defined(__APPLE__)
+#if !defined(_WIN64) && !defined(__APPLE__) && !defined(__OpenBSD__)
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(core_id, &set);
ARM_COMPUTE_EXIT_ON_MSG(sched_setaffinity(0, sizeof(set), &set), "Error setting thread affinity");
-#endif /* !defined(__APPLE__) */
+#endif /* !defined(__APPLE__) && !defined(__OpenBSD__) */
}
/** There are currently 2 scheduling modes supported by CPPScheduler
@@ -150,10 +149,10 @@ public:
*/
explicit Thread(int core_pin = -1);
- Thread(const Thread &) = delete;
+ Thread(const Thread &) = delete;
Thread &operator=(const Thread &) = delete;
Thread(Thread &&) = delete;
- Thread &operator=(Thread &&) = delete;
+ Thread &operator=(Thread &&) = delete;
/** Destructor. Make the thread join. */
~Thread();
@@ -172,7 +171,7 @@ public:
void start();
/** Wait for the current kernel execution to complete. */
- void wait();
+ std::exception_ptr wait();
/** Function ran by the worker thread. */
void worker_thread();
@@ -196,21 +195,20 @@ public:
private:
std::thread _thread{};
ThreadInfo _info{};
- std::vector<IScheduler::Workload> *_workloads{ nullptr };
- ThreadFeeder *_feeder{ nullptr };
+ std::vector<IScheduler::Workload> *_workloads{nullptr};
+ ThreadFeeder *_feeder{nullptr};
std::mutex _m{};
std::condition_variable _cv{};
- bool _wait_for_work{ false };
- bool _job_complete{ true };
- std::exception_ptr _current_exception{ nullptr };
- int _core_pin{ -1 };
- std::list<Thread> *_thread_pool{ nullptr };
- unsigned int _wake_beg{ 0 };
- unsigned int _wake_end{ 0 };
+ bool _wait_for_work{false};
+ bool _job_complete{true};
+ std::exception_ptr _current_exception{nullptr};
+ int _core_pin{-1};
+ std::list<Thread> *_thread_pool{nullptr};
+ unsigned int _wake_beg{0};
+ unsigned int _wake_end{0};
};
-Thread::Thread(int core_pin)
- : _core_pin(core_pin)
+Thread::Thread(int core_pin) : _core_pin(core_pin)
{
_thread = std::thread(&Thread::worker_thread, this);
}
@@ -218,7 +216,7 @@ Thread::Thread(int core_pin)
Thread::~Thread()
{
// Make sure worker thread has ended
- if(_thread.joinable())
+ if (_thread.joinable())
{
ThreadFeeder feeder;
set_workload(nullptr, feeder, ThreadInfo());
@@ -244,24 +242,20 @@ void Thread::start()
_cv.notify_one();
}
-void Thread::wait()
+std::exception_ptr Thread::wait()
{
{
std::unique_lock<std::mutex> lock(_m);
_cv.wait(lock, [&] { return _job_complete; });
}
-
- if(_current_exception)
- {
- std::rethrow_exception(_current_exception);
- }
+ return _current_exception;
}
void Thread::worker_thread()
{
set_thread_affinity(_core_pin);
- while(true)
+ while (true)
{
std::unique_lock<std::mutex> lock(_m);
_cv.wait(lock, [&] { return _wait_for_work; });
@@ -270,18 +264,18 @@ void Thread::worker_thread()
_current_exception = nullptr;
// Exit if the worker thread has not been fed with workloads
- if(_workloads == nullptr || _feeder == nullptr)
+ if (_workloads == nullptr || _feeder == nullptr)
{
return;
}
// Wake up more peer threads from thread pool if this job has been delegated to the current thread
- if(_thread_pool != nullptr)
+ if (_thread_pool != nullptr)
{
auto thread_it = _thread_pool->begin();
std::advance(thread_it, std::min(static_cast<unsigned int>(_thread_pool->size()), _wake_beg));
auto wake_end = std::min(_wake_end, static_cast<unsigned int>(_info.num_threads - 1));
- for(unsigned int t = _wake_beg; t < wake_end; ++t, ++thread_it)
+ for (unsigned int t = _wake_beg; t < wake_end; ++t, ++thread_it)
{
thread_it->start();
}
@@ -295,7 +289,7 @@ void Thread::worker_thread()
#ifndef ARM_COMPUTE_EXCEPTIONS_DISABLED
}
- catch(...)
+ catch (...)
{
_current_exception = std::current_exception();
}
@@ -326,11 +320,11 @@ struct CPPScheduler::Impl final
: _num_threads(thread_hint), _threads(_num_threads - 1), _mode(Mode::Linear), _wake_fanout(0U)
{
const auto mode_env_v = utility::tolower(utility::getenv("ARM_COMPUTE_CPP_SCHEDULER_MODE"));
- if(mode_env_v == "linear")
+ if (mode_env_v == "linear")
{
_forced_mode = ModeToggle::Linear;
}
- else if(mode_env_v == "fanout")
+ else if (mode_env_v == "fanout")
{
_forced_mode = ModeToggle::Fanout;
}
@@ -354,7 +348,7 @@ struct CPPScheduler::Impl final
// Set affinity on worked threads
_threads.clear();
- for(auto i = 1U; i < _num_threads; ++i)
+ for (auto i = 1U; i < _num_threads; ++i)
{
_threads.emplace_back(func(i, thread_hint));
}
@@ -363,20 +357,23 @@ struct CPPScheduler::Impl final
void auto_switch_mode(unsigned int num_threads_to_use)
{
// If the environment variable is set to any of the modes, it overwrites the mode selected over num_threads_to_use
- if(_forced_mode == ModeToggle::Fanout || (_forced_mode == ModeToggle::None && num_threads_to_use > 8))
+ if (_forced_mode == ModeToggle::Fanout || (_forced_mode == ModeToggle::None && num_threads_to_use > 8))
{
set_fanout_mode(m_default_wake_fanout, num_threads_to_use);
- ARM_COMPUTE_LOG_INFO_MSG_WITH_FORMAT_CORE("Set CPPScheduler to Fanout mode, with wake up fanout : %d and %d threads to use\n", this->wake_fanout(), num_threads_to_use);
+ ARM_COMPUTE_LOG_INFO_MSG_WITH_FORMAT_CORE(
+ "Set CPPScheduler to Fanout mode, with wake up fanout : %d and %d threads to use\n",
+ this->wake_fanout(), num_threads_to_use);
}
else // Equivalent to (_forced_mode == ModeToggle::Linear || (_forced_mode == ModeToggle::None && num_threads_to_use <= 8))
{
set_linear_mode();
- ARM_COMPUTE_LOG_INFO_MSG_WITH_FORMAT_CORE("Set CPPScheduler to Linear mode, with %d threads to use\n", num_threads_to_use);
+ ARM_COMPUTE_LOG_INFO_MSG_WITH_FORMAT_CORE("Set CPPScheduler to Linear mode, with %d threads to use\n",
+ num_threads_to_use);
}
}
void set_linear_mode()
{
- for(auto &thread : _threads)
+ for (auto &thread : _threads)
{
thread.set_linear_mode();
}
@@ -388,14 +385,14 @@ struct CPPScheduler::Impl final
ARM_COMPUTE_ERROR_ON(num_threads_to_use > _threads.size() + 1);
const auto actual_wake_fanout = std::max(2U, std::min(wake_fanout, num_threads_to_use - 1));
auto thread_it = _threads.begin();
- for(auto i = 1U; i < num_threads_to_use; ++i, ++thread_it)
+ for (auto i = 1U; i < num_threads_to_use; ++i, ++thread_it)
{
const auto wake_begin = i * actual_wake_fanout - 1;
const auto wake_end = std::min((i + 1) * actual_wake_fanout - 1, num_threads_to_use - 1);
thread_it->set_fanout_mode(&_threads, wake_begin, wake_end);
}
// Reset the remaining threads's wake up schedule
- while(thread_it != _threads.end())
+ while (thread_it != _threads.end())
{
thread_it->set_fanout_mode(&_threads, 0U, 0U);
++thread_it;
@@ -421,9 +418,9 @@ struct CPPScheduler::Impl final
unsigned int _num_threads;
std::list<Thread> _threads;
arm_compute::Mutex _run_workloads_mutex{};
- Mode _mode{ Mode::Linear };
- ModeToggle _forced_mode{ ModeToggle::None };
- unsigned int _wake_fanout{ 0 };
+ Mode _mode{Mode::Linear};
+ ModeToggle _forced_mode{ModeToggle::None};
+ unsigned int _wake_fanout{0};
};
/*
@@ -435,8 +432,7 @@ CPPScheduler &CPPScheduler::get()
return scheduler;
}
-CPPScheduler::CPPScheduler()
- : _impl(std::make_unique<Impl>(num_threads_hint()))
+CPPScheduler::CPPScheduler() : _impl(std::make_unique<Impl>(num_threads_hint()))
{
}
@@ -469,15 +465,15 @@ void CPPScheduler::run_workloads(std::vector<IScheduler::Workload> &workloads)
// This is not great because different threads workloads won't run in parallel but at least they
// won't interfere each other and deadlock.
arm_compute::lock_guard<std::mutex> lock(_impl->_run_workloads_mutex);
- const unsigned int num_threads_to_use = std::min(_impl->num_threads(), static_cast<unsigned int>(workloads.size()));
- if(num_threads_to_use < 1)
+ const unsigned int num_threads_to_use = std::min(_impl->num_threads(), static_cast<unsigned int>(workloads.size()));
+ if (num_threads_to_use < 1)
{
return;
}
// Re-adjust the mode if the actual number of threads to use is different from the number of threads created
_impl->auto_switch_mode(num_threads_to_use);
int num_threads_to_start = 0;
- switch(_impl->mode())
+ switch (_impl->mode())
{
case CPPScheduler::Impl::Mode::Fanout:
{
@@ -493,35 +489,54 @@ void CPPScheduler::run_workloads(std::vector<IScheduler::Workload> &workloads)
}
ThreadFeeder feeder(num_threads_to_use, workloads.size());
ThreadInfo info;
- info.cpu_info = &_cpu_info;
+ info.cpu_info = &cpu_info();
info.num_threads = num_threads_to_use;
unsigned int t = 0;
auto thread_it = _impl->_threads.begin();
// Set num_threads_to_use - 1 workloads to the threads as the remaining 1 is left to the main thread
- for(; t < num_threads_to_use - 1; ++t, ++thread_it)
+ for (; t < num_threads_to_use - 1; ++t, ++thread_it)
{
info.thread_id = t;
thread_it->set_workload(&workloads, feeder, info);
}
thread_it = _impl->_threads.begin();
- for(int i = 0; i < num_threads_to_start; ++i, ++thread_it)
+ for (int i = 0; i < num_threads_to_start; ++i, ++thread_it)
{
thread_it->start();
}
- info.thread_id = t; // Set main thread's thread_id
- process_workloads(workloads, feeder, info); // Main thread processes workloads
+ info.thread_id = t; // Set main thread's thread_id
+ std::exception_ptr last_exception = nullptr;
+#ifndef ARM_COMPUTE_EXCEPTIONS_DISABLED
+ try
+ {
+#endif /* ARM_COMPUTE_EXCEPTIONS_DISABLED */
+ process_workloads(workloads, feeder, info); // Main thread processes workloads
#ifndef ARM_COMPUTE_EXCEPTIONS_DISABLED
+ }
+ catch (...)
+ {
+ last_exception = std::current_exception();
+ }
+
try
{
#endif /* ARM_COMPUTE_EXCEPTIONS_DISABLED */
thread_it = _impl->_threads.begin();
- for(unsigned int i = 0; i < num_threads_to_use - 1; ++i, ++thread_it)
+ for (unsigned int i = 0; i < num_threads_to_use - 1; ++i, ++thread_it)
+ {
+ std::exception_ptr current_exception = thread_it->wait();
+ if (current_exception)
+ {
+ last_exception = current_exception;
+ }
+ }
+ if (last_exception)
{
- thread_it->wait();
+ std::rethrow_exception(last_exception);
}
#ifndef ARM_COMPUTE_EXCEPTIONS_DISABLED
}
- catch(const std::system_error &e)
+ catch (const std::system_error &e)
{
std::cerr << "Caught system_error with code " << e.code() << " meaning " << e.what() << '\n';
}
diff --git a/src/runtime/CPP/SingleThreadScheduler.cpp b/src/runtime/CPP/SingleThreadScheduler.cpp
index 70536b7ccc..c46a2731d8 100644
--- a/src/runtime/CPP/SingleThreadScheduler.cpp
+++ b/src/runtime/CPP/SingleThreadScheduler.cpp
@@ -39,33 +39,36 @@ void SingleThreadScheduler::schedule(ICPPKernel *kernel, const Hints &hints)
{
const Window &max_window = kernel->window();
- if(hints.split_dimension() != IScheduler::split_dimensions_all)
+ if (hints.split_dimension() != IScheduler::split_dimensions_all)
{
const unsigned int num_iterations = max_window.num_iterations(hints.split_dimension());
- if(num_iterations < 1)
+ if (num_iterations < 1)
{
return;
}
}
ThreadInfo info;
- info.cpu_info = &_cpu_info;
+ info.cpu_info = &cpu_info();
kernel->run(kernel->window(), info);
}
-void SingleThreadScheduler::schedule_op(ICPPKernel *kernel, const Hints &hints, const Window &window, ITensorPack &tensors)
+void SingleThreadScheduler::schedule_op(ICPPKernel *kernel,
+ const Hints &hints,
+ const Window &window,
+ ITensorPack &tensors)
{
ARM_COMPUTE_UNUSED(hints);
ThreadInfo info;
- info.cpu_info = &_cpu_info;
+ info.cpu_info = &cpu_info();
kernel->run_op(tensors, window, info);
}
void SingleThreadScheduler::run_workloads(std::vector<Workload> &workloads)
{
ThreadInfo info;
- info.cpu_info = &_cpu_info;
- for(auto &wl : workloads)
+ info.cpu_info = &cpu_info();
+ for (auto &wl : workloads)
{
wl(info);
}
diff --git a/src/runtime/CPP/functions/CPPBoxWithNonMaximaSuppressionLimit.cpp b/src/runtime/CPP/functions/CPPBoxWithNonMaximaSuppressionLimit.cpp
index b6803d0d37..94a1673d59 100644
--- a/src/runtime/CPP/functions/CPPBoxWithNonMaximaSuppressionLimit.cpp
+++ b/src/runtime/CPP/functions/CPPBoxWithNonMaximaSuppressionLimit.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020 Arm Limited.
+ * Copyright (c) 2018-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,6 +26,8 @@
#include "arm_compute/core/CPP/kernels/CPPBoxWithNonMaximaSuppressionLimitKernel.h"
#include "arm_compute/runtime/Scheduler.h"
+#include "src/common/utils/Log.h"
+
namespace arm_compute
{
namespace
@@ -40,28 +42,37 @@ void dequantize_tensor(const ITensor *input, ITensor *output)
Iterator input_it(input, window);
Iterator output_it(output, window);
- switch(data_type)
+ switch (data_type)
{
case DataType::QASYMM8:
- execute_window_loop(window, [&](const Coordinates &)
- {
- *reinterpret_cast<float *>(output_it.ptr()) = dequantize(*reinterpret_cast<const uint8_t *>(input_it.ptr()), qinfo.scale, qinfo.offset);
- },
- input_it, output_it);
+ execute_window_loop(
+ window,
+ [&](const Coordinates &)
+ {
+ *reinterpret_cast<float *>(output_it.ptr()) =
+ dequantize(*reinterpret_cast<const uint8_t *>(input_it.ptr()), qinfo.scale, qinfo.offset);
+ },
+ input_it, output_it);
break;
case DataType::QASYMM8_SIGNED:
- execute_window_loop(window, [&](const Coordinates &)
- {
- *reinterpret_cast<float *>(output_it.ptr()) = dequantize_qasymm8_signed(*reinterpret_cast<const int8_t *>(input_it.ptr()), qinfo);
- },
- input_it, output_it);
+ execute_window_loop(
+ window,
+ [&](const Coordinates &)
+ {
+ *reinterpret_cast<float *>(output_it.ptr()) =
+ dequantize_qasymm8_signed(*reinterpret_cast<const int8_t *>(input_it.ptr()), qinfo);
+ },
+ input_it, output_it);
break;
case DataType::QASYMM16:
- execute_window_loop(window, [&](const Coordinates &)
- {
- *reinterpret_cast<float *>(output_it.ptr()) = dequantize(*reinterpret_cast<const uint16_t *>(input_it.ptr()), qinfo.scale, qinfo.offset);
- },
- input_it, output_it);
+ execute_window_loop(
+ window,
+ [&](const Coordinates &)
+ {
+ *reinterpret_cast<float *>(output_it.ptr()) =
+ dequantize(*reinterpret_cast<const uint16_t *>(input_it.ptr()), qinfo.scale, qinfo.offset);
+ },
+ input_it, output_it);
break;
default:
ARM_COMPUTE_ERROR("Unsupported data type");
@@ -78,28 +89,37 @@ void quantize_tensor(const ITensor *input, ITensor *output)
Iterator input_it(input, window);
Iterator output_it(output, window);
- switch(data_type)
+ switch (data_type)
{
case DataType::QASYMM8:
- execute_window_loop(window, [&](const Coordinates &)
- {
- *reinterpret_cast<uint8_t *>(output_it.ptr()) = quantize_qasymm8(*reinterpret_cast<const float *>(input_it.ptr()), qinfo);
- },
- input_it, output_it);
+ execute_window_loop(
+ window,
+ [&](const Coordinates &)
+ {
+ *reinterpret_cast<uint8_t *>(output_it.ptr()) =
+ quantize_qasymm8(*reinterpret_cast<const float *>(input_it.ptr()), qinfo);
+ },
+ input_it, output_it);
break;
case DataType::QASYMM8_SIGNED:
- execute_window_loop(window, [&](const Coordinates &)
- {
- *reinterpret_cast<int8_t *>(output_it.ptr()) = quantize_qasymm8_signed(*reinterpret_cast<const float *>(input_it.ptr()), qinfo);
- },
- input_it, output_it);
+ execute_window_loop(
+ window,
+ [&](const Coordinates &)
+ {
+ *reinterpret_cast<int8_t *>(output_it.ptr()) =
+ quantize_qasymm8_signed(*reinterpret_cast<const float *>(input_it.ptr()), qinfo);
+ },
+ input_it, output_it);
break;
case DataType::QASYMM16:
- execute_window_loop(window, [&](const Coordinates &)
- {
- *reinterpret_cast<uint16_t *>(output_it.ptr()) = quantize_qasymm16(*reinterpret_cast<const float *>(input_it.ptr()), qinfo);
- },
- input_it, output_it);
+ execute_window_loop(
+ window,
+ [&](const Coordinates &)
+ {
+ *reinterpret_cast<uint16_t *>(output_it.ptr()) =
+ quantize_qasymm16(*reinterpret_cast<const float *>(input_it.ptr()), qinfo);
+ },
+ input_it, output_it);
break;
default:
ARM_COMPUTE_ERROR("Unsupported data type");
@@ -130,12 +150,23 @@ CPPBoxWithNonMaximaSuppressionLimit::CPPBoxWithNonMaximaSuppressionLimit(std::sh
{
}
-void CPPBoxWithNonMaximaSuppressionLimit::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, ITensor *keeps, ITensor *keeps_size, const BoxNMSLimitInfo info)
+void CPPBoxWithNonMaximaSuppressionLimit::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,
+ ITensor *keeps,
+ ITensor *keeps_size,
+ const BoxNMSLimitInfo info)
{
ARM_COMPUTE_ERROR_ON_NULLPTR(scores_in, boxes_in, scores_out, boxes_out, classes);
+ ARM_COMPUTE_LOG_PARAMS(scores_in, boxes_in, batch_splits_in, scores_out, boxes_out, classes, batch_splits_out,
+ keeps, keeps_size, info);
- _is_qasymm8 = scores_in->info()->data_type() == DataType::QASYMM8 || scores_in->info()->data_type() == DataType::QASYMM8_SIGNED;
+ _is_qasymm8 = scores_in->info()->data_type() == DataType::QASYMM8 ||
+ scores_in->info()->data_type() == DataType::QASYMM8_SIGNED;
_scores_in = scores_in;
_boxes_in = boxes_in;
@@ -146,7 +177,7 @@ void CPPBoxWithNonMaximaSuppressionLimit::configure(const ITensor *scores_in, co
_batch_splits_out = batch_splits_out;
_keeps = keeps;
- if(_is_qasymm8)
+ if (_is_qasymm8)
{
// Manage intermediate buffers
_memory_group.manage(&_scores_in_f32);
@@ -156,7 +187,7 @@ void CPPBoxWithNonMaximaSuppressionLimit::configure(const ITensor *scores_in, co
_memory_group.manage(&_classes_f32);
_scores_in_f32.allocator()->init(scores_in->info()->clone()->set_data_type(DataType::F32));
_boxes_in_f32.allocator()->init(boxes_in->info()->clone()->set_data_type(DataType::F32));
- if(batch_splits_in != nullptr)
+ if (batch_splits_in != nullptr)
{
_memory_group.manage(&_batch_splits_in_f32);
_batch_splits_in_f32.allocator()->init(batch_splits_in->info()->clone()->set_data_type(DataType::F32));
@@ -164,58 +195,70 @@ void CPPBoxWithNonMaximaSuppressionLimit::configure(const ITensor *scores_in, co
_scores_out_f32.allocator()->init(scores_out->info()->clone()->set_data_type(DataType::F32));
_boxes_out_f32.allocator()->init(boxes_out->info()->clone()->set_data_type(DataType::F32));
_classes_f32.allocator()->init(classes->info()->clone()->set_data_type(DataType::F32));
- if(batch_splits_out != nullptr)
+ if (batch_splits_out != nullptr)
{
_memory_group.manage(&_batch_splits_out_f32);
_batch_splits_out_f32.allocator()->init(batch_splits_out->info()->clone()->set_data_type(DataType::F32));
}
- if(keeps != nullptr)
+ if (keeps != nullptr)
{
_memory_group.manage(&_keeps_f32);
_keeps_f32.allocator()->init(keeps->info()->clone()->set_data_type(DataType::F32));
}
- _box_with_nms_limit_kernel.configure(&_scores_in_f32, &_boxes_in_f32, (batch_splits_in != nullptr) ? &_batch_splits_in_f32 : nullptr,
+ _box_with_nms_limit_kernel.configure(&_scores_in_f32, &_boxes_in_f32,
+ (batch_splits_in != nullptr) ? &_batch_splits_in_f32 : nullptr,
&_scores_out_f32, &_boxes_out_f32, &_classes_f32,
- (batch_splits_out != nullptr) ? &_batch_splits_out_f32 : nullptr, (keeps != nullptr) ? &_keeps_f32 : nullptr,
- keeps_size, info);
+ (batch_splits_out != nullptr) ? &_batch_splits_out_f32 : nullptr,
+ (keeps != nullptr) ? &_keeps_f32 : nullptr, keeps_size, info);
}
else
{
- _box_with_nms_limit_kernel.configure(scores_in, boxes_in, batch_splits_in, scores_out, boxes_out, classes, batch_splits_out, keeps, keeps_size, info);
+ _box_with_nms_limit_kernel.configure(scores_in, boxes_in, batch_splits_in, scores_out, boxes_out, classes,
+ batch_splits_out, keeps, keeps_size, info);
}
- if(_is_qasymm8)
+ if (_is_qasymm8)
{
_scores_in_f32.allocator()->allocate();
_boxes_in_f32.allocator()->allocate();
- if(_batch_splits_in != nullptr)
+ if (_batch_splits_in != nullptr)
{
_batch_splits_in_f32.allocator()->allocate();
}
_scores_out_f32.allocator()->allocate();
_boxes_out_f32.allocator()->allocate();
_classes_f32.allocator()->allocate();
- if(batch_splits_out != nullptr)
+ if (batch_splits_out != nullptr)
{
_batch_splits_out_f32.allocator()->allocate();
}
- if(keeps != nullptr)
+ if (keeps != nullptr)
{
_keeps_f32.allocator()->allocate();
}
}
}
-Status validate(const ITensorInfo *scores_in, const ITensorInfo *boxes_in, const ITensorInfo *batch_splits_in, const ITensorInfo *scores_out, const ITensorInfo *boxes_out, const ITensorInfo *classes,
- const ITensorInfo *batch_splits_out, const ITensorInfo *keeps, const ITensorInfo *keeps_size, const BoxNMSLimitInfo info)
+Status validate(const ITensorInfo *scores_in,
+ const ITensorInfo *boxes_in,
+ const ITensorInfo *batch_splits_in,
+ const ITensorInfo *scores_out,
+ const ITensorInfo *boxes_out,
+ const ITensorInfo *classes,
+ const ITensorInfo *batch_splits_out,
+ const ITensorInfo *keeps,
+ const ITensorInfo *keeps_size,
+ const BoxNMSLimitInfo info)
{
ARM_COMPUTE_UNUSED(batch_splits_in, batch_splits_out, keeps, keeps_size, info);
ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(scores_in, boxes_in, scores_out, boxes_out, classes);
- ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(scores_in, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(scores_in, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED,
+ DataType::F16, DataType::F32);
- const bool is_qasymm8 = scores_in->data_type() == DataType::QASYMM8 || scores_in->data_type() == DataType::QASYMM8_SIGNED;
- if(is_qasymm8)
+ const bool is_qasymm8 =
+ scores_in->data_type() == DataType::QASYMM8 || scores_in->data_type() == DataType::QASYMM8_SIGNED;
+ if (is_qasymm8)
{
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(boxes_in, 1, DataType::QASYMM16);
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(boxes_in, boxes_out);
@@ -233,11 +276,11 @@ void CPPBoxWithNonMaximaSuppressionLimit::run()
// Acquire all the temporaries
MemoryGroupResourceScope scope_mg(_memory_group);
- if(_is_qasymm8)
+ if (_is_qasymm8)
{
dequantize_tensor(_scores_in, &_scores_in_f32);
dequantize_tensor(_boxes_in, &_boxes_in_f32);
- if(_batch_splits_in != nullptr)
+ if (_batch_splits_in != nullptr)
{
dequantize_tensor(_batch_splits_in, &_batch_splits_in_f32);
}
@@ -245,16 +288,16 @@ void CPPBoxWithNonMaximaSuppressionLimit::run()
Scheduler::get().schedule(&_box_with_nms_limit_kernel, Window::DimY);
- if(_is_qasymm8)
+ if (_is_qasymm8)
{
quantize_tensor(&_scores_out_f32, _scores_out);
quantize_tensor(&_boxes_out_f32, _boxes_out);
quantize_tensor(&_classes_f32, _classes);
- if(_batch_splits_out != nullptr)
+ if (_batch_splits_out != nullptr)
{
quantize_tensor(&_batch_splits_out_f32, _batch_splits_out);
}
- if(_keeps != nullptr)
+ if (_keeps != nullptr)
{
quantize_tensor(&_keeps_f32, _keeps);
}
diff --git a/src/runtime/CPP/functions/CPPDetectionOutputLayer.cpp b/src/runtime/CPP/functions/CPPDetectionOutputLayer.cpp
index fdb4c9f0f6..e6291f973e 100644
--- a/src/runtime/CPP/functions/CPPDetectionOutputLayer.cpp
+++ b/src/runtime/CPP/functions/CPPDetectionOutputLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020 Arm Limited.
+ * Copyright (c) 2018-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,6 +26,8 @@
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Validate.h"
+
+#include "src/common/utils/Log.h"
#include "src/core/helpers/AutoConfiguration.h"
#include <list>
@@ -34,25 +36,35 @@ namespace arm_compute
{
namespace
{
-Status validate_arguments(const ITensorInfo *input_loc, const ITensorInfo *input_conf, const ITensorInfo *input_priorbox, const ITensorInfo *output, DetectionOutputLayerInfo info)
+Status validate_arguments(const ITensorInfo *input_loc,
+ const ITensorInfo *input_conf,
+ const ITensorInfo *input_priorbox,
+ const ITensorInfo *output,
+ DetectionOutputLayerInfo info)
{
ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input_loc, input_conf, input_priorbox, output);
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input_loc, 1, DataType::F32);
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input_loc, input_conf, input_priorbox);
ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_loc->num_dimensions() > 2, "The location input tensor should be [C1, N].");
ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_conf->num_dimensions() > 2, "The location input tensor should be [C2, N].");
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_priorbox->num_dimensions() > 3, "The priorbox input tensor should be [C3, 2, N].");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_priorbox->num_dimensions() > 3,
+ "The priorbox input tensor should be [C3, 2, N].");
ARM_COMPUTE_RETURN_ERROR_ON_MSG(info.eta() <= 0.f && info.eta() > 1.f, "Eta should be between 0 and 1");
const int num_priors = input_priorbox->tensor_shape()[0] / 4;
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(static_cast<size_t>((num_priors * info.num_loc_classes() * 4)) != input_loc->tensor_shape()[0], "Number of priors must match number of location predictions.");
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(static_cast<size_t>((num_priors * info.num_classes())) != input_conf->tensor_shape()[0], "Number of priors must match number of confidence predictions.");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(static_cast<size_t>((num_priors * info.num_loc_classes() * 4)) !=
+ input_loc->tensor_shape()[0],
+ "Number of priors must match number of location predictions.");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(static_cast<size_t>((num_priors * info.num_classes())) !=
+ input_conf->tensor_shape()[0],
+ "Number of priors must match number of confidence predictions.");
// Validate configured output
- if(output->total_size() != 0)
+ if (output->total_size() != 0)
{
- const unsigned int max_size = info.keep_top_k() * (input_loc->num_dimensions() > 1 ? input_loc->dimension(1) : 1);
+ const unsigned int max_size =
+ info.keep_top_k() * (input_loc->num_dimensions() > 1 ? input_loc->dimension(1) : 1);
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output->tensor_shape(), TensorShape(7U, max_size));
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input_loc, output);
}
@@ -63,8 +75,7 @@ Status validate_arguments(const ITensorInfo *input_loc, const ITensorInfo *input
/** Function used to sort pair<float, T> in descend order based on the score (first) value.
*/
template <typename T>
-bool SortScorePairDescend(const std::pair<float, T> &pair1,
- const std::pair<float, T> &pair2)
+bool SortScorePairDescend(const std::pair<float, T> &pair1, const std::pair<float, T> &pair2)
{
return pair1.first > pair2.first;
}
@@ -80,16 +91,19 @@ bool SortScorePairDescend(const std::pair<float, T> &pair1,
* @param[out] all_location_predictions All the location predictions.
*
*/
-void retrieve_all_loc_predictions(const ITensor *input_loc, const int num,
- const int num_priors, const int num_loc_classes,
- const bool share_location, std::vector<LabelBBox> &all_location_predictions)
+void retrieve_all_loc_predictions(const ITensor *input_loc,
+ const int num,
+ const int num_priors,
+ const int num_loc_classes,
+ const bool share_location,
+ std::vector<LabelBBox> &all_location_predictions)
{
- for(int i = 0; i < num; ++i)
+ for (int i = 0; i < num; ++i)
{
- for(int c = 0; c < num_loc_classes; ++c)
+ for (int c = 0; c < num_loc_classes; ++c)
{
int label = share_location ? -1 : c;
- if(all_location_predictions[i].find(label) == all_location_predictions[i].end())
+ if (all_location_predictions[i].find(label) == all_location_predictions[i].end())
{
all_location_predictions[i][label].resize(num_priors);
}
@@ -100,19 +114,23 @@ void retrieve_all_loc_predictions(const ITensor *input_loc, const int num,
}
}
}
- for(int i = 0; i < num; ++i)
+ for (int i = 0; i < num; ++i)
{
- for(int p = 0; p < num_priors; ++p)
+ for (int p = 0; p < num_priors; ++p)
{
- for(int c = 0; c < num_loc_classes; ++c)
+ for (int c = 0; c < num_loc_classes; ++c)
{
const int label = share_location ? -1 : c;
const int base_ptr = i * num_priors * num_loc_classes * 4 + p * num_loc_classes * 4 + c * 4;
//xmin, ymin, xmax, ymax
- all_location_predictions[i][label][p][0] = *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr)));
- all_location_predictions[i][label][p][1] = *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr + 1)));
- all_location_predictions[i][label][p][2] = *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr + 2)));
- all_location_predictions[i][label][p][3] = *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr + 3)));
+ all_location_predictions[i][label][p][0] =
+ *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr)));
+ all_location_predictions[i][label][p][1] =
+ *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr + 1)));
+ all_location_predictions[i][label][p][2] =
+ *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr + 2)));
+ all_location_predictions[i][label][p][3] =
+ *reinterpret_cast<float *>(input_loc->ptr_to_element(Coordinates(base_ptr + 3)));
}
}
}
@@ -128,26 +146,28 @@ void retrieve_all_loc_predictions(const ITensor *input_loc, const int num,
* @param[out] all_location_predictions All the location predictions.
*
*/
-void retrieve_all_conf_scores(const ITensor *input_conf, const int num,
- const int num_priors, const int num_classes,
+void retrieve_all_conf_scores(const ITensor *input_conf,
+ const int num,
+ const int num_priors,
+ const int num_classes,
std::vector<std::map<int, std::vector<float>>> &all_confidence_scores)
{
std::vector<float> tmp_buffer;
tmp_buffer.resize(num * num_priors * num_classes);
- for(int i = 0; i < num; ++i)
+ for (int i = 0; i < num; ++i)
{
- for(int c = 0; c < num_classes; ++c)
+ for (int c = 0; c < num_classes; ++c)
{
- for(int p = 0; p < num_priors; ++p)
+ for (int p = 0; p < num_priors; ++p)
{
- tmp_buffer[i * num_classes * num_priors + c * num_priors + p] =
- *reinterpret_cast<float *>(input_conf->ptr_to_element(Coordinates(i * num_classes * num_priors + p * num_classes + c)));
+ tmp_buffer[i * num_classes * num_priors + c * num_priors + p] = *reinterpret_cast<float *>(
+ input_conf->ptr_to_element(Coordinates(i * num_classes * num_priors + p * num_classes + c)));
}
}
}
- for(int i = 0; i < num; ++i)
+ for (int i = 0; i < num; ++i)
{
- for(int c = 0; c < num_classes; ++c)
+ for (int c = 0; c < num_classes; ++c)
{
all_confidence_scores[i][c].resize(num_priors);
all_confidence_scores[i][c].assign(&tmp_buffer[i * num_classes * num_priors + c * num_priors],
@@ -166,28 +186,23 @@ void retrieve_all_conf_scores(const ITensor *input_conf, const int num,
* @param[out] all_location_predictions All the location predictions.
*
*/
-void retrieve_all_priorbox(const ITensor *input_priorbox,
- const int num_priors,
- std::vector<BBox> &all_prior_bboxes,
+void retrieve_all_priorbox(const ITensor *input_priorbox,
+ const int num_priors,
+ std::vector<BBox> &all_prior_bboxes,
std::vector<std::array<float, 4>> &all_prior_variances)
{
- for(int i = 0; i < num_priors; ++i)
+ for (int i = 0; i < num_priors; ++i)
{
- all_prior_bboxes[i] =
- {
- {
- *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4))),
- *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4 + 1))),
- *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4 + 2))),
- *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4 + 3)))
- }
- };
+ all_prior_bboxes[i] = {{*reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4))),
+ *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4 + 1))),
+ *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4 + 2))),
+ *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates(i * 4 + 3)))}};
}
- std::array<float, 4> var({ { 0, 0, 0, 0 } });
- for(int i = 0; i < num_priors; ++i)
+ std::array<float, 4> var({{0, 0, 0, 0}});
+ for (int i = 0; i < num_priors; ++i)
{
- for(int j = 0; j < 4; ++j)
+ for (int j = 0; j < 4; ++j)
{
var[j] = *reinterpret_cast<float *>(input_priorbox->ptr_to_element(Coordinates((num_priors + i) * 4 + j)));
}
@@ -206,13 +221,17 @@ void retrieve_all_priorbox(const ITensor *input_priorbox,
* @param[out] decode_bbox The decoded bboxes.
*
*/
-void DecodeBBox(const BBox &prior_bbox, const std::array<float, 4> &prior_variance,
- const DetectionOutputLayerCodeType code_type, const bool variance_encoded_in_target,
- const bool clip_bbox, const BBox &bbox, BBox &decode_bbox)
+void DecodeBBox(const BBox &prior_bbox,
+ const std::array<float, 4> &prior_variance,
+ const DetectionOutputLayerCodeType code_type,
+ const bool variance_encoded_in_target,
+ const bool clip_bbox,
+ const BBox &bbox,
+ BBox &decode_bbox)
{
// if the variance is encoded in target, we simply need to add the offset predictions
// otherwise we need to scale the offset accordingly.
- switch(code_type)
+ switch (code_type)
{
case DetectionOutputLayerCodeType::CORNER:
{
@@ -235,10 +254,14 @@ void DecodeBBox(const BBox &prior_bbox, const std::array<float, 4> &prior_varian
const float prior_center_x = (prior_bbox[0] + prior_bbox[2]) / 2.;
const float prior_center_y = (prior_bbox[1] + prior_bbox[3]) / 2.;
- const float decode_bbox_center_x = (variance_encoded_in_target ? bbox[0] : prior_variance[0] * bbox[0]) * prior_width + prior_center_x;
- const float decode_bbox_center_y = (variance_encoded_in_target ? bbox[1] : prior_variance[1] * bbox[1]) * prior_height + prior_center_y;
- const float decode_bbox_width = (variance_encoded_in_target ? std::exp(bbox[2]) : std::exp(prior_variance[2] * bbox[2])) * prior_width;
- const float decode_bbox_height = (variance_encoded_in_target ? std::exp(bbox[3]) : std::exp(prior_variance[3] * bbox[3])) * prior_height;
+ const float decode_bbox_center_x =
+ (variance_encoded_in_target ? bbox[0] : prior_variance[0] * bbox[0]) * prior_width + prior_center_x;
+ const float decode_bbox_center_y =
+ (variance_encoded_in_target ? bbox[1] : prior_variance[1] * bbox[1]) * prior_height + prior_center_y;
+ const float decode_bbox_width =
+ (variance_encoded_in_target ? std::exp(bbox[2]) : std::exp(prior_variance[2] * bbox[2])) * prior_width;
+ const float decode_bbox_height =
+ (variance_encoded_in_target ? std::exp(bbox[3]) : std::exp(prior_variance[3] * bbox[3])) * prior_height;
decode_bbox[0] = (decode_bbox_center_x - decode_bbox_width / 2.f);
decode_bbox[1] = (decode_bbox_center_y - decode_bbox_height / 2.f);
@@ -256,10 +279,14 @@ void DecodeBBox(const BBox &prior_bbox, const std::array<float, 4> &prior_varian
ARM_COMPUTE_ERROR_ON(prior_width <= 0.f);
ARM_COMPUTE_ERROR_ON(prior_height <= 0.f);
- decode_bbox[0] = prior_bbox[0] + (variance_encoded_in_target ? bbox[0] : prior_variance[0] * bbox[0]) * prior_width;
- decode_bbox[1] = prior_bbox[1] + (variance_encoded_in_target ? bbox[1] : prior_variance[1] * bbox[1]) * prior_height;
- decode_bbox[2] = prior_bbox[2] + (variance_encoded_in_target ? bbox[2] : prior_variance[2] * bbox[2]) * prior_width;
- decode_bbox[3] = prior_bbox[3] + (variance_encoded_in_target ? bbox[3] : prior_variance[3] * bbox[3]) * prior_height;
+ decode_bbox[0] =
+ prior_bbox[0] + (variance_encoded_in_target ? bbox[0] : prior_variance[0] * bbox[0]) * prior_width;
+ decode_bbox[1] =
+ prior_bbox[1] + (variance_encoded_in_target ? bbox[1] : prior_variance[1] * bbox[1]) * prior_height;
+ decode_bbox[2] =
+ prior_bbox[2] + (variance_encoded_in_target ? bbox[2] : prior_variance[2] * bbox[2]) * prior_width;
+ decode_bbox[3] =
+ prior_bbox[3] + (variance_encoded_in_target ? bbox[3] : prior_variance[3] * bbox[3]) * prior_height;
break;
}
@@ -267,9 +294,9 @@ void DecodeBBox(const BBox &prior_bbox, const std::array<float, 4> &prior_varian
ARM_COMPUTE_ERROR("Unsupported Detection Output Code Type.");
}
- if(clip_bbox)
+ if (clip_bbox)
{
- for(auto &d_bbox : decode_bbox)
+ for (auto &d_bbox : decode_bbox)
{
d_bbox = utility::clamp(d_bbox, 0.f, 1.f);
}
@@ -287,10 +314,13 @@ void DecodeBBox(const BBox &prior_bbox, const std::array<float, 4> &prior_varian
* @param[out] indices The kept indices of bboxes after nms.
*
*/
-void ApplyNMSFast(const std::vector<BBox> &bboxes,
- const std::vector<float> &scores, const float score_threshold,
- const float nms_threshold, const float eta, const int top_k,
- std::vector<int> &indices)
+void ApplyNMSFast(const std::vector<BBox> &bboxes,
+ const std::vector<float> &scores,
+ const float score_threshold,
+ const float nms_threshold,
+ const float eta,
+ const int top_k,
+ std::vector<int> &indices)
{
ARM_COMPUTE_ERROR_ON_MSG(bboxes.size() != scores.size(), "bboxes and scores have different size.");
@@ -298,9 +328,9 @@ void ApplyNMSFast(const std::vector<BBox> &bboxes,
std::list<std::pair<float, int>> score_index_vec;
// Generate index score pairs.
- for(size_t i = 0; i < scores.size(); ++i)
+ for (size_t i = 0; i < scores.size(); ++i)
{
- if(scores[i] > score_threshold)
+ if (scores[i] > score_threshold)
{
score_index_vec.emplace_back(std::make_pair(scores[i], i));
}
@@ -311,7 +341,7 @@ void ApplyNMSFast(const std::vector<BBox> &bboxes,
// Keep top_k scores if needed.
const int score_index_vec_size = score_index_vec.size();
- if(top_k > -1 && top_k < score_index_vec_size)
+ if (top_k > -1 && top_k < score_index_vec_size)
{
score_index_vec.resize(top_k);
}
@@ -320,46 +350,45 @@ void ApplyNMSFast(const std::vector<BBox> &bboxes,
float adaptive_threshold = nms_threshold;
indices.clear();
- while(!score_index_vec.empty())
+ while (!score_index_vec.empty())
{
const int idx = score_index_vec.front().second;
bool keep = true;
- for(int kept_idx : indices)
+ for (int kept_idx : indices)
{
- if(keep)
+ if (keep)
{
// Compute the jaccard (intersection over union IoU) overlap between two bboxes.
- BBox intersect_bbox = std::array<float, 4>({ 0, 0, 0, 0 });
- if(bboxes[kept_idx][0] > bboxes[idx][2] || bboxes[kept_idx][2] < bboxes[idx][0] || bboxes[kept_idx][1] > bboxes[idx][3] || bboxes[kept_idx][3] < bboxes[idx][1])
+ BBox intersect_bbox = std::array<float, 4>({0, 0, 0, 0});
+ if (bboxes[kept_idx][0] > bboxes[idx][2] || bboxes[kept_idx][2] < bboxes[idx][0] ||
+ bboxes[kept_idx][1] > bboxes[idx][3] || bboxes[kept_idx][3] < bboxes[idx][1])
{
- intersect_bbox = std::array<float, 4>({ { 0, 0, 0, 0 } });
+ intersect_bbox = std::array<float, 4>({{0, 0, 0, 0}});
}
else
{
- intersect_bbox = std::array<float, 4>({ {
- std::max(bboxes[idx][0], bboxes[kept_idx][0]),
- std::max(bboxes[idx][1], bboxes[kept_idx][1]),
- std::min(bboxes[idx][2], bboxes[kept_idx][2]),
- std::min(bboxes[idx][3], bboxes[kept_idx][3])
- }
- });
+ intersect_bbox = std::array<float, 4>(
+ {{std::max(bboxes[idx][0], bboxes[kept_idx][0]), std::max(bboxes[idx][1], bboxes[kept_idx][1]),
+ std::min(bboxes[idx][2], bboxes[kept_idx][2]),
+ std::min(bboxes[idx][3], bboxes[kept_idx][3])}});
}
float intersect_width = intersect_bbox[2] - intersect_bbox[0];
float intersect_height = intersect_bbox[3] - intersect_bbox[1];
float overlap = 0.f;
- if(intersect_width > 0 && intersect_height > 0)
+ if (intersect_width > 0 && intersect_height > 0)
{
float intersect_size = intersect_width * intersect_height;
- float bbox1_size = (bboxes[idx][2] < bboxes[idx][0]
- || bboxes[idx][3] < bboxes[idx][1]) ?
- 0.f :
- (bboxes[idx][2] - bboxes[idx][0]) * (bboxes[idx][3] - bboxes[idx][1]); //BBoxSize(bboxes[idx]);
- float bbox2_size = (bboxes[kept_idx][2] < bboxes[kept_idx][0]
- || bboxes[kept_idx][3] < bboxes[kept_idx][1]) ?
- 0.f :
- (bboxes[kept_idx][2] - bboxes[kept_idx][0]) * (bboxes[kept_idx][3] - bboxes[kept_idx][1]); // BBoxSize(bboxes[kept_idx]);
+ float bbox1_size = (bboxes[idx][2] < bboxes[idx][0] || bboxes[idx][3] < bboxes[idx][1])
+ ? 0.f
+ : (bboxes[idx][2] - bboxes[idx][0]) *
+ (bboxes[idx][3] - bboxes[idx][1]); //BBoxSize(bboxes[idx]);
+ float bbox2_size =
+ (bboxes[kept_idx][2] < bboxes[kept_idx][0] || bboxes[kept_idx][3] < bboxes[kept_idx][1])
+ ? 0.f
+ : (bboxes[kept_idx][2] - bboxes[kept_idx][0]) *
+ (bboxes[kept_idx][3] - bboxes[kept_idx][1]); // BBoxSize(bboxes[kept_idx]);
overlap = intersect_size / (bbox1_size + bbox2_size - intersect_size);
}
keep = (overlap <= adaptive_threshold);
@@ -369,12 +398,12 @@ void ApplyNMSFast(const std::vector<BBox> &bboxes,
break;
}
}
- if(keep)
+ if (keep)
{
indices.push_back(idx);
}
score_index_vec.erase(score_index_vec.begin());
- if(keep && eta < 1.f && adaptive_threshold > 0.5f)
+ if (keep && eta < 1.f && adaptive_threshold > 0.5f)
{
adaptive_threshold *= eta;
}
@@ -383,23 +412,42 @@ void ApplyNMSFast(const std::vector<BBox> &bboxes,
} // namespace
CPPDetectionOutputLayer::CPPDetectionOutputLayer()
- : _input_loc(nullptr), _input_conf(nullptr), _input_priorbox(nullptr), _output(nullptr), _info(), _num_priors(), _num(), _all_location_predictions(), _all_confidence_scores(), _all_prior_bboxes(),
- _all_prior_variances(), _all_decode_bboxes(), _all_indices()
+ : _input_loc(nullptr),
+ _input_conf(nullptr),
+ _input_priorbox(nullptr),
+ _output(nullptr),
+ _info(),
+ _num_priors(),
+ _num(),
+ _all_location_predictions(),
+ _all_confidence_scores(),
+ _all_prior_bboxes(),
+ _all_prior_variances(),
+ _all_decode_bboxes(),
+ _all_indices()
{
}
-void CPPDetectionOutputLayer::configure(const ITensor *input_loc, const ITensor *input_conf, const ITensor *input_priorbox, ITensor *output, DetectionOutputLayerInfo info)
+void CPPDetectionOutputLayer::configure(const ITensor *input_loc,
+ const ITensor *input_conf,
+ const ITensor *input_priorbox,
+ ITensor *output,
+ DetectionOutputLayerInfo info)
{
ARM_COMPUTE_ERROR_ON_NULLPTR(input_loc, input_conf, input_priorbox, output);
+ ARM_COMPUTE_LOG_PARAMS(input_loc, input_conf, input_priorbox, output, info);
+
// Output auto initialization if not yet initialized
// Since the number of bboxes to kept is unknown before nms, the shape is set to the maximum
// The maximum is keep_top_k * input_loc_size[1]
// Each row is a 7 dimension std::vector, which stores [image_id, label, confidence, xmin, ymin, xmax, ymax]
- const unsigned int max_size = info.keep_top_k() * (input_loc->info()->num_dimensions() > 1 ? input_loc->info()->dimension(1) : 1);
+ const unsigned int max_size =
+ info.keep_top_k() * (input_loc->info()->num_dimensions() > 1 ? input_loc->info()->dimension(1) : 1);
auto_init_if_empty(*output->info(), input_loc->info()->clone()->set_tensor_shape(TensorShape(7U, max_size)));
// Perform validation step
- ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input_loc->info(), input_conf->info(), input_priorbox->info(), output->info(), info));
+ ARM_COMPUTE_ERROR_THROW_ON(
+ validate_arguments(input_loc->info(), input_conf->info(), input_priorbox->info(), output->info(), info));
_input_loc = input_loc;
_input_conf = input_conf;
@@ -415,12 +463,12 @@ void CPPDetectionOutputLayer::configure(const ITensor *input_loc, const ITensor
_all_prior_variances.resize(_num_priors);
_all_decode_bboxes.resize(_num);
- for(int i = 0; i < _num; ++i)
+ for (int i = 0; i < _num; ++i)
{
- for(int c = 0; c < _info.num_loc_classes(); ++c)
+ for (int c = 0; c < _info.num_loc_classes(); ++c)
{
const int label = _info.share_location() ? -1 : c;
- if(label == _info.background_label_id())
+ if (label == _info.background_label_id())
{
// Ignore background class.
continue;
@@ -435,7 +483,11 @@ void CPPDetectionOutputLayer::configure(const ITensor *input_loc, const ITensor
output->info()->set_valid_region(ValidRegion(coord, output->info()->tensor_shape()));
}
-Status CPPDetectionOutputLayer::validate(const ITensorInfo *input_loc, const ITensorInfo *input_conf, const ITensorInfo *input_priorbox, const ITensorInfo *output, DetectionOutputLayerInfo info)
+Status CPPDetectionOutputLayer::validate(const ITensorInfo *input_loc,
+ const ITensorInfo *input_conf,
+ const ITensorInfo *input_priorbox,
+ const ITensorInfo *output,
+ DetectionOutputLayerInfo info)
{
ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input_loc, input_conf, input_priorbox, output, info));
return Status{};
@@ -444,7 +496,8 @@ Status CPPDetectionOutputLayer::validate(const ITensorInfo *input_loc, const ITe
void CPPDetectionOutputLayer::run()
{
// Retrieve all location predictions.
- retrieve_all_loc_predictions(_input_loc, _num, _num_priors, _info.num_loc_classes(), _info.share_location(), _all_location_predictions);
+ retrieve_all_loc_predictions(_input_loc, _num, _num_priors, _info.num_loc_classes(), _info.share_location(),
+ _all_location_predictions);
// Retrieve all confidences.
retrieve_all_conf_scores(_input_conf, _num, _num_priors, _info.num_classes(), _all_confidence_scores);
@@ -454,75 +507,79 @@ void CPPDetectionOutputLayer::run()
// Decode all loc predictions to bboxes
const bool clip_bbox = false;
- for(int i = 0; i < _num; ++i)
+ for (int i = 0; i < _num; ++i)
{
- for(int c = 0; c < _info.num_loc_classes(); ++c)
+ for (int c = 0; c < _info.num_loc_classes(); ++c)
{
const int label = _info.share_location() ? -1 : c;
- if(label == _info.background_label_id())
+ if (label == _info.background_label_id())
{
// Ignore background class.
continue;
}
- ARM_COMPUTE_ERROR_ON_MSG_VAR(_all_location_predictions[i].find(label) == _all_location_predictions[i].end(), "Could not find location predictions for label %d.", label);
+ ARM_COMPUTE_ERROR_ON_MSG_VAR(_all_location_predictions[i].find(label) == _all_location_predictions[i].end(),
+ "Could not find location predictions for label %d.", label);
const std::vector<BBox> &label_loc_preds = _all_location_predictions[i].find(label)->second;
const int num_bboxes = _all_prior_bboxes.size();
ARM_COMPUTE_ERROR_ON(_all_prior_variances[i].size() != 4);
- for(int j = 0; j < num_bboxes; ++j)
+ for (int j = 0; j < num_bboxes; ++j)
{
- DecodeBBox(_all_prior_bboxes[j], _all_prior_variances[j], _info.code_type(), _info.variance_encoded_in_target(), clip_bbox, label_loc_preds[j], _all_decode_bboxes[i][label][j]);
+ DecodeBBox(_all_prior_bboxes[j], _all_prior_variances[j], _info.code_type(),
+ _info.variance_encoded_in_target(), clip_bbox, label_loc_preds[j],
+ _all_decode_bboxes[i][label][j]);
}
}
}
int num_kept = 0;
- for(int i = 0; i < _num; ++i)
+ for (int i = 0; i < _num; ++i)
{
- const LabelBBox &decode_bboxes = _all_decode_bboxes[i];
- const std::map<int, std::vector<float>> &conf_scores = _all_confidence_scores[i];
+ const LabelBBox &decode_bboxes = _all_decode_bboxes[i];
+ const std::map<int, std::vector<float>> &conf_scores = _all_confidence_scores[i];
std::map<int, std::vector<int>> indices;
- int num_det = 0;
- for(int c = 0; c < _info.num_classes(); ++c)
+ int num_det = 0;
+ for (int c = 0; c < _info.num_classes(); ++c)
{
- if(c == _info.background_label_id())
+ if (c == _info.background_label_id())
{
// Ignore background class
continue;
}
const int label = _info.share_location() ? -1 : c;
- if(conf_scores.find(c) == conf_scores.end() || decode_bboxes.find(label) == decode_bboxes.end())
+ if (conf_scores.find(c) == conf_scores.end() || decode_bboxes.find(label) == decode_bboxes.end())
{
ARM_COMPUTE_ERROR_VAR("Could not find predictions for label %d.", label);
}
const std::vector<float> &scores = conf_scores.find(c)->second;
- const std::vector<BBox> &bboxes = decode_bboxes.find(label)->second;
+ const std::vector<BBox> &bboxes = decode_bboxes.find(label)->second;
- ApplyNMSFast(bboxes, scores, _info.confidence_threshold(), _info.nms_threshold(), _info.eta(), _info.top_k(), indices[c]);
+ ApplyNMSFast(bboxes, scores, _info.confidence_threshold(), _info.nms_threshold(), _info.eta(),
+ _info.top_k(), indices[c]);
num_det += indices[c].size();
}
int num_to_add = 0;
- if(_info.keep_top_k() > -1 && num_det > _info.keep_top_k())
+ if (_info.keep_top_k() > -1 && num_det > _info.keep_top_k())
{
std::vector<std::pair<float, std::pair<int, int>>> score_index_pairs;
- for(auto const &it : indices)
+ for (auto const &it : indices)
{
const int label = it.first;
const std::vector<int> &label_indices = it.second;
- if(conf_scores.find(label) == conf_scores.end())
+ if (conf_scores.find(label) == conf_scores.end())
{
ARM_COMPUTE_ERROR_VAR("Could not find predictions for label %d.", label);
}
const std::vector<float> &scores = conf_scores.find(label)->second;
- for(auto idx : label_indices)
+ for (auto idx : label_indices)
{
ARM_COMPUTE_ERROR_ON(idx > static_cast<int>(scores.size()));
score_index_pairs.emplace_back(std::make_pair(scores[idx], std::make_pair(label, idx)));
@@ -536,7 +593,7 @@ void CPPDetectionOutputLayer::run()
// Store the new indices.
std::map<int, std::vector<int>> new_indices;
- for(auto score_index_pair : score_index_pairs)
+ for (auto score_index_pair : score_index_pairs)
{
int label = score_index_pair.second.first;
int idx = score_index_pair.second.second;
@@ -557,25 +614,25 @@ void CPPDetectionOutputLayer::run()
_output->info()->set_valid_region(ValidRegion(Coordinates(0, 0), TensorShape(7, num_kept)));
int count = 0;
- for(int i = 0; i < _num; ++i)
+ for (int i = 0; i < _num; ++i)
{
- const std::map<int, std::vector<float>> &conf_scores = _all_confidence_scores[i];
- const LabelBBox &decode_bboxes = _all_decode_bboxes[i];
- for(auto &it : _all_indices[i])
+ const std::map<int, std::vector<float>> &conf_scores = _all_confidence_scores[i];
+ const LabelBBox &decode_bboxes = _all_decode_bboxes[i];
+ for (auto &it : _all_indices[i])
{
const int label = it.first;
const std::vector<float> &scores = conf_scores.find(label)->second;
const int loc_label = _info.share_location() ? -1 : label;
- if(conf_scores.find(label) == conf_scores.end() || decode_bboxes.find(loc_label) == decode_bboxes.end())
+ if (conf_scores.find(label) == conf_scores.end() || decode_bboxes.find(loc_label) == decode_bboxes.end())
{
// Either if there are no confidence predictions
// or there are no location predictions for current label.
ARM_COMPUTE_ERROR_VAR("Could not find predictions for the label %d.", label);
}
const std::vector<BBox> &bboxes = decode_bboxes.find(loc_label)->second;
- const std::vector<int> &indices = it.second;
+ const std::vector<int> &indices = it.second;
- for(auto idx : indices)
+ for (auto idx : indices)
{
*(reinterpret_cast<float *>(_output->ptr_to_element(Coordinates(count * 7)))) = i;
*(reinterpret_cast<float *>(_output->ptr_to_element(Coordinates(count * 7 + 1)))) = label;
diff --git a/src/runtime/CPP/functions/CPPDetectionPostProcessLayer.cpp b/src/runtime/CPP/functions/CPPDetectionPostProcessLayer.cpp
index 31f1fafd69..2861d6cacb 100644
--- a/src/runtime/CPP/functions/CPPDetectionPostProcessLayer.cpp
+++ b/src/runtime/CPP/functions/CPPDetectionPostProcessLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Arm Limited.
+ * Copyright (c) 2019-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,6 +26,8 @@
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Validate.h"
+
+#include "src/common/utils/Log.h"
#include "src/core/helpers/AutoConfiguration.h"
#include <cstddef>
@@ -36,53 +38,76 @@ namespace arm_compute
{
namespace
{
-Status validate_arguments(const ITensorInfo *input_box_encoding, const ITensorInfo *input_class_score, const ITensorInfo *input_anchors,
- ITensorInfo *output_boxes, ITensorInfo *output_classes, ITensorInfo *output_scores, ITensorInfo *num_detection,
- DetectionPostProcessLayerInfo info, const unsigned int kBatchSize, const unsigned int kNumCoordBox)
+Status validate_arguments(const ITensorInfo *input_box_encoding,
+ const ITensorInfo *input_class_score,
+ const ITensorInfo *input_anchors,
+ ITensorInfo *output_boxes,
+ ITensorInfo *output_classes,
+ ITensorInfo *output_scores,
+ ITensorInfo *num_detection,
+ DetectionPostProcessLayerInfo info,
+ const unsigned int kBatchSize,
+ const unsigned int kNumCoordBox)
{
ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input_box_encoding, input_class_score, input_anchors);
- ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input_box_encoding, 1, DataType::F32, DataType::QASYMM8, DataType::QASYMM8_SIGNED);
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input_box_encoding, 1, DataType::F32, DataType::QASYMM8,
+ DataType::QASYMM8_SIGNED);
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input_box_encoding, input_anchors);
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_box_encoding->num_dimensions() > 3, "The location input tensor shape should be [4, N, kBatchSize].");
- if(input_box_encoding->num_dimensions() > 2)
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_box_encoding->num_dimensions() > 3,
+ "The location input tensor shape should be [4, N, kBatchSize].");
+ if (input_box_encoding->num_dimensions() > 2)
{
- ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(input_box_encoding->dimension(2) != kBatchSize, "The third dimension of the input box_encoding tensor should be equal to %d.", kBatchSize);
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(
+ input_box_encoding->dimension(2) != kBatchSize,
+ "The third dimension of the input box_encoding tensor should be equal to %d.", kBatchSize);
}
- ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(input_box_encoding->dimension(0) != kNumCoordBox, "The first dimension of the input box_encoding tensor should be equal to %d.", kNumCoordBox);
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_class_score->dimension(0) != (info.num_classes() + 1),
- "The first dimension of the input class_prediction should be equal to the number of classes plus one.");
-
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_anchors->num_dimensions() > 3, "The anchors input tensor shape should be [4, N, kBatchSize].");
- if(input_anchors->num_dimensions() > 2)
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(input_box_encoding->dimension(0) != kNumCoordBox,
+ "The first dimension of the input box_encoding tensor should be equal to %d.",
+ kNumCoordBox);
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(
+ input_class_score->dimension(0) != (info.num_classes() + 1),
+ "The first dimension of the input class_prediction should be equal to the number of classes plus one.");
+
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(input_anchors->num_dimensions() > 3,
+ "The anchors input tensor shape should be [4, N, kBatchSize].");
+ if (input_anchors->num_dimensions() > 2)
{
- ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(input_anchors->dimension(0) != kNumCoordBox, "The first dimension of the input anchors tensor should be equal to %d.", kNumCoordBox);
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG_VAR(input_anchors->dimension(0) != kNumCoordBox,
+ "The first dimension of the input anchors tensor should be equal to %d.",
+ kNumCoordBox);
}
- ARM_COMPUTE_RETURN_ERROR_ON_MSG((input_box_encoding->dimension(1) != input_class_score->dimension(1))
- || (input_box_encoding->dimension(1) != input_anchors->dimension(1)),
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG((input_box_encoding->dimension(1) != input_class_score->dimension(1)) ||
+ (input_box_encoding->dimension(1) != input_anchors->dimension(1)),
"The second dimension of the inputs should be the same.");
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(num_detection->num_dimensions() > 1, "The num_detection output tensor shape should be [M].");
- ARM_COMPUTE_RETURN_ERROR_ON_MSG((info.iou_threshold() <= 0.0f) || (info.iou_threshold() > 1.0f), "The intersection over union should be positive and less than 1.");
- ARM_COMPUTE_RETURN_ERROR_ON_MSG(info.max_classes_per_detection() <= 0, "The number of max classes per detection should be positive.");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(num_detection->num_dimensions() > 1,
+ "The num_detection output tensor shape should be [M].");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG((info.iou_threshold() <= 0.0f) || (info.iou_threshold() > 1.0f),
+ "The intersection over union should be positive and less than 1.");
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(info.max_classes_per_detection() <= 0,
+ "The number of max classes per detection should be positive.");
const unsigned int num_detected_boxes = info.max_detections() * info.max_classes_per_detection();
// Validate configured outputs
- if(output_boxes->total_size() != 0)
+ if (output_boxes->total_size() != 0)
{
- ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output_boxes->tensor_shape(), TensorShape(4U, num_detected_boxes, 1U));
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output_boxes->tensor_shape(),
+ TensorShape(4U, num_detected_boxes, 1U));
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output_boxes, 1, DataType::F32);
}
- if(output_classes->total_size() != 0)
+ if (output_classes->total_size() != 0)
{
- ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output_classes->tensor_shape(), TensorShape(num_detected_boxes, 1U));
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output_classes->tensor_shape(),
+ TensorShape(num_detected_boxes, 1U));
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output_classes, 1, DataType::F32);
}
- if(output_scores->total_size() != 0)
+ if (output_scores->total_size() != 0)
{
- ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output_scores->tensor_shape(), TensorShape(num_detected_boxes, 1U));
+ ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(output_scores->tensor_shape(),
+ TensorShape(num_detected_boxes, 1U));
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(output_scores, 1, DataType::F32);
}
- if(num_detection->total_size() != 0)
+ if (num_detection->total_size() != 0)
{
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(num_detection->tensor_shape(), TensorShape(1U));
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(num_detection, 1, DataType::F32);
@@ -91,15 +116,18 @@ Status validate_arguments(const ITensorInfo *input_box_encoding, const ITensorIn
return Status{};
}
-inline void DecodeBoxCorner(BBox &box_centersize, BBox &anchor, Iterator &decoded_it, DetectionPostProcessLayerInfo info)
+inline void
+DecodeBoxCorner(BBox &box_centersize, BBox &anchor, Iterator &decoded_it, DetectionPostProcessLayerInfo info)
{
const float half_factor = 0.5f;
// BBox is equavalent to CenterSizeEncoding [y,x,h,w]
const float y_center = box_centersize[0] / info.scale_value_y() * anchor[2] + anchor[0];
const float x_center = box_centersize[1] / info.scale_value_x() * anchor[3] + anchor[1];
- const float half_h = half_factor * static_cast<float>(std::exp(box_centersize[2] / info.scale_value_h())) * anchor[2];
- const float half_w = half_factor * static_cast<float>(std::exp(box_centersize[3] / info.scale_value_w())) * anchor[3];
+ const float half_h =
+ half_factor * static_cast<float>(std::exp(box_centersize[2] / info.scale_value_h())) * anchor[2];
+ const float half_w =
+ half_factor * static_cast<float>(std::exp(box_centersize[3] / info.scale_value_w())) * anchor[3];
// Box Corner encoding boxes are saved as [xmin, ymin, xmax, ymax]
auto decoded_ptr = reinterpret_cast<float *>(decoded_it.ptr());
@@ -116,12 +144,15 @@ inline void DecodeBoxCorner(BBox &box_centersize, BBox &anchor, Iterator &decode
* @param[in] info The detection informations
* @param[out] decoded_boxes The decoded bboxes.
*/
-void DecodeCenterSizeBoxes(const ITensor *input_box_encoding, const ITensor *input_anchors, DetectionPostProcessLayerInfo info, Tensor *decoded_boxes)
+void DecodeCenterSizeBoxes(const ITensor *input_box_encoding,
+ const ITensor *input_anchors,
+ DetectionPostProcessLayerInfo info,
+ Tensor *decoded_boxes)
{
const QuantizationInfo &qi_box = input_box_encoding->info()->quantization_info();
const QuantizationInfo &qi_anchors = input_anchors->info()->quantization_info();
- BBox box_centersize{ {} };
- BBox anchor{ {} };
+ BBox box_centersize{{}};
+ BBox anchor{{}};
Window win;
win.use_tensor_dimensions(input_box_encoding->info()->tensor_shape());
@@ -131,103 +162,155 @@ void DecodeCenterSizeBoxes(const ITensor *input_box_encoding, const ITensor *inp
Iterator anchor_it(input_anchors, win);
Iterator decoded_it(decoded_boxes, win);
- if(input_box_encoding->info()->data_type() == DataType::QASYMM8)
+ if (input_box_encoding->info()->data_type() == DataType::QASYMM8)
{
- execute_window_loop(win, [&](const Coordinates &)
- {
- const auto box_ptr = reinterpret_cast<const qasymm8_t *>(box_it.ptr());
- const auto anchor_ptr = reinterpret_cast<const qasymm8_t *>(anchor_it.ptr());
- box_centersize = BBox({ dequantize_qasymm8(*box_ptr, qi_box), dequantize_qasymm8(*(box_ptr + 1), qi_box),
- dequantize_qasymm8(*(2 + box_ptr), qi_box), dequantize_qasymm8(*(3 + box_ptr), qi_box)
- });
- anchor = BBox({ dequantize_qasymm8(*anchor_ptr, qi_anchors), dequantize_qasymm8(*(anchor_ptr + 1), qi_anchors),
- dequantize_qasymm8(*(2 + anchor_ptr), qi_anchors), dequantize_qasymm8(*(3 + anchor_ptr), qi_anchors)
- });
- DecodeBoxCorner(box_centersize, anchor, decoded_it, info);
- },
- box_it, anchor_it, decoded_it);
+ execute_window_loop(
+ win,
+ [&](const Coordinates &)
+ {
+ const auto box_ptr = reinterpret_cast<const qasymm8_t *>(box_it.ptr());
+ const auto anchor_ptr = reinterpret_cast<const qasymm8_t *>(anchor_it.ptr());
+ box_centersize =
+ BBox({dequantize_qasymm8(*box_ptr, qi_box), dequantize_qasymm8(*(box_ptr + 1), qi_box),
+ dequantize_qasymm8(*(2 + box_ptr), qi_box), dequantize_qasymm8(*(3 + box_ptr), qi_box)});
+ anchor = BBox({dequantize_qasymm8(*anchor_ptr, qi_anchors),
+ dequantize_qasymm8(*(anchor_ptr + 1), qi_anchors),
+ dequantize_qasymm8(*(2 + anchor_ptr), qi_anchors),
+ dequantize_qasymm8(*(3 + anchor_ptr), qi_anchors)});
+ DecodeBoxCorner(box_centersize, anchor, decoded_it, info);
+ },
+ box_it, anchor_it, decoded_it);
}
- else if(input_box_encoding->info()->data_type() == DataType::QASYMM8_SIGNED)
+ else if (input_box_encoding->info()->data_type() == DataType::QASYMM8_SIGNED)
{
- execute_window_loop(win, [&](const Coordinates &)
- {
- const auto box_ptr = reinterpret_cast<const qasymm8_signed_t *>(box_it.ptr());
- const auto anchor_ptr = reinterpret_cast<const qasymm8_signed_t *>(anchor_it.ptr());
- box_centersize = BBox({ dequantize_qasymm8_signed(*box_ptr, qi_box), dequantize_qasymm8_signed(*(box_ptr + 1), qi_box),
- dequantize_qasymm8_signed(*(2 + box_ptr), qi_box), dequantize_qasymm8_signed(*(3 + box_ptr), qi_box)
- });
- anchor = BBox({ dequantize_qasymm8_signed(*anchor_ptr, qi_anchors), dequantize_qasymm8_signed(*(anchor_ptr + 1), qi_anchors),
- dequantize_qasymm8_signed(*(2 + anchor_ptr), qi_anchors), dequantize_qasymm8_signed(*(3 + anchor_ptr), qi_anchors)
- });
- DecodeBoxCorner(box_centersize, anchor, decoded_it, info);
- },
- box_it, anchor_it, decoded_it);
+ execute_window_loop(
+ win,
+ [&](const Coordinates &)
+ {
+ const auto box_ptr = reinterpret_cast<const qasymm8_signed_t *>(box_it.ptr());
+ const auto anchor_ptr = reinterpret_cast<const qasymm8_signed_t *>(anchor_it.ptr());
+ box_centersize = BBox({dequantize_qasymm8_signed(*box_ptr, qi_box),
+ dequantize_qasymm8_signed(*(box_ptr + 1), qi_box),
+ dequantize_qasymm8_signed(*(2 + box_ptr), qi_box),
+ dequantize_qasymm8_signed(*(3 + box_ptr), qi_box)});
+ anchor = BBox({dequantize_qasymm8_signed(*anchor_ptr, qi_anchors),
+ dequantize_qasymm8_signed(*(anchor_ptr + 1), qi_anchors),
+ dequantize_qasymm8_signed(*(2 + anchor_ptr), qi_anchors),
+ dequantize_qasymm8_signed(*(3 + anchor_ptr), qi_anchors)});
+ DecodeBoxCorner(box_centersize, anchor, decoded_it, info);
+ },
+ box_it, anchor_it, decoded_it);
}
else
{
- execute_window_loop(win, [&](const Coordinates &)
- {
- const auto box_ptr = reinterpret_cast<const float *>(box_it.ptr());
- const auto anchor_ptr = reinterpret_cast<const float *>(anchor_it.ptr());
- box_centersize = BBox({ *box_ptr, *(box_ptr + 1), *(2 + box_ptr), *(3 + box_ptr) });
- anchor = BBox({ *anchor_ptr, *(anchor_ptr + 1), *(2 + anchor_ptr), *(3 + anchor_ptr) });
- DecodeBoxCorner(box_centersize, anchor, decoded_it, info);
- },
- box_it, anchor_it, decoded_it);
+ execute_window_loop(
+ win,
+ [&](const Coordinates &)
+ {
+ const auto box_ptr = reinterpret_cast<const float *>(box_it.ptr());
+ const auto anchor_ptr = reinterpret_cast<const float *>(anchor_it.ptr());
+ box_centersize = BBox({*box_ptr, *(box_ptr + 1), *(2 + box_ptr), *(3 + box_ptr)});
+ anchor = BBox({*anchor_ptr, *(anchor_ptr + 1), *(2 + anchor_ptr), *(3 + anchor_ptr)});
+ DecodeBoxCorner(box_centersize, anchor, decoded_it, info);
+ },
+ box_it, anchor_it, decoded_it);
}
}
-void SaveOutputs(const Tensor *decoded_boxes, const std::vector<int> &result_idx_boxes_after_nms, const std::vector<float> &result_scores_after_nms, const std::vector<int> &result_classes_after_nms,
- std::vector<unsigned int> &sorted_indices, const unsigned int num_output, const unsigned int max_detections, ITensor *output_boxes, ITensor *output_classes, ITensor *output_scores,
- ITensor *num_detection)
+void SaveOutputs(const Tensor *decoded_boxes,
+ const std::vector<int> &result_idx_boxes_after_nms,
+ const std::vector<float> &result_scores_after_nms,
+ const std::vector<int> &result_classes_after_nms,
+ std::vector<unsigned int> &sorted_indices,
+ const unsigned int num_output,
+ const unsigned int max_detections,
+ ITensor *output_boxes,
+ ITensor *output_classes,
+ ITensor *output_scores,
+ ITensor *num_detection)
{
// xmin,ymin,xmax,ymax -> ymin,xmin,ymax,xmax
unsigned int i = 0;
- for(; i < num_output; ++i)
+ for (; i < num_output; ++i)
{
const unsigned int box_in_idx = result_idx_boxes_after_nms[sorted_indices[i]];
- *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(0, i)))) = *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(1, box_in_idx))));
- *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(1, i)))) = *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(0, box_in_idx))));
- *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(2, i)))) = *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(3, box_in_idx))));
- *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(3, i)))) = *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(2, box_in_idx))));
- *(reinterpret_cast<float *>(output_classes->ptr_to_element(Coordinates(i)))) = static_cast<float>(result_classes_after_nms[sorted_indices[i]]);
- *(reinterpret_cast<float *>(output_scores->ptr_to_element(Coordinates(i)))) = result_scores_after_nms[sorted_indices[i]];
+ *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(0, i)))) =
+ *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(1, box_in_idx))));
+ *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(1, i)))) =
+ *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(0, box_in_idx))));
+ *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(2, i)))) =
+ *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(3, box_in_idx))));
+ *(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(3, i)))) =
+ *(reinterpret_cast<float *>(decoded_boxes->ptr_to_element(Coordinates(2, box_in_idx))));
+ *(reinterpret_cast<float *>(output_classes->ptr_to_element(Coordinates(i)))) =
+ static_cast<float>(result_classes_after_nms[sorted_indices[i]]);
+ *(reinterpret_cast<float *>(output_scores->ptr_to_element(Coordinates(i)))) =
+ result_scores_after_nms[sorted_indices[i]];
}
- for(; i < max_detections; ++i)
+ for (; i < max_detections; ++i)
{
*(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(1, i)))) = 0.0f;
*(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(0, i)))) = 0.0f;
*(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(3, i)))) = 0.0f;
*(reinterpret_cast<float *>(output_boxes->ptr_to_element(Coordinates(2, i)))) = 0.0f;
- *(reinterpret_cast<float *>(output_classes->ptr_to_element(Coordinates(i)))) = 0.0f;
- *(reinterpret_cast<float *>(output_scores->ptr_to_element(Coordinates(i)))) = 0.0f;
+ *(reinterpret_cast<float *>(output_classes->ptr_to_element(Coordinates(i)))) = 0.0f;
+ *(reinterpret_cast<float *>(output_scores->ptr_to_element(Coordinates(i)))) = 0.0f;
}
*(reinterpret_cast<float *>(num_detection->ptr_to_element(Coordinates(0)))) = num_output;
}
} // namespace
CPPDetectionPostProcessLayer::CPPDetectionPostProcessLayer(std::shared_ptr<IMemoryManager> memory_manager)
- : _memory_group(std::move(memory_manager)), _nms(), _input_box_encoding(nullptr), _input_scores(nullptr), _input_anchors(nullptr), _output_boxes(nullptr), _output_classes(nullptr),
- _output_scores(nullptr), _num_detection(nullptr), _info(), _num_boxes(), _num_classes_with_background(), _num_max_detected_boxes(), _dequantize_scores(false), _decoded_boxes(), _decoded_scores(),
- _selected_indices(), _class_scores(), _input_scores_to_use(nullptr)
+ : _memory_group(std::move(memory_manager)),
+ _nms(),
+ _input_box_encoding(nullptr),
+ _input_scores(nullptr),
+ _input_anchors(nullptr),
+ _output_boxes(nullptr),
+ _output_classes(nullptr),
+ _output_scores(nullptr),
+ _num_detection(nullptr),
+ _info(),
+ _num_boxes(),
+ _num_classes_with_background(),
+ _num_max_detected_boxes(),
+ _dequantize_scores(false),
+ _decoded_boxes(),
+ _decoded_scores(),
+ _selected_indices(),
+ _class_scores(),
+ _input_scores_to_use(nullptr)
{
}
-void CPPDetectionPostProcessLayer::configure(const ITensor *input_box_encoding, const ITensor *input_scores, const ITensor *input_anchors,
- ITensor *output_boxes, ITensor *output_classes, ITensor *output_scores, ITensor *num_detection, DetectionPostProcessLayerInfo info)
+void CPPDetectionPostProcessLayer::configure(const ITensor *input_box_encoding,
+ const ITensor *input_scores,
+ const ITensor *input_anchors,
+ ITensor *output_boxes,
+ ITensor *output_classes,
+ ITensor *output_scores,
+ ITensor *num_detection,
+ DetectionPostProcessLayerInfo info)
{
- ARM_COMPUTE_ERROR_ON_NULLPTR(input_box_encoding, input_scores, input_anchors, output_boxes, output_classes, output_scores);
+ ARM_COMPUTE_ERROR_ON_NULLPTR(input_box_encoding, input_scores, input_anchors, output_boxes, output_classes,
+ output_scores);
+ ARM_COMPUTE_LOG_PARAMS(input_box_encoding, input_scores, input_anchors, output_boxes, output_classes, output_scores,
+ num_detection, info);
+
_num_max_detected_boxes = info.max_detections() * info.max_classes_per_detection();
- auto_init_if_empty(*output_boxes->info(), TensorInfo(TensorShape(_kNumCoordBox, _num_max_detected_boxes, _kBatchSize), 1, DataType::F32));
- auto_init_if_empty(*output_classes->info(), TensorInfo(TensorShape(_num_max_detected_boxes, _kBatchSize), 1, DataType::F32));
- auto_init_if_empty(*output_scores->info(), TensorInfo(TensorShape(_num_max_detected_boxes, _kBatchSize), 1, DataType::F32));
+ auto_init_if_empty(*output_boxes->info(),
+ TensorInfo(TensorShape(_kNumCoordBox, _num_max_detected_boxes, _kBatchSize), 1, DataType::F32));
+ auto_init_if_empty(*output_classes->info(),
+ TensorInfo(TensorShape(_num_max_detected_boxes, _kBatchSize), 1, DataType::F32));
+ auto_init_if_empty(*output_scores->info(),
+ TensorInfo(TensorShape(_num_max_detected_boxes, _kBatchSize), 1, DataType::F32));
auto_init_if_empty(*num_detection->info(), TensorInfo(TensorShape(1U), 1, DataType::F32));
// Perform validation step
- ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input_box_encoding->info(), input_scores->info(), input_anchors->info(), output_boxes->info(), output_classes->info(), output_scores->info(),
- num_detection->info(),
- info, _kBatchSize, _kNumCoordBox));
+ ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(
+ input_box_encoding->info(), input_scores->info(), input_anchors->info(), output_boxes->info(),
+ output_classes->info(), output_scores->info(), num_detection->info(), info, _kBatchSize, _kNumCoordBox));
_input_box_encoding = input_box_encoding;
_input_scores = input_scores;
@@ -239,13 +322,24 @@ void CPPDetectionPostProcessLayer::configure(const ITensor *input_box_encoding,
_info = info;
_num_boxes = input_box_encoding->info()->dimension(1);
_num_classes_with_background = _input_scores->info()->dimension(0);
- _dequantize_scores = (info.dequantize_scores() && is_data_type_quantized(input_box_encoding->info()->data_type()));
-
- auto_init_if_empty(*_decoded_boxes.info(), TensorInfo(TensorShape(_kNumCoordBox, _input_box_encoding->info()->dimension(1), _kBatchSize), 1, DataType::F32));
- auto_init_if_empty(*_decoded_scores.info(), TensorInfo(TensorShape(_input_scores->info()->dimension(0), _input_scores->info()->dimension(1), _kBatchSize), 1, DataType::F32));
- auto_init_if_empty(*_selected_indices.info(), TensorInfo(TensorShape(info.use_regular_nms() ? info.detection_per_class() : info.max_detections()), 1, DataType::S32));
+ _dequantize_scores = (info.dequantize_scores() && is_data_type_quantized(input_box_encoding->info()->data_type()));
+
+ auto_init_if_empty(*_decoded_boxes.info(),
+ TensorInfo(TensorShape(_kNumCoordBox, _input_box_encoding->info()->dimension(1), _kBatchSize), 1,
+ DataType::F32));
+ auto_init_if_empty(
+ *_decoded_scores.info(),
+ TensorInfo(TensorShape(_input_scores->info()->dimension(0), _input_scores->info()->dimension(1), _kBatchSize),
+ 1, DataType::F32));
+ auto_init_if_empty(
+ *_selected_indices.info(),
+ TensorInfo(TensorShape(info.use_regular_nms() ? info.detection_per_class() : info.max_detections()), 1,
+ DataType::S32));
const unsigned int num_classes_per_box = std::min(info.max_classes_per_detection(), info.num_classes());
- auto_init_if_empty(*_class_scores.info(), TensorInfo(info.use_regular_nms() ? TensorShape(_num_boxes) : TensorShape(_num_boxes * num_classes_per_box), 1, DataType::F32));
+ auto_init_if_empty(
+ *_class_scores.info(),
+ TensorInfo(info.use_regular_nms() ? TensorShape(_num_boxes) : TensorShape(_num_boxes * num_classes_per_box), 1,
+ DataType::F32));
_input_scores_to_use = _dequantize_scores ? &_decoded_scores : _input_scores;
@@ -254,7 +348,9 @@ void CPPDetectionPostProcessLayer::configure(const ITensor *input_box_encoding,
_memory_group.manage(&_decoded_scores);
_memory_group.manage(&_selected_indices);
_memory_group.manage(&_class_scores);
- _nms.configure(&_decoded_boxes, &_class_scores, &_selected_indices, info.use_regular_nms() ? info.detection_per_class() : info.max_detections(), info.nms_score_threshold(), info.iou_threshold());
+ _nms.configure(&_decoded_boxes, &_class_scores, &_selected_indices,
+ info.use_regular_nms() ? info.detection_per_class() : info.max_detections(),
+ info.nms_score_threshold(), info.iou_threshold());
// Allocate and reserve intermediate tensors and vectors
_decoded_boxes.allocator()->allocate();
@@ -263,18 +359,28 @@ void CPPDetectionPostProcessLayer::configure(const ITensor *input_box_encoding,
_class_scores.allocator()->allocate();
}
-Status CPPDetectionPostProcessLayer::validate(const ITensorInfo *input_box_encoding, const ITensorInfo *input_class_score, const ITensorInfo *input_anchors,
- ITensorInfo *output_boxes, ITensorInfo *output_classes, ITensorInfo *output_scores, ITensorInfo *num_detection, DetectionPostProcessLayerInfo info)
+Status CPPDetectionPostProcessLayer::validate(const ITensorInfo *input_box_encoding,
+ const ITensorInfo *input_class_score,
+ const ITensorInfo *input_anchors,
+ ITensorInfo *output_boxes,
+ ITensorInfo *output_classes,
+ ITensorInfo *output_scores,
+ ITensorInfo *num_detection,
+ DetectionPostProcessLayerInfo info)
{
- constexpr unsigned int kBatchSize = 1;
- constexpr unsigned int kNumCoordBox = 4;
- const TensorInfo _decoded_boxes_info = TensorInfo(TensorShape(kNumCoordBox, input_box_encoding->dimension(1)), 1, DataType::F32);
- const TensorInfo _decoded_scores_info = TensorInfo(TensorShape(input_box_encoding->dimension(1)), 1, DataType::F32);
- const TensorInfo _selected_indices_info = TensorInfo(TensorShape(info.max_detections()), 1, DataType::S32);
-
- ARM_COMPUTE_RETURN_ON_ERROR(CPPNonMaximumSuppression::validate(&_decoded_boxes_info, &_decoded_scores_info, &_selected_indices_info, info.max_detections(), info.nms_score_threshold(),
- info.iou_threshold()));
- ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input_box_encoding, input_class_score, input_anchors, output_boxes, output_classes, output_scores, num_detection, info, kBatchSize, kNumCoordBox));
+ constexpr unsigned int kBatchSize = 1;
+ constexpr unsigned int kNumCoordBox = 4;
+ const TensorInfo _decoded_boxes_info =
+ TensorInfo(TensorShape(kNumCoordBox, input_box_encoding->dimension(1)), 1, DataType::F32);
+ const TensorInfo _decoded_scores_info = TensorInfo(TensorShape(input_box_encoding->dimension(1)), 1, DataType::F32);
+ const TensorInfo _selected_indices_info = TensorInfo(TensorShape(info.max_detections()), 1, DataType::S32);
+
+ ARM_COMPUTE_RETURN_ON_ERROR(CPPNonMaximumSuppression::validate(&_decoded_boxes_info, &_decoded_scores_info,
+ &_selected_indices_info, info.max_detections(),
+ info.nms_score_threshold(), info.iou_threshold()));
+ ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input_box_encoding, input_class_score, input_anchors, output_boxes,
+ output_classes, output_scores, num_detection, info, kBatchSize,
+ kNumCoordBox));
return Status{};
}
@@ -287,62 +393,69 @@ void CPPDetectionPostProcessLayer::run()
DecodeCenterSizeBoxes(_input_box_encoding, _input_anchors, _info, &_decoded_boxes);
// Decode scores if necessary
- if(_dequantize_scores)
+ if (_dequantize_scores)
{
- if(_input_box_encoding->info()->data_type() == DataType::QASYMM8)
+ if (_input_box_encoding->info()->data_type() == DataType::QASYMM8)
{
- for(unsigned int idx_c = 0; idx_c < _num_classes_with_background; ++idx_c)
+ for (unsigned int idx_c = 0; idx_c < _num_classes_with_background; ++idx_c)
{
- for(unsigned int idx_b = 0; idx_b < _num_boxes; ++idx_b)
+ for (unsigned int idx_b = 0; idx_b < _num_boxes; ++idx_b)
{
*(reinterpret_cast<float *>(_decoded_scores.ptr_to_element(Coordinates(idx_c, idx_b)))) =
- dequantize_qasymm8(*(reinterpret_cast<qasymm8_t *>(_input_scores->ptr_to_element(Coordinates(idx_c, idx_b)))), _input_scores->info()->quantization_info());
+ dequantize_qasymm8(
+ *(reinterpret_cast<qasymm8_t *>(_input_scores->ptr_to_element(Coordinates(idx_c, idx_b)))),
+ _input_scores->info()->quantization_info());
}
}
}
- else if(_input_box_encoding->info()->data_type() == DataType::QASYMM8_SIGNED)
+ else if (_input_box_encoding->info()->data_type() == DataType::QASYMM8_SIGNED)
{
- for(unsigned int idx_c = 0; idx_c < _num_classes_with_background; ++idx_c)
+ for (unsigned int idx_c = 0; idx_c < _num_classes_with_background; ++idx_c)
{
- for(unsigned int idx_b = 0; idx_b < _num_boxes; ++idx_b)
+ for (unsigned int idx_b = 0; idx_b < _num_boxes; ++idx_b)
{
*(reinterpret_cast<float *>(_decoded_scores.ptr_to_element(Coordinates(idx_c, idx_b)))) =
- dequantize_qasymm8_signed(*(reinterpret_cast<qasymm8_signed_t *>(_input_scores->ptr_to_element(Coordinates(idx_c, idx_b)))), _input_scores->info()->quantization_info());
+ dequantize_qasymm8_signed(*(reinterpret_cast<qasymm8_signed_t *>(
+ _input_scores->ptr_to_element(Coordinates(idx_c, idx_b)))),
+ _input_scores->info()->quantization_info());
}
}
}
}
// Regular NMS
- if(_info.use_regular_nms())
+ if (_info.use_regular_nms())
{
std::vector<int> result_idx_boxes_after_nms;
std::vector<int> result_classes_after_nms;
std::vector<float> result_scores_after_nms;
std::vector<unsigned int> sorted_indices;
- for(unsigned int c = 0; c < num_classes; ++c)
+ for (unsigned int c = 0; c < num_classes; ++c)
{
// For each boxes get scores of the boxes for the class c
- for(unsigned int i = 0; i < _num_boxes; ++i)
+ for (unsigned int i = 0; i < _num_boxes; ++i)
{
*(reinterpret_cast<float *>(_class_scores.ptr_to_element(Coordinates(i)))) =
- *(reinterpret_cast<float *>(_input_scores_to_use->ptr_to_element(Coordinates(c + 1, i)))); // i * _num_classes_with_background + c + 1
+ *(reinterpret_cast<float *>(_input_scores_to_use->ptr_to_element(
+ Coordinates(c + 1, i)))); // i * _num_classes_with_background + c + 1
}
// Run Non-maxima Suppression
_nms.run();
- for(unsigned int i = 0; i < _info.detection_per_class(); ++i)
+ for (unsigned int i = 0; i < _info.detection_per_class(); ++i)
{
- const auto selected_index = *(reinterpret_cast<int *>(_selected_indices.ptr_to_element(Coordinates(i))));
- if(selected_index == -1)
+ const auto selected_index =
+ *(reinterpret_cast<int *>(_selected_indices.ptr_to_element(Coordinates(i))));
+ if (selected_index == -1)
{
// Nms will return -1 for all the last M-elements not valid
break;
}
result_idx_boxes_after_nms.emplace_back(selected_index);
- result_scores_after_nms.emplace_back((reinterpret_cast<float *>(_class_scores.buffer()))[selected_index]);
+ result_scores_after_nms.emplace_back(
+ (reinterpret_cast<float *>(_class_scores.buffer()))[selected_index]);
result_classes_after_nms.emplace_back(c);
}
}
@@ -354,49 +467,46 @@ void CPPDetectionPostProcessLayer::run()
// Sort selected indices based on result scores
sorted_indices.resize(num_selected);
std::iota(sorted_indices.begin(), sorted_indices.end(), 0);
- std::partial_sort(sorted_indices.data(),
- sorted_indices.data() + num_output,
+ std::partial_sort(sorted_indices.data(), sorted_indices.data() + num_output,
sorted_indices.data() + num_selected,
[&](unsigned int first, unsigned int second)
- {
-
- return result_scores_after_nms[first] > result_scores_after_nms[second];
- });
+ { return result_scores_after_nms[first] > result_scores_after_nms[second]; });
- SaveOutputs(&_decoded_boxes, result_idx_boxes_after_nms, result_scores_after_nms, result_classes_after_nms, sorted_indices,
- num_output, max_detections, _output_boxes, _output_classes, _output_scores, _num_detection);
+ SaveOutputs(&_decoded_boxes, result_idx_boxes_after_nms, result_scores_after_nms, result_classes_after_nms,
+ sorted_indices, num_output, max_detections, _output_boxes, _output_classes, _output_scores,
+ _num_detection);
}
// Fast NMS
else
{
- const unsigned int num_classes_per_box = std::min<unsigned int>(_info.max_classes_per_detection(), _info.num_classes());
+ const unsigned int num_classes_per_box =
+ std::min<unsigned int>(_info.max_classes_per_detection(), _info.num_classes());
std::vector<float> max_scores;
std::vector<int> box_indices;
std::vector<int> max_score_classes;
- for(unsigned int b = 0; b < _num_boxes; ++b)
+ for (unsigned int b = 0; b < _num_boxes; ++b)
{
std::vector<float> box_scores;
- for(unsigned int c = 0; c < num_classes; ++c)
+ for (unsigned int c = 0; c < num_classes; ++c)
{
- box_scores.emplace_back(*(reinterpret_cast<float *>(_input_scores_to_use->ptr_to_element(Coordinates(c + 1, b)))));
+ box_scores.emplace_back(
+ *(reinterpret_cast<float *>(_input_scores_to_use->ptr_to_element(Coordinates(c + 1, b)))));
}
std::vector<unsigned int> max_score_indices;
max_score_indices.resize(_info.num_classes());
std::iota(max_score_indices.data(), max_score_indices.data() + _info.num_classes(), 0);
- std::partial_sort(max_score_indices.data(),
- max_score_indices.data() + num_classes_per_box,
+ std::partial_sort(max_score_indices.data(), max_score_indices.data() + num_classes_per_box,
max_score_indices.data() + num_classes,
[&](unsigned int first, unsigned int second)
- {
- return box_scores[first] > box_scores[second];
- });
+ { return box_scores[first] > box_scores[second]; });
- for(unsigned int i = 0; i < num_classes_per_box; ++i)
+ for (unsigned int i = 0; i < num_classes_per_box; ++i)
{
- const float score_to_add = box_scores[max_score_indices[i]];
- *(reinterpret_cast<float *>(_class_scores.ptr_to_element(Coordinates(b * num_classes_per_box + i)))) = score_to_add;
+ const float score_to_add = box_scores[max_score_indices[i]];
+ *(reinterpret_cast<float *>(_class_scores.ptr_to_element(Coordinates(b * num_classes_per_box + i)))) =
+ score_to_add;
max_scores.emplace_back(score_to_add);
box_indices.emplace_back(b);
max_score_classes.emplace_back(max_score_indices[i]);
@@ -406,10 +516,10 @@ void CPPDetectionPostProcessLayer::run()
// Run Non-maxima Suppression
_nms.run();
std::vector<unsigned int> selected_indices;
- for(unsigned int i = 0; i < max_detections; ++i)
+ for (unsigned int i = 0; i < max_detections; ++i)
{
// NMS returns M valid indices, the not valid tail is filled with -1
- if(*(reinterpret_cast<int *>(_selected_indices.ptr_to_element(Coordinates(i)))) == -1)
+ if (*(reinterpret_cast<int *>(_selected_indices.ptr_to_element(Coordinates(i)))) == -1)
{
// Nms will return -1 for all the last M-elements not valid
break;
@@ -419,8 +529,8 @@ void CPPDetectionPostProcessLayer::run()
// We select the max detection numbers of the highest score of all classes
const auto num_output = std::min<unsigned int>(_info.max_detections(), selected_indices.size());
- SaveOutputs(&_decoded_boxes, box_indices, max_scores, max_score_classes, selected_indices,
- num_output, max_detections, _output_boxes, _output_classes, _output_scores, _num_detection);
+ SaveOutputs(&_decoded_boxes, box_indices, max_scores, max_score_classes, selected_indices, num_output,
+ max_detections, _output_boxes, _output_classes, _output_scores, _num_detection);
}
}
} // namespace arm_compute
diff --git a/src/runtime/CPP/functions/CPPNonMaximumSuppression.cpp b/src/runtime/CPP/functions/CPPNonMaximumSuppression.cpp
index d0d0b1e98b..3217742c6b 100644
--- a/src/runtime/CPP/functions/CPPNonMaximumSuppression.cpp
+++ b/src/runtime/CPP/functions/CPPNonMaximumSuppression.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Arm Limited.
+ * Copyright (c) 2019-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,21 +25,32 @@
#include "arm_compute/core/CPP/kernels/CPPNonMaximumSuppressionKernel.h"
+#include "src/common/utils/Log.h"
+
namespace arm_compute
{
-void CPPNonMaximumSuppression::configure(
- const ITensor *bboxes, const ITensor *scores, ITensor *indices, unsigned int max_output_size,
- const float score_threshold, const float nms_threshold)
+void CPPNonMaximumSuppression::configure(const ITensor *bboxes,
+ const ITensor *scores,
+ ITensor *indices,
+ unsigned int max_output_size,
+ const float score_threshold,
+ const float nms_threshold)
{
+ ARM_COMPUTE_LOG_PARAMS(bboxes, scores, indices, max_output_size, score_threshold, nms_threshold);
+
auto k = std::make_unique<CPPNonMaximumSuppressionKernel>();
k->configure(bboxes, scores, indices, max_output_size, score_threshold, nms_threshold);
_kernel = std::move(k);
}
-Status CPPNonMaximumSuppression::validate(
- const ITensorInfo *bboxes, const ITensorInfo *scores, const ITensorInfo *indices, unsigned int max_output_size,
- const float score_threshold, const float nms_threshold)
+Status CPPNonMaximumSuppression::validate(const ITensorInfo *bboxes,
+ const ITensorInfo *scores,
+ const ITensorInfo *indices,
+ unsigned int max_output_size,
+ const float score_threshold,
+ const float nms_threshold)
{
- return CPPNonMaximumSuppressionKernel::validate(bboxes, scores, indices, max_output_size, score_threshold, nms_threshold);
+ return CPPNonMaximumSuppressionKernel::validate(bboxes, scores, indices, max_output_size, score_threshold,
+ nms_threshold);
}
} // namespace arm_compute
diff --git a/src/runtime/CPP/functions/CPPPermute.cpp b/src/runtime/CPP/functions/CPPPermute.cpp
index 76fa09f12b..83941f1dc1 100644
--- a/src/runtime/CPP/functions/CPPPermute.cpp
+++ b/src/runtime/CPP/functions/CPPPermute.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Arm Limited.
+ * Copyright (c) 2017-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,10 +25,14 @@
#include "arm_compute/core/CPP/kernels/CPPPermuteKernel.h"
+#include "src/common/utils/Log.h"
+
using namespace arm_compute;
void CPPPermute::configure(const ITensor *input, ITensor *output, const PermutationVector &perm)
{
+ ARM_COMPUTE_LOG_PARAMS(input, output, perm);
+
auto k = std::make_unique<CPPPermuteKernel>();
k->configure(input, output, perm);
_kernel = std::move(k);
diff --git a/src/runtime/CPP/functions/CPPTopKV.cpp b/src/runtime/CPP/functions/CPPTopKV.cpp
index 2547e56a1d..3d64def804 100644
--- a/src/runtime/CPP/functions/CPPTopKV.cpp
+++ b/src/runtime/CPP/functions/CPPTopKV.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020 Arm Limited.
+ * Copyright (c) 2019-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,16 +25,23 @@
#include "arm_compute/core/CPP/kernels/CPPTopKVKernel.h"
+#include "src/common/utils/Log.h"
+
namespace arm_compute
{
void CPPTopKV::configure(const ITensor *predictions, const ITensor *targets, ITensor *output, const unsigned int k)
{
+ ARM_COMPUTE_LOG_PARAMS(predictions, targets, output, k);
+
auto kernel = std::make_unique<CPPTopKVKernel>();
kernel->configure(predictions, targets, output, k);
_kernel = std::move(kernel);
}
-Status CPPTopKV::validate(const ITensorInfo *predictions, const ITensorInfo *targets, ITensorInfo *output, const unsigned int k)
+Status CPPTopKV::validate(const ITensorInfo *predictions,
+ const ITensorInfo *targets,
+ ITensorInfo *output,
+ const unsigned int k)
{
return CPPTopKVKernel::validate(predictions, targets, output, k);
}
diff --git a/src/runtime/CPP/functions/CPPUpsample.cpp b/src/runtime/CPP/functions/CPPUpsample.cpp
index 3b4ba2ba42..8f72473aeb 100644
--- a/src/runtime/CPP/functions/CPPUpsample.cpp
+++ b/src/runtime/CPP/functions/CPPUpsample.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Arm Limited.
+ * Copyright (c) 2017-2021 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,10 +25,14 @@
#include "arm_compute/core/CPP/kernels/CPPUpsampleKernel.h"
+#include "src/common/utils/Log.h"
+
using namespace arm_compute;
void CPPUpsample::configure(const ITensor *input, ITensor *output, const PadStrideInfo &info)
{
+ ARM_COMPUTE_LOG_PARAMS(input, output, info);
+
auto k = std::make_unique<CPPUpsampleKernel>();
k->configure(input, output, info);
_kernel = std::move(k);