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 #ifndef ARM_COMPUTE_TEST_SOBEL_FIXTURE 25 #define ARM_COMPUTE_TEST_SOBEL_FIXTURE 26 27 #include "arm_compute/core/TensorShape.h" 28 #include "arm_compute/core/Types.h" 29 #include "tests/AssetsLibrary.h" 30 #include "tests/Globals.h" 31 #include "tests/IAccessor.h" 32 #include "tests/framework/Asserts.h" 33 #include "tests/framework/Fixture.h" 34 #include "tests/validation/reference/Sobel.h" 35 36 #include <memory> 37 38 namespace arm_compute 39 { 40 class CLSobel3x3; 41 class CLSobel5x5; 42 class CLSobel7x7; 43 class NESobel3x3; 44 class NESobel5x5; 45 class NESobel7x7; 46 47 namespace test 48 { 49 namespace validation 50 { 51 namespace 52 { 53 template <typename Function> 54 struct info; 55 56 template <> 57 struct info<NESobel3x3> 58 { 59 static const Format dst_format = Format::S16; 60 static const int filter_size = 3; 61 }; 62 63 template <> 64 struct info<CLSobel3x3> 65 { 66 static const Format dst_format = Format::S16; 67 static const int filter_size = 3; 68 }; 69 70 template <> 71 struct info<NESobel5x5> 72 { 73 static const Format dst_format = Format::S16; 74 static const int filter_size = 5; 75 }; 76 77 template <> 78 struct info<CLSobel5x5> 79 { 80 static const Format dst_format = Format::S16; 81 static const int filter_size = 5; 82 }; 83 84 template <> 85 struct info<NESobel7x7> 86 { 87 static const Format dst_format = Format::S32; 88 static const int filter_size = 7; 89 }; 90 91 template <> 92 struct info<CLSobel7x7> 93 { 94 static const Format dst_format = Format::S32; 95 static const int filter_size = 7; 96 }; 97 } // namespace 98 99 template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename U> 100 class SobelValidationFixture : public framework::Fixture 101 { 102 public: 103 template <typename...> 104 void setup(TensorShape shape, BorderMode border_mode, Format format, GradientDimension gradient_dimension) 105 { 106 // Generate a random constant value 107 std::mt19937 gen(library->seed()); 108 std::uniform_int_distribution<uint8_t> int_dist(0, 255); 109 const uint8_t constant_border_value = int_dist(gen); 110 111 _border_mode = border_mode; 112 _target = compute_target(shape, border_mode, format, constant_border_value, gradient_dimension); 113 _reference = compute_reference(shape, info<FunctionType>::filter_size, border_mode, format, constant_border_value, gradient_dimension); 114 } 115 116 protected: 117 template <typename V> 118 void fill(V &&tensor) 119 { 120 library->fill_tensor_uniform(tensor, 0); 121 } 122 123 std::pair<TensorType, TensorType> compute_target(const TensorShape &shape, BorderMode border_mode, Format format, uint8_t constant_border_value, GradientDimension gradient_dimension) 124 { 125 // Create tensors 126 TensorType src = create_tensor<TensorType>(shape, data_type_from_format(format)); 127 TensorType dst_x = create_tensor<TensorType>(shape, data_type_from_format(info<FunctionType>::dst_format)); 128 TensorType dst_y = create_tensor<TensorType>(shape, data_type_from_format(info<FunctionType>::dst_format)); 129 130 src.info()->set_format(format); 131 dst_x.info()->set_format(info<FunctionType>::dst_format); 132 dst_y.info()->set_format(info<FunctionType>::dst_format); 133 134 FunctionType sobel; 135 136 switch(gradient_dimension) 137 { 138 case GradientDimension::GRAD_X: 139 sobel.configure(&src, &dst_x, nullptr, border_mode, constant_border_value); 140 break; 141 case GradientDimension::GRAD_Y: 142 sobel.configure(&src, nullptr, &dst_y, border_mode, constant_border_value); 143 break; 144 case GradientDimension::GRAD_XY: 145 sobel.configure(&src, &dst_x, &dst_y, border_mode, constant_border_value); 146 break; 147 default: 148 ARM_COMPUTE_ERROR("Gradient dimension not supported"); 149 } 150 151 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); 152 ARM_COMPUTE_EXPECT(dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); 153 ARM_COMPUTE_EXPECT(dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); 154 155 // Allocate tensors 156 src.allocator()->allocate(); 157 dst_x.allocator()->allocate(); 158 dst_y.allocator()->allocate(); 159 160 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS); 161 ARM_COMPUTE_EXPECT(!dst_x.info()->is_resizable(), framework::LogLevel::ERRORS); 162 ARM_COMPUTE_EXPECT(!dst_y.info()->is_resizable(), framework::LogLevel::ERRORS); 163 164 // Fill tensors 165 fill(AccessorType(src)); 166 167 // Compute function 168 sobel.run(); 169 170 return std::make_pair(std::move(dst_x), std::move(dst_y)); 171 } 172 173 std::pair<SimpleTensor<U>, SimpleTensor<U>> compute_reference(const TensorShape &shape, int filter_size, BorderMode border_mode, Format format, uint8_t constant_border_value, 174 GradientDimension gradient_dimension) 175 { 176 // Create reference 177 SimpleTensor<T> src{ shape, format }; 178 179 // Fill reference 180 fill(src); 181 182 return reference::sobel<U>(src, filter_size, border_mode, constant_border_value, gradient_dimension); 183 } 184 185 BorderMode _border_mode{ BorderMode::UNDEFINED }; 186 std::pair<TensorType, TensorType> _target{}; 187 std::pair<SimpleTensor<U>, SimpleTensor<U>> _reference{}; 188 }; 189 } // namespace validation 190 } // namespace test 191 } // namespace arm_compute 192 #endif /* ARM_COMPUTE_TEST_SOBEL_FIXTURE */ 193