1 /*
2 * Copyright (c) 2017-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 */
24 #include "arm_compute/runtime/CL/functions/CLHOGDescriptor.h"
25
26 #include "arm_compute/core/Error.h"
27 #include "arm_compute/core/HOGInfo.h"
28 #include "arm_compute/core/Size2D.h"
29 #include "arm_compute/core/Validate.h"
30 #include "arm_compute/runtime/CL/CLScheduler.h"
31 #include "src/core/CL/kernels/CLFillBorderKernel.h"
32 #include "src/core/CL/kernels/CLHOGDescriptorKernel.h"
33 #include "src/core/CL/kernels/CLMagnitudePhaseKernel.h"
34 #include "support/MemorySupport.h"
35
36 using namespace arm_compute;
37
CLHOGDescriptor(std::shared_ptr<IMemoryManager> memory_manager)38 CLHOGDescriptor::CLHOGDescriptor(std::shared_ptr<IMemoryManager> memory_manager)
39 : _memory_group(std::move(memory_manager)),
40 _gradient(),
41 _orient_bin(support::cpp14::make_unique<CLHOGOrientationBinningKernel>()),
42 _block_norm(support::cpp14::make_unique<CLHOGBlockNormalizationKernel>()),
43 _mag(),
44 _phase(),
45 _hog_space()
46 {
47 }
48
49 CLHOGDescriptor::~CLHOGDescriptor() = default;
50
configure(ICLTensor * input,ICLTensor * output,const IHOG * hog,BorderMode border_mode,uint8_t constant_border_value)51 void CLHOGDescriptor::configure(ICLTensor *input, ICLTensor *output, const IHOG *hog, BorderMode border_mode, uint8_t constant_border_value)
52 {
53 configure(CLKernelLibrary::get().get_compile_context(), input, output, hog, border_mode, constant_border_value);
54 }
55
configure(const CLCompileContext & compile_context,ICLTensor * input,ICLTensor * output,const IHOG * hog,BorderMode border_mode,uint8_t constant_border_value)56 void CLHOGDescriptor::configure(const CLCompileContext &compile_context, ICLTensor *input, ICLTensor *output, const IHOG *hog, BorderMode border_mode, uint8_t constant_border_value)
57 {
58 ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8);
59 ARM_COMPUTE_ERROR_ON(nullptr == output);
60 ARM_COMPUTE_ERROR_ON(nullptr == hog);
61
62 const HOGInfo *hog_info = hog->info();
63 const size_t width = input->info()->dimension(Window::DimX);
64 const size_t height = input->info()->dimension(Window::DimY);
65 const size_t num_bins = hog_info->num_bins();
66
67 Size2D cell_size = hog_info->cell_size();
68
69 // Calculate number of cells along the x and y directions for the hog_space
70 const size_t num_cells_x = width / cell_size.width;
71 const size_t num_cells_y = height / cell_size.height;
72
73 // TensorShape of the input image
74 const TensorShape &shape_img = input->info()->tensor_shape();
75
76 // TensorShape of the hog space
77 TensorShape shape_hog_space = input->info()->tensor_shape();
78 shape_hog_space.set(Window::DimX, num_cells_x);
79 shape_hog_space.set(Window::DimY, num_cells_y);
80
81 // Intitialize tensors for magnitude, phase and hog space
82 TensorInfo info_mag(shape_img, Format::S16);
83 _mag.allocator()->init(info_mag);
84
85 TensorInfo info_phase(shape_img, Format::U8);
86 _phase.allocator()->init(info_phase);
87
88 TensorInfo info_space(shape_hog_space, num_bins, DataType::F32);
89 _hog_space.allocator()->init(info_space);
90
91 // Manage intermediate buffers
92 _memory_group.manage(&_mag);
93 _memory_group.manage(&_phase);
94
95 // Initialise gradient kernel
96 _gradient.configure(compile_context, input, &_mag, &_phase, hog_info->phase_type(), border_mode, constant_border_value);
97
98 // Manage intermediate buffers
99 _memory_group.manage(&_hog_space);
100
101 // Initialise orientation binning kernel
102 _orient_bin->configure(compile_context, &_mag, &_phase, &_hog_space, hog->info());
103
104 // Initialize HOG norm kernel
105 _block_norm->configure(compile_context, &_hog_space, output, hog->info());
106
107 // Allocate intermediate tensors
108 _mag.allocator()->allocate();
109 _phase.allocator()->allocate();
110 _hog_space.allocator()->allocate();
111 }
112
run()113 void CLHOGDescriptor::run()
114 {
115 MemoryGroupResourceScope scope_mg(_memory_group);
116
117 // Run gradient
118 _gradient.run();
119
120 // Run orientation binning
121 CLScheduler::get().enqueue(*_orient_bin, false);
122
123 // Run block normalization
124 CLScheduler::get().enqueue(*_block_norm);
125 }