• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2018 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 #ifndef ARM_COMPUTE_TEST_OPTICAL_FLOW
25 #define ARM_COMPUTE_TEST_OPTICAL_FLOW
26 
27 #include "arm_compute/core/PyramidInfo.h"
28 #include "arm_compute/core/TensorShape.h"
29 #include "arm_compute/core/Types.h"
30 #include "tests/AssetsLibrary.h"
31 #include "tests/Globals.h"
32 #include "tests/IAccessor.h"
33 #include "tests/Types.h"
34 #include "tests/framework/Asserts.h"
35 #include "tests/framework/Fixture.h"
36 #include "tests/validation/reference/OpticalFlow.h"
37 
38 namespace arm_compute
39 {
40 namespace test
41 {
42 namespace validation
43 {
44 template <typename TensorType,
45           typename AccessorType,
46           typename ArrayType,
47           typename ArrayAccessorType,
48           typename FunctionType,
49           typename PyramidType,
50           typename PyramidFunctionType,
51           typename T>
52 
53 class OpticalFlowValidationFixture : public framework::Fixture
54 {
55 public:
56     template <typename...>
setup(std::string old_image_name,std::string new_image_name,OpticalFlowParameters params,size_t num_levels,size_t num_keypoints,Format format,BorderMode border_mode)57     void setup(std::string old_image_name, std::string new_image_name, OpticalFlowParameters params,
58                size_t num_levels, size_t num_keypoints, Format format, BorderMode border_mode)
59     {
60         std::mt19937                           gen(library->seed());
61         std::uniform_int_distribution<uint8_t> int_dist(0, 255);
62         const uint8_t                          constant_border_value = int_dist(gen);
63 
64         // Create keypoints
65         std::vector<KeyPoint> old_keypoints           = generate_random_keypoints(library->get_image_shape(old_image_name), num_keypoints, library->seed(), num_levels);
66         std::vector<KeyPoint> new_keypoints_estimates = old_keypoints;
67 
68         _target    = compute_target(old_image_name, new_image_name, params, num_levels, old_keypoints, new_keypoints_estimates, format, border_mode, constant_border_value);
69         _reference = compute_reference(old_image_name, new_image_name, params, num_levels, old_keypoints, new_keypoints_estimates, format, border_mode, constant_border_value);
70     }
71 
72 protected:
73     template <typename V>
fill(V && tensor,const std::string image,Format format)74     void fill(V &&tensor, const std::string image, Format format)
75     {
76         library->fill(tensor, image, format);
77     }
78 
compute_target(std::string old_image_name,std::string new_image_name,OpticalFlowParameters params,size_t num_levels,std::vector<KeyPoint> & old_keypoints,std::vector<KeyPoint> & new_keypoints_estimates,Format format,BorderMode border_mode,uint8_t constant_border_value)79     ArrayType compute_target(std::string old_image_name, std::string new_image_name, OpticalFlowParameters params, size_t num_levels,
80                              std::vector<KeyPoint> &old_keypoints, std::vector<KeyPoint> &new_keypoints_estimates,
81                              Format format, BorderMode border_mode, uint8_t constant_border_value)
82     {
83         // Get image shapes
84         TensorShape old_shape = library->get_image_shape(old_image_name);
85         TensorShape new_shape = library->get_image_shape(new_image_name);
86 
87         // Create tensors
88         auto old_image = create_tensor<TensorType>(old_shape, format);
89         auto new_image = create_tensor<TensorType>(new_shape, format);
90 
91         // Load keypoints
92         ArrayType old_points(old_keypoints.size());
93         ArrayType new_points_estimates(new_keypoints_estimates.size());
94         ArrayType new_points(old_keypoints.size());
95 
96         fill_array(ArrayAccessorType(old_points), old_keypoints);
97         fill_array(ArrayAccessorType(new_points_estimates), new_keypoints_estimates);
98 
99         // Create pyramid images
100         PyramidInfo pyramid_info(num_levels, SCALE_PYRAMID_HALF, old_image.info()->tensor_shape(), format);
101         PyramidType old_pyramid = create_pyramid<PyramidType>(pyramid_info);
102         PyramidType new_pyramid = create_pyramid<PyramidType>(pyramid_info);
103 
104         // Create and configure pyramid functions
105         PyramidFunctionType old_gp;
106         old_gp.configure(&old_image, &old_pyramid, border_mode, constant_border_value);
107 
108         PyramidFunctionType new_gp;
109         new_gp.configure(&new_image, &new_pyramid, border_mode, constant_border_value);
110 
111         for(size_t i = 0; i < pyramid_info.num_levels(); ++i)
112         {
113             ARM_COMPUTE_EXPECT(old_pyramid.get_pyramid_level(i)->info()->is_resizable(), framework::LogLevel::ERRORS);
114             ARM_COMPUTE_EXPECT(new_pyramid.get_pyramid_level(i)->info()->is_resizable(), framework::LogLevel::ERRORS);
115         }
116 
117         // Create and configure optical flow function
118         FunctionType optical_flow;
119 
120         optical_flow.configure(&old_pyramid,
121                                &new_pyramid,
122                                &old_points,
123                                &new_points_estimates,
124                                &new_points,
125                                params.termination,
126                                params.epsilon,
127                                params.num_iterations,
128                                params.window_dimension,
129                                params.use_initial_estimate,
130                                border_mode,
131                                constant_border_value);
132 
133         ARM_COMPUTE_EXPECT(old_image.info()->is_resizable(), framework::LogLevel::ERRORS);
134         ARM_COMPUTE_EXPECT(new_image.info()->is_resizable(), framework::LogLevel::ERRORS);
135 
136         // Allocate input tensors
137         old_image.allocator()->allocate();
138         new_image.allocator()->allocate();
139 
140         // Allocate pyramids
141         old_pyramid.allocate();
142         new_pyramid.allocate();
143 
144         ARM_COMPUTE_EXPECT(!old_image.info()->is_resizable(), framework::LogLevel::ERRORS);
145         ARM_COMPUTE_EXPECT(!new_image.info()->is_resizable(), framework::LogLevel::ERRORS);
146 
147         for(size_t i = 0; i < pyramid_info.num_levels(); ++i)
148         {
149             ARM_COMPUTE_EXPECT(!old_pyramid.get_pyramid_level(i)->info()->is_resizable(), framework::LogLevel::ERRORS);
150             ARM_COMPUTE_EXPECT(!new_pyramid.get_pyramid_level(i)->info()->is_resizable(), framework::LogLevel::ERRORS);
151         }
152 
153         // Fill tensors
154         fill(AccessorType(old_image), old_image_name, format);
155         fill(AccessorType(new_image), new_image_name, format);
156 
157         // Compute functions
158         old_gp.run();
159         new_gp.run();
160         optical_flow.run();
161 
162         return new_points;
163     }
164 
compute_reference(std::string old_image_name,std::string new_image_name,OpticalFlowParameters params,size_t num_levels,std::vector<KeyPoint> & old_keypoints,std::vector<KeyPoint> & new_keypoints_estimates,Format format,BorderMode border_mode,uint8_t constant_border_value)165     std::vector<KeyPoint> compute_reference(std::string old_image_name, std::string new_image_name,
166                                             OpticalFlowParameters params, size_t num_levels,
167                                             std::vector<KeyPoint> &old_keypoints, std::vector<KeyPoint> &new_keypoints_estimates,
168                                             Format format, BorderMode border_mode, uint8_t constant_border_value)
169     {
170         SimpleTensor<T> old_image{ library->get_image_shape(old_image_name), data_type_from_format(format) };
171         SimpleTensor<T> new_image{ library->get_image_shape(new_image_name), data_type_from_format(format) };
172 
173         fill(old_image, old_image_name, format);
174         fill(new_image, new_image_name, format);
175 
176         return reference::optical_flow<T>(old_image, new_image, params, num_levels, old_keypoints, new_keypoints_estimates,
177                                           border_mode, constant_border_value);
178     }
179 
180     ArrayType             _target{};
181     std::vector<KeyPoint> _reference{};
182 };
183 } // namespace validation
184 } // namespace test
185 } // namespace arm_compute
186 #endif /* ARM_COMPUTE_TEST_OPTICAL_FLOW */
187