Compute Library
 19.08
CLCannyEdge Class Reference

Basic function to execute canny edge on OpenCL. More...

#include <CLCannyEdge.h>

Collaboration diagram for CLCannyEdge:
[legend]

Public Member Functions

 CLCannyEdge (std::shared_ptr< IMemoryManager > memory_manager=nullptr)
 Constructor. More...
 
 CLCannyEdge (const CLCannyEdge &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
CLCannyEdgeoperator= (const CLCannyEdge &)=delete
 Prevent instances of this class from being copied (As this class contains pointers) More...
 
void configure (ICLTensor *input, ICLTensor *output, int32_t upper_thr, int32_t lower_thr, int32_t gradient_size, int32_t norm_type, BorderMode border_mode, uint8_t constant_border_value=0)
 Initialise the function's source, destination, thresholds, gradient size, normalization type and border mode. More...
 
virtual void run () override
 Run the kernels contained in the function. More...
 
- Public Member Functions inherited from IFunction
virtual ~IFunction ()=default
 Destructor. More...
 
virtual void prepare ()
 Prepare the function for executing. More...
 

Detailed Description

Basic function to execute canny edge on OpenCL.

This function calls the following OpenCL kernels and functions:

  1. CLFillBorderKernel (if border_mode == REPLICATE or border_mode == CONSTANT)
  2. CLSobel3x3 (if gradient_size == 3) or CLSobel5x5 (if gradient_size == 5) or CLSobel7x7 (if gradient_size == 7)
  3. CLGradientKernel
  4. CLEdgeNonMaxSuppressionKernel
  5. CLEdgeTraceKernel

Definition at line 50 of file CLCannyEdge.h.

Constructor & Destructor Documentation

◆ CLCannyEdge() [1/2]

CLCannyEdge ( std::shared_ptr< IMemoryManager memory_manager = nullptr)

Constructor.

Definition at line 38 of file CLCannyEdge.cpp.

39  : _memory_group(std::move(memory_manager)),
40  _sobel(),
41  _gradient(),
42  _border_mag_gradient(),
43  _non_max_suppr(),
44  _edge_trace(),
45  _gx(),
46  _gy(),
47  _mag(),
48  _phase(),
49  _nonmax(),
50  _visited(),
51  _recorded(),
52  _l1_list_counter(),
53  _l1_stack(),
54  _output(nullptr)
55 {
56 }

◆ CLCannyEdge() [2/2]

CLCannyEdge ( const CLCannyEdge )
delete

Prevent instances of this class from being copied (As this class contains pointers)

Member Function Documentation

◆ configure()

void configure ( ICLTensor input,
ICLTensor output,
int32_t  upper_thr,
int32_t  lower_thr,
int32_t  gradient_size,
int32_t  norm_type,
BorderMode  border_mode,
uint8_t  constant_border_value = 0 
)

Initialise the function's source, destination, thresholds, gradient size, normalization type and border mode.

Parameters
[in,out]inputSource tensor. Data types supported: U8. (Written to only for border_mode != UNDEFINED)
[out]outputDestination tensor. Data types supported: U8.
[in]upper_thrUpper threshold used for the hysteresis.
[in]lower_thrLower threshold used for the hysteresis.
[in]gradient_sizeGradient size (3, 5 or 7).
[in]norm_typeNormalization type. if 1, L1-Norm otherwise L2-Norm.
[in]border_modeBorder mode to use for the convolution.
[in]constant_border_value(Optional) Constant value to use for borders if border_mode is set to CONSTANT.

Definition at line 58 of file CLCannyEdge.cpp.

60 {
61  ARM_COMPUTE_ERROR_ON_NULLPTR(input, output);
64  ARM_COMPUTE_ERROR_ON((1 != norm_type) && (2 != norm_type));
65  ARM_COMPUTE_ERROR_ON((gradient_size != 3) && (gradient_size != 5) && (gradient_size != 7));
66  ARM_COMPUTE_ERROR_ON((lower_thr < 0) || (lower_thr >= upper_thr));
67 
68  _output = output;
69 
70  const unsigned int L1_hysteresis_stack_size = 8;
71  const TensorShape shape = input->info()->tensor_shape();
72 
73  TensorInfo gradient_info;
75 
76  // Initialize images
77  if(gradient_size < 7)
78  {
79  gradient_info.init(shape, 1, arm_compute::DataType::S16);
81  }
82  else
83  {
84  gradient_info.init(shape, 1, arm_compute::DataType::S32);
86  }
87 
88  _gx.allocator()->init(gradient_info);
89  _gy.allocator()->init(gradient_info);
90  _mag.allocator()->init(info);
91  _nonmax.allocator()->init(info);
92 
94  _phase.allocator()->init(info_u8);
95  _l1_list_counter.allocator()->init(info_u8);
96 
98  _visited.allocator()->init(info_u32);
99  _recorded.allocator()->init(info_u32);
100 
101  TensorShape shape_l1_stack = input->info()->tensor_shape();
102  shape_l1_stack.set(0, input->info()->dimension(0) * L1_hysteresis_stack_size);
103  TensorInfo info_s32(shape_l1_stack, 1, arm_compute::DataType::S32);
104  _l1_stack.allocator()->init(info_s32);
105 
106  // Manage intermediate buffers
107  _memory_group.manage(&_gx);
108  _memory_group.manage(&_gy);
109 
110  // Configure/Init sobelNxN
111  if(gradient_size == 3)
112  {
113  auto k = arm_compute::support::cpp14::make_unique<CLSobel3x3>();
114  k->configure(input, &_gx, &_gy, border_mode, constant_border_value);
115  _sobel = std::move(k);
116  }
117  else if(gradient_size == 5)
118  {
119  auto k = arm_compute::support::cpp14::make_unique<CLSobel5x5>();
120  k->configure(input, &_gx, &_gy, border_mode, constant_border_value);
121  _sobel = std::move(k);
122  }
123  else if(gradient_size == 7)
124  {
125  auto k = arm_compute::support::cpp14::make_unique<CLSobel7x7>();
126  k->configure(input, &_gx, &_gy, border_mode, constant_border_value);
127  _sobel = std::move(k);
128  }
129  else
130  {
131  ARM_COMPUTE_ERROR("Gradient size %d not supported", gradient_size);
132  }
133 
134  // Manage intermediate buffers
135  _memory_group.manage(&_mag);
136  _memory_group.manage(&_phase);
137 
138  // Configure gradient
139  _gradient.configure(&_gx, &_gy, &_mag, &_phase, norm_type);
140 
141  // Allocate intermediate buffers
142  _gx.allocator()->allocate();
143  _gy.allocator()->allocate();
144 
145  // Manage intermediate buffers
146  _memory_group.manage(&_nonmax);
147 
148  // Configure non-maxima suppression
149  _non_max_suppr.configure(&_mag, &_phase, &_nonmax, lower_thr, border_mode == BorderMode::UNDEFINED);
150 
151  // Allocate intermediate buffers
152  _phase.allocator()->allocate();
153 
154  // Fill border around magnitude image as non-maxima suppression will access
155  // it. If border mode is undefined filling the border is a nop.
156  _border_mag_gradient.configure(&_mag, _non_max_suppr.border_size(), border_mode, constant_border_value);
157 
158  // Allocate intermediate buffers
159  _mag.allocator()->allocate();
160 
161  // Manage intermediate buffers
162  _memory_group.manage(&_visited);
163  _memory_group.manage(&_recorded);
164  _memory_group.manage(&_l1_stack);
165  _memory_group.manage(&_l1_list_counter);
166 
167  // Configure edge tracing
168  _edge_trace.configure(&_nonmax, output, upper_thr, lower_thr, &_visited, &_recorded, &_l1_stack, &_l1_list_counter);
169 
170  // Allocate intermediate buffers
171  _visited.allocator()->allocate();
172  _recorded.allocator()->allocate();
173  _l1_stack.allocator()->allocate();
174  _l1_list_counter.allocator()->allocate();
175  _nonmax.allocator()->allocate();
176 }
#define ARM_COMPUTE_ERROR(...)
Print the given message then throw an std::runtime_error.
Definition: Error.h:261
void configure(const ICLTensor *magnitude, const ICLTensor *phase, ICLTensor *output, int32_t lower_thr, bool border_undefined)
Initialise the kernel's sources, destination and border mode.
Shape of a tensor.
Definition: TensorShape.h:39
virtual size_t dimension(size_t index) const =0
Return the size of the requested dimension.
1 channel, 1 U8 per channel
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:337
CLTensorAllocator * allocator()
Return a pointer to the tensor's allocator.
Definition: CLTensor.cpp:55
1 channel, 1 U16 per channel
void configure(ICLTensor *tensor, BorderSize border_size, BorderMode border_mode, const PixelValue &constant_border_value=PixelValue())
Initialise the kernel's input, output and border mode.
void init(const TensorInfo &input, size_t alignment=0)
Initialize a tensor based on the passed TensorInfo.
1 channel, 1 S32 per channel
void manage(TensorType *obj)
Sets a object to be managed by the given memory group.
1 channel, 1 U32 per channel
virtual const TensorShape & tensor_shape() const =0
Size for each dimension of the tensor.
virtual ITensorInfo * info() const =0
Interface to be implemented by the child class to return the tensor's metadata.
1 channel, 1 S16 per channel
#define ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:789
void init(Format format)
Initialize the tensor info with just a format.
Definition: TensorInfo.cpp:99
void allocate() override
Allocate size specified by TensorInfo of OpenCL memory.
void configure(const ICLTensor *gx, const ICLTensor *gy, ICLTensor *magnitude, ICLTensor *phase, int32_t norm_type)
Initialise the kernel's sources, destinations and border mode.
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:161
void configure(const ICLTensor *input, ICLTensor *output, int32_t upper_thr, int32_t lower_thr, ICLTensor *visited, ICLTensor *recorded, ICLTensor *l1_stack, ICLTensor *l1_stack_counter)
Initialise the kernel's source, destination and border mode.
Borders are left undefined.
TensorShape & set(size_t dimension, size_t value, bool apply_dim_correction=true)
Accessor to set the value of one of the dimensions.
Definition: TensorShape.h:78
Store the tensor's metadata.
Definition: TensorInfo.h:45
BorderSize border_size() const override
The size of the border for that kernel.

References CLTensorAllocator::allocate(), CLTensor::allocator(), ARM_COMPUTE_ERROR, ARM_COMPUTE_ERROR_ON, ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN, ARM_COMPUTE_ERROR_ON_NULLPTR, arm_compute::test::validation::border_mode, CLEdgeNonMaxSuppressionKernel::border_size(), CLGradientKernel::configure(), CLFillBorderKernel::configure(), CLEdgeNonMaxSuppressionKernel::configure(), CLEdgeTraceKernel::configure(), ITensorInfo::dimension(), ITensor::info(), arm_compute::test::validation::info, ITensorAllocator::init(), TensorInfo::init(), MemoryGroupBase< TensorType >::manage(), arm_compute::S16, arm_compute::S32, TensorShape::set(), arm_compute::test::validation::shape, ITensorInfo::tensor_shape(), arm_compute::U16, arm_compute::U32, arm_compute::U8, and arm_compute::UNDEFINED.

Referenced by arm_compute::test::validation::DATA_TEST_CASE().

◆ operator=()

CLCannyEdge& operator= ( const CLCannyEdge )
delete

Prevent instances of this class from being copied (As this class contains pointers)

◆ run()

void run ( )
overridevirtual

Run the kernels contained in the function.

For NEON kernels:

  • Multi-threading is used for the kernels which are parallelisable.
  • By default std::thread::hardware_concurrency() threads are used.
Note
CPPScheduler::set_num_threads() can be used to manually set the number of threads

For OpenCL kernels:

  • All the kernels are enqueued on the queue associated with CLScheduler.
  • The queue is then flushed.
Note
The function will not block until the kernels are executed. It is the user's responsibility to wait.
Will call prepare() on first run if hasn't been done

Implements IFunction.

Definition at line 178 of file CLCannyEdge.cpp.

179 {
180  MemoryGroupResourceScope scope_mg(_memory_group);
181 
182  // Run sobel
183  _sobel->run();
184 
185  // Run phase and magnitude calculation
186  CLScheduler::get().enqueue(_gradient, false);
187 
188  // Fill border before non-maxima suppression. Nop for border mode undefined.
189  CLScheduler::get().enqueue(_border_mag_gradient, false);
190 
191  // Run non max suppresion
192  _nonmax.clear(CLScheduler::get().queue());
193  CLScheduler::get().enqueue(_non_max_suppr, false);
194 
195  // Clear temporary structures and run edge trace
196  _output->clear(CLScheduler::get().queue());
197  _visited.clear(CLScheduler::get().queue());
198  _recorded.clear(CLScheduler::get().queue());
199  _l1_list_counter.clear(CLScheduler::get().queue());
200  _l1_stack.clear(CLScheduler::get().queue());
201  CLScheduler::get().enqueue(_edge_trace, true);
202 }
static CLScheduler & get()
Access the scheduler singleton.
Definition: CLScheduler.cpp:41
void clear(cl::CommandQueue &q)
Clear the contents of the tensor synchronously.
Definition: ICLTensor.cpp:46
void enqueue(ICLKernel &kernel, bool flush=true)
Schedule the execution of the passed kernel if possible.
Definition: CLScheduler.cpp:95
Memory group resources scope handling class.
Definition: IMemoryGroup.h:46

References ICLTensor::clear(), CLScheduler::enqueue(), and CLScheduler::get().


The documentation for this class was generated from the following files: