Compute Library
 20.11
CLHarrisCorners.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
25 
27 #include "arm_compute/core/Error.h"
40 #include "support/MemorySupport.h"
41 
42 #include <cmath>
43 #include <utility>
44 
45 using namespace arm_compute;
46 
47 CLHarrisCorners::CLHarrisCorners(std::shared_ptr<IMemoryManager> memory_manager) // NOLINT
48  : _memory_group(std::move(memory_manager)),
49  _sobel(nullptr),
50  _harris_score(support::cpp14::make_unique<CLHarrisScoreKernel>()),
51  _non_max_suppr(),
52  _candidates(),
53  _sort_euclidean(),
54  _border_gx(support::cpp14::make_unique<CLFillBorderKernel>()),
55  _border_gy(support::cpp14::make_unique<CLFillBorderKernel>()),
56  _gx(),
57  _gy(),
58  _score(),
59  _nonmax(),
60  _corners_list(),
61  _num_corner_candidates(0),
62  _corners(nullptr)
63 {
64 }
65 
67 
68 void CLHarrisCorners::configure(ICLImage *input, float threshold, float min_dist,
69  float sensitivity, int32_t gradient_size, int32_t block_size, ICLKeyPointArray *corners,
70  BorderMode border_mode, uint8_t constant_border_value, bool use_fp16)
71 {
72  configure(CLKernelLibrary::get().get_compile_context(), input, threshold, min_dist, sensitivity, gradient_size, block_size, corners, border_mode, constant_border_value, use_fp16);
73 }
74 
75 void CLHarrisCorners::configure(const CLCompileContext &compile_context, ICLImage *input, float threshold, float min_dist,
76  float sensitivity, int32_t gradient_size, int32_t block_size, ICLKeyPointArray *corners,
77  BorderMode border_mode, uint8_t constant_border_value, bool use_fp16)
78 {
79  ARM_COMPUTE_UNUSED(use_fp16); //TODO(COMPMID-772): Add half float support
82  ARM_COMPUTE_ERROR_ON(!(block_size == 3 || block_size == 5 || block_size == 7));
83  ARM_COMPUTE_ERROR_ON(nullptr == corners);
84 
85  _corners = corners;
86 
87  const TensorShape shape = input->info()->tensor_shape();
88  const DataType dt = (gradient_size < 7) ? DataType::S16 : DataType::S32;
89  TensorInfo tensor_info(shape, 1, dt);
90 
91  _gx.allocator()->init(tensor_info);
92  _gy.allocator()->init(tensor_info);
93 
94  TensorInfo info_f32(shape, 1, DataType::F32);
95  _score.allocator()->init(info_f32);
96  _nonmax.allocator()->init(info_f32);
97 
98  _corners_list.resize(shape.x() * shape.y());
99 
100  // Manage intermediate buffers
101  _memory_group.manage(&_gx);
102  _memory_group.manage(&_gy);
103 
104  /* Set/init Sobel kernel accordingly with gradient_size */
105  switch(gradient_size)
106  {
107  case 3:
108  {
109  auto k = arm_compute::support::cpp14::make_unique<CLSobel3x3>();
110  k->configure(compile_context, input, &_gx, &_gy, border_mode, constant_border_value);
111  _sobel = std::move(k);
112  break;
113  }
114  case 5:
115  {
116  auto k = arm_compute::support::cpp14::make_unique<CLSobel5x5>();
117  k->configure(compile_context, input, &_gx, &_gy, border_mode, constant_border_value);
118  _sobel = std::move(k);
119  break;
120  }
121  case 7:
122  {
123  auto k = arm_compute::support::cpp14::make_unique<CLSobel7x7>();
124  k->configure(compile_context, input, &_gx, &_gy, border_mode, constant_border_value);
125  _sobel = std::move(k);
126  break;
127  }
128  default:
129  ARM_COMPUTE_ERROR("Gradient size not implemented");
130  }
131 
132  // Normalization factor
133  const float norm_factor = 1.0f / (255.0f * pow(4.0f, gradient_size / 2) * block_size);
134  const float pow4_normalization_factor = pow(norm_factor, 4);
135 
136  // Manage intermediate buffers
137  _memory_group.manage(&_score);
138 
139  // Set/init Harris Score kernel accordingly with block_size
140  _harris_score->configure(compile_context, &_gx, &_gy, &_score, block_size, pow4_normalization_factor, threshold, sensitivity, border_mode == BorderMode::UNDEFINED);
141 
142  // Configure border filling using harris score kernel's block size
143  _border_gx->configure(compile_context, &_gx, _harris_score->border_size(), border_mode, PixelValue(constant_border_value));
144  _border_gy->configure(compile_context, &_gy, _harris_score->border_size(), border_mode, PixelValue(constant_border_value));
145 
146  // Allocate intermediate buffers
147  _gx.allocator()->allocate();
148  _gy.allocator()->allocate();
149 
150  // Manage intermediate buffers
151  _memory_group.manage(&_nonmax);
152 
153  // Init non-maxima suppression function
154  _non_max_suppr.configure(compile_context, &_score, &_nonmax, border_mode);
155 
156  // Allocate intermediate buffers
157  _score.allocator()->allocate();
158 
159  // Init corner candidates kernel
160  _candidates.configure(&_nonmax, _corners_list.data(), &_num_corner_candidates);
161 
162  // Allocate intermediate buffers
163  _nonmax.allocator()->allocate();
164 
165  // Init euclidean distance
166  _sort_euclidean.configure(_corners_list.data(), _corners, &_num_corner_candidates, min_dist);
167 }
168 
170 {
171  ARM_COMPUTE_ERROR_ON_MSG(_sobel == nullptr, "Unconfigured function");
172 
173  MemoryGroupResourceScope scope_mg(_memory_group);
174 
175  // Init to 0 number of corner candidates
176  _num_corner_candidates = 0;
177 
178  // Run Sobel kernel
179  _sobel->run();
180 
181  // Fill border before harris score kernel
182  CLScheduler::get().enqueue(*_border_gx, false);
183  CLScheduler::get().enqueue(*_border_gy, false);
184 
185  // Run harris score kernel
186  CLScheduler::get().enqueue(*_harris_score, false);
187 
188  // Run non-maxima suppression
189  _non_max_suppr.run();
190 
191  // Run corner candidate kernel
192  _nonmax.map(true);
193  Scheduler::get().schedule(&_candidates, Window::DimY);
194  _nonmax.unmap();
195 
196  _corners->map(CLScheduler::get().queue(), true);
197  Scheduler::get().schedule(&_sort_euclidean, Window::DimY);
198  _corners->unmap(CLScheduler::get().queue());
199 }
BorderMode
Methods available to handle borders.
Definition: Types.h:265
Class describing the value of a pixel for any image format.
Definition: PixelValue.h:34
~CLHarrisCorners()
Default destructor.
Shape of a tensor.
Definition: TensorShape.h:39
#define ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(t)
Definition: Validate.h:856
static CLScheduler & get()
Access the scheduler singleton.
Definition: CLScheduler.cpp:99
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
1 channel, 1 U8 per channel
1 channel, 1 F32 per channel
void map(cl::CommandQueue &q, bool blocking=true)
Enqueue a map operation of the allocated buffer on the given queue.
Definition: ICLArray.h:72
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
static CLKernelLibrary & get()
Access the KernelLibrary singleton.
CLTensorAllocator * allocator()
Return a pointer to the tensor's allocator.
Definition: CLTensor.cpp:61
void init(const TensorInfo &input, size_t alignment=0)
Initialize a tensor based on the passed TensorInfo.
Copyright (c) 2017-2020 Arm Limited.
void map(bool blocking=true)
Enqueue a map operation of the allocated buffer.
Definition: CLTensor.cpp:66
1 channel, 1 S32 per channel
void manage(IMemoryManageable *obj) override
Sets a object to be managed by the given memory group.
Definition: MemoryGroup.h:79
Interface to enqueue OpenCL kernels and get/set the OpenCL CommandQueue and ICLTuner.
void configure(InternalKeypoint *in_out, IKeyPointArray *output, const int32_t *num_corner_candidates, float min_distance)
Initialise the kernel's source, destination and border mode.
Interface for OpenCL Array.
Definition: ICLArray.h:35
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
void run() override final
Run the kernels contained in the function.
void configure(ICLTensor *input, ICLTensor *output, BorderMode border_mode)
Initialise the function's source, destinations and border mode.
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
_Unique_if< T >::_Single_object make_unique(Args &&... args)
Construct a single object and return a unique pointer to it.
Definition: MemorySupport.h:88
Interface for the harris score kernel.
1 channel, 1 S16 per channel
void enqueue(ICLKernel &kernel, bool flush=true)
Schedule the execution of the passed kernel if possible.
#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:790
CLCompileContext class.
DataType dt
void unmap(cl::CommandQueue &q)
Enqueue an unmap operation of the allocated and mapped buffer on the given queue.
Definition: ICLArray.h:83
void allocate() override
Allocate size specified by TensorInfo of OpenCL memory.
static constexpr size_t DimY
Alias for dimension 1 also known as Y dimension.
Definition: Window.h:45
Interface for filling the border of a kernel.
Memory group resources scope handling class.
Definition: IMemoryGroup.h:82
Interface for OpenCL tensor.
Definition: ICLTensor.h:42
virtual void schedule(ICPPKernel *kernel, const Hints &hints)=0
Runs the kernel in the same thread as the caller synchronously.
Borders are left undefined.
void run() override
Run the kernels contained in the function.
Wrapper to configure the Khronos OpenCL C++ header.
Store the tensor's metadata.
Definition: TensorInfo.h:45
void configure(ICLImage *input, float threshold, float min_dist, float sensitivity, int32_t gradient_size, int32_t block_size, ICLKeyPointArray *corners, BorderMode border_mode, uint8_t constant_border_value=0, bool use_fp16=false)
Initialize the function's source, destination, conv and border_mode.
DataType
Available data types.
Definition: Types.h:77
void unmap()
Enqueue an unmap operation of the allocated and mapped buffer.
Definition: CLTensor.cpp:71
SimpleTensor< T > threshold(const SimpleTensor< T > &src, T threshold, T false_value, T true_value, ThresholdType type, T upper)
Definition: Threshold.cpp:35
CLHarrisCorners(std::shared_ptr< IMemoryManager > memory_manager=nullptr)
Constructor.
void configure(const IImage *input, InternalKeypoint *output, int32_t *num_corner_candidates)
Setup the kernel parameters.
static IScheduler & get()
Access the scheduler singleton.
Definition: Scheduler.cpp:95