blob: 2c736790588805d9abea77a5fd15fb64a57b827d [file] [log] [blame]
Giorgio Arenafc2817d2017-06-27 17:26:37 +01001/*
2 * Copyright (c) 2017 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 */
Giorgio Arenafc2817d2017-06-27 17:26:37 +010024#include "CL/CLAccessor.h"
Giorgio Arenafc2817d2017-06-27 17:26:37 +010025#include "TypePrinter.h"
26#include "Utils.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010027#include "tests/AssetsLibrary.h"
28#include "tests/Globals.h"
29#include "tests/validation_old/Datasets.h"
30#include "tests/validation_old/Reference.h"
31#include "tests/validation_old/Validation.h"
32#include "tests/validation_old/ValidationUserConfiguration.h"
Giorgio Arenafc2817d2017-06-27 17:26:37 +010033
34#include "arm_compute/core/Helpers.h"
35#include "arm_compute/core/Types.h"
36#include "arm_compute/runtime/CL/CLArray.h"
37#include "arm_compute/runtime/CL/functions/CLHarrisCorners.h"
38#include "arm_compute/runtime/Tensor.h"
39#include "arm_compute/runtime/TensorAllocator.h"
40
41#include "PaddingCalculator.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010042#include "tests/validation_old/boost_wrapper.h"
Giorgio Arenafc2817d2017-06-27 17:26:37 +010043
44#include <random>
45#include <string>
46
47using namespace arm_compute;
48using namespace arm_compute::test;
49using namespace arm_compute::test::validation;
50
51namespace
52{
53/** Compute CL Harris corners function.
54 *
55 * @param[in] shape Shape of input tensor
56 * @param[in] threshold Minimum threshold with which to eliminate Harris Corner scores (computed using the normalized Sobel kernel).
57 * @param[in] min_dist Radial Euclidean distance for the euclidean distance stage
58 * @param[in] sensitivity Sensitivity threshold k from the Harris-Stephens equation
59 * @param[in] gradient_size The gradient window size to use on the input. The implementation supports 3, 5, and 7
60 * @param[in] block_size The block window size used to compute the Harris Corner score. The implementation supports 3, 5, and 7.
61 * @param[in] border_mode Border mode to use
62 * @param[in] constant_border_value Constant value to use for borders if border_mode is set to CONSTANT.
63 *
64 * @return Computed corners' keypoints.
65 */
66void compute_harris_corners(const TensorShape &shape, CLKeyPointArray &corners, float threshold, float min_dist, float sensitivity,
67 int32_t gradient_size, int32_t block_size, BorderMode border_mode, uint8_t constant_border_value)
68{
69 // Create tensors
70 CLTensor src = create_tensor<CLTensor>(shape, DataType::U8);
71 src.info()->set_format(Format::U8);
72
73 // Create harris corners configure function
74 CLHarrisCorners harris_corners;
75 harris_corners.configure(&src, threshold, min_dist, sensitivity, gradient_size, block_size, &corners, border_mode, constant_border_value);
76
77 // Allocate tensors
78 src.allocator()->allocate();
79
80 BOOST_TEST(!src.info()->is_resizable());
81
82 // Fill tensors
83 library->fill_tensor_uniform(CLAccessor(src), 0);
84
85 // Compute function
86 harris_corners.run();
87}
88} // namespace
89
90#ifndef DOXYGEN_SKIP_THIS
91BOOST_AUTO_TEST_SUITE(CL)
92BOOST_AUTO_TEST_SUITE(HarrisCorners)
93
94BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
95BOOST_DATA_TEST_CASE(Configuration, (Small2DShapes() + Large2DShapes()) * BorderModes()
96 * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }),
97 shape, border_mode, gradient, block)
98{
99 // Create tensors
100 CLTensor src = create_tensor<CLTensor>(shape, DataType::U8);
101 src.info()->set_format(Format::U8);
102
103 CLKeyPointArray corners(shape.total_size());
104
105 uint8_t constant_border_value = 0;
106
107 std::mt19937 gen(user_config.seed.get());
108 std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min());
109
110 const float threshold = real_dist(gen);
111 const float sensitivity = real_dist(gen);
112 const float max_euclidean_distance = 30.f;
113
114 real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance);
115 float min_dist = real_dist(gen);
116
117 // Generate a random constant value if border_mode is constant
118 if(border_mode == BorderMode::CONSTANT)
119 {
120 std::uniform_int_distribution<uint8_t> int_dist(0, 255);
121 constant_border_value = int_dist(gen);
122 }
123
124 BOOST_TEST(src.info()->is_resizable());
125
126 // Create harris corners configure function
127 CLHarrisCorners harris_corners;
128 harris_corners.configure(&src, threshold, min_dist, sensitivity, gradient, block, &corners, border_mode, constant_border_value);
129
130 // Validate valid region
131 const ValidRegion valid_region = shape_to_valid_region(shape);
132
133 validate(src.info()->valid_region(), valid_region);
134
135 // Validate padding
136 PaddingCalculator calculator(shape.x(), 8);
137
138 calculator.set_border_mode(border_mode);
139 calculator.set_border_size(gradient / 2);
140 calculator.set_access_offset(-gradient / 2);
141 calculator.set_accessed_elements(16);
142
143 const PaddingSize padding = calculator.required_padding();
144
145 validate(src.info()->padding(), padding);
146}
147
148BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
149BOOST_DATA_TEST_CASE(RunSmall, Small2DShapes() * BorderModes() * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), shape, border_mode, gradient, block)
150{
151 uint8_t constant_border_value = 0;
152
153 std::mt19937 gen(user_config.seed.get());
154 std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min());
155
156 const float threshold = real_dist(gen);
157 const float sensitivity = real_dist(gen);
158 const float max_euclidean_distance = 30.f;
159
160 real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance);
161 const float min_dist = real_dist(gen);
162
163 // Generate a random constant value if border_mode is constant
164 if(border_mode == BorderMode::CONSTANT)
165 {
166 std::uniform_int_distribution<uint8_t> int_dist(0, 255);
167 constant_border_value = int_dist(gen);
168 }
169
170 // Create array of keypoints
171 CLKeyPointArray dst(shape.total_size());
172
173 // Compute function
174 compute_harris_corners(shape, dst, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value);
175
176 // Compute reference
177 KeyPointArray ref_dst = Reference::compute_reference_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value);
178
179 // Validate output
180 dst.map();
Moritz Pflanzer632925a2017-08-30 09:29:47 +0100181 validate(dst, ref_dst, 1);
Giorgio Arenafc2817d2017-06-27 17:26:37 +0100182 dst.unmap();
183}
184
185BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
186BOOST_DATA_TEST_CASE(RunLarge, Large2DShapes() * BorderModes() * boost::unit_test::data::make({ 3, 5, 7 }) * boost::unit_test::data::make({ 3, 5, 7 }), shape, border_mode, gradient, block)
187{
188 uint8_t constant_border_value = 0;
189
190 std::mt19937 gen(user_config.seed.get());
191 std::uniform_real_distribution<float> real_dist(0.01, std::numeric_limits<float>::min());
192
193 const float threshold = real_dist(gen);
194 const float sensitivity = real_dist(gen);
195 const float max_euclidean_distance = 30.f;
196
197 real_dist = std::uniform_real_distribution<float>(0.f, max_euclidean_distance);
198 const float min_dist = real_dist(gen);
199
200 // Generate a random constant value if border_mode is constant
201 if(border_mode == BorderMode::CONSTANT)
202 {
203 std::uniform_int_distribution<uint8_t> int_dist(0, 255);
204 constant_border_value = int_dist(gen);
205 }
206
207 // Create array of keypoints
208 CLKeyPointArray dst(shape.total_size());
209
210 // Compute function
211 compute_harris_corners(shape, dst, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value);
212
213 // Compute reference
214 KeyPointArray ref_dst = Reference::compute_reference_harris_corners(shape, threshold, min_dist, sensitivity, gradient, block, border_mode, constant_border_value);
215
216 // Validate output
217 dst.map();
218 validate(dst, ref_dst);
219 dst.unmap();
220}
221
222BOOST_AUTO_TEST_SUITE_END()
223BOOST_AUTO_TEST_SUITE_END()
224#endif /* DOXYGEN_SKIP_THIS */