Compute Library
 21.02
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 
41 #include <cmath>
42 #include <utility>
43 
44 using namespace arm_compute;
45 
46 CLHarrisCorners::CLHarrisCorners(std::shared_ptr<IMemoryManager> memory_manager) // NOLINT
47  : _memory_group(std::move(memory_manager)),
48  _sobel(nullptr),
49  _harris_score(std::make_unique<CLHarrisScoreKernel>()),
50  _non_max_suppr(),
51  _candidates(),
52  _sort_euclidean(),
53  _border_gx(std::make_unique<CLFillBorderKernel>()),
54  _border_gy(std::make_unique<CLFillBorderKernel>()),
55  _gx(),
56  _gy(),
57  _score(),
58  _nonmax(),
59  _corners_list(),
60  _num_corner_candidates(0),
61  _corners(nullptr)
62 {
63 }
64 
66 
67 void CLHarrisCorners::configure(ICLImage *input, float threshold, float min_dist,
68  float sensitivity, int32_t gradient_size, int32_t block_size, ICLKeyPointArray *corners,
69  BorderMode border_mode, uint8_t constant_border_value, bool use_fp16)
70 {
71  configure(CLKernelLibrary::get().get_compile_context(), input, threshold, min_dist, sensitivity, gradient_size, block_size, corners, border_mode, constant_border_value, use_fp16);
72 }
73 
74 void CLHarrisCorners::configure(const CLCompileContext &compile_context, ICLImage *input, float threshold, float min_dist,
75  float sensitivity, int32_t gradient_size, int32_t block_size, ICLKeyPointArray *corners,
76  BorderMode border_mode, uint8_t constant_border_value, bool use_fp16)
77 {
78  ARM_COMPUTE_UNUSED(use_fp16); //TODO(COMPMID-772): Add half float support
81  ARM_COMPUTE_ERROR_ON(!(block_size == 3 || block_size == 5 || block_size == 7));
82  ARM_COMPUTE_ERROR_ON(nullptr == corners);
83 
84  _corners = corners;
85 
86  const TensorShape shape = input->info()->tensor_shape();
87  const DataType dt = (gradient_size < 7) ? DataType::S16 : DataType::S32;
88  TensorInfo tensor_info(shape, 1, dt);
89 
90  _gx.allocator()->init(tensor_info);
91  _gy.allocator()->init(tensor_info);
92 
93  TensorInfo info_f32(shape, 1, DataType::F32);
94  _score.allocator()->init(info_f32);
95  _nonmax.allocator()->init(info_f32);
96 
97  _corners_list.resize(shape.x() * shape.y());
98 
99  // Manage intermediate buffers
100  _memory_group.manage(&_gx);
101  _memory_group.manage(&_gy);
102 
103  /* Set/init Sobel kernel accordingly with gradient_size */
104  switch(gradient_size)
105  {
106  case 3:
107  {
108  auto k = std::make_unique<CLSobel3x3>();
109  k->configure(compile_context, input, &_gx, &_gy, border_mode, constant_border_value);
110  _sobel = std::move(k);
111  break;
112  }
113  case 5:
114  {
115  auto k = std::make_unique<CLSobel5x5>();
116  k->configure(compile_context, input, &_gx, &_gy, border_mode, constant_border_value);
117  _sobel = std::move(k);
118  break;
119  }
120  case 7:
121  {
122  auto k = std::make_unique<CLSobel7x7>();
123  k->configure(compile_context, input, &_gx, &_gy, border_mode, constant_border_value);
124  _sobel = std::move(k);
125  break;
126  }
127  default:
128  ARM_COMPUTE_ERROR("Gradient size not implemented");
129  }
130 
131  // Normalization factor
132  const float norm_factor = 1.0f / (255.0f * pow(4.0f, gradient_size / 2) * block_size);
133  const float pow4_normalization_factor = pow(norm_factor, 4);
134 
135  // Manage intermediate buffers
136  _memory_group.manage(&_score);
137 
138  // Set/init Harris Score kernel accordingly with block_size
139  _harris_score->configure(compile_context, &_gx, &_gy, &_score, block_size, pow4_normalization_factor, threshold, sensitivity, border_mode == BorderMode::UNDEFINED);
140 
141  // Configure border filling using harris score kernel's block size
142  _border_gx->configure(compile_context, &_gx, _harris_score->border_size(), border_mode, PixelValue(constant_border_value));
143  _border_gy->configure(compile_context, &_gy, _harris_score->border_size(), border_mode, PixelValue(constant_border_value));
144 
145  // Allocate intermediate buffers
146  _gx.allocator()->allocate();
147  _gy.allocator()->allocate();
148 
149  // Manage intermediate buffers
150  _memory_group.manage(&_nonmax);
151 
152  // Init non-maxima suppression function
153  _non_max_suppr.configure(compile_context, &_score, &_nonmax, border_mode);
154 
155  // Allocate intermediate buffers
156  _score.allocator()->allocate();
157 
158  // Init corner candidates kernel
159  _candidates.configure(&_nonmax, _corners_list.data(), &_num_corner_candidates);
160 
161  // Allocate intermediate buffers
162  _nonmax.allocator()->allocate();
163 
164  // Init euclidean distance
165  _sort_euclidean.configure(_corners_list.data(), _corners, &_num_corner_candidates, min_dist);
166 }
167 
169 {
170  ARM_COMPUTE_ERROR_ON_MSG(_sobel == nullptr, "Unconfigured function");
171 
172  MemoryGroupResourceScope scope_mg(_memory_group);
173 
174  // Init to 0 number of corner candidates
175  _num_corner_candidates = 0;
176 
177  // Run Sobel kernel
178  _sobel->run();
179 
180  // Fill border before harris score kernel
181  CLScheduler::get().enqueue(*_border_gx, false);
182  CLScheduler::get().enqueue(*_border_gy, false);
183 
184  // Run harris score kernel
185  CLScheduler::get().enqueue(*_harris_score, false);
186 
187  // Run non-maxima suppression
188  _non_max_suppr.run();
189 
190  // Run corner candidate kernel
191  _nonmax.map(true);
192  Scheduler::get().schedule(&_candidates, Window::DimY);
193  _nonmax.unmap();
194 
195  _corners->map(CLScheduler::get().queue(), true);
196  Scheduler::get().schedule(&_sort_euclidean, Window::DimY);
197  _corners->unmap(CLScheduler::get().queue());
198 }
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.
#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&#39;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-2021 Arm Limited.
void map(bool blocking=true)
Enqueue a map operation of the allocated buffer.
Definition: CLTensor.cpp:66
DataType dt
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
T x() const
Alias to access the size of the first dimension.
Definition: Dimensions.h:87
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&#39;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&#39;s source, destinations and border mode.
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
#define ARM_COMPUTE_ERROR_ON_MSG(cond, msg)
Definition: Error.h:456
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor&#39;s metadata.
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.
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&#39;s metadata.
Definition: TensorInfo.h:45
T y() const
Alias to access the size of the second dimension.
Definition: Dimensions.h:92
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&#39;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:94